Skocz do zawartości

Dodatkowe ćwiczenia z wyświetlaczem 2x16 znaków


Pomocna odpowiedź

Gość
11 minut temu, ethanak napisał:

Przecież pisałem - to są sprzętowe timery a nie kawałki programu. I timer raz uruchomiony będzie liczył niezależnie od tego co procesor wyprawia.

Tak, tak. Miałem na myśli to w jaki sposób wykonać działanie/ działania if aby w ich pętlach nie uciekały ms. Jak widzisz nawet jeżeli zastosujesz kompensację czasu pętli, to pomiędzy tym działaniem, a kolejnym if w którym operujesz wartościami czasu zdążą uciec ms, co powoduje odchyłki. Trzeba zrobić takie działanie które bez kompensacji będzie prawidłowo obliczać czas w odniesieniu do stanu licznika, będące niewrażliwym na błąd wprowadzany poprzez czas wykonywanej pętli. Na pierwszy rzut oka nie jest to takie proste, no ale w PLC musieli jakoś to rozwiązać i zamknąć kod w bloczku o nazwie timer. Taki kod warto sobie zapisać w notatniku aby więcej się nad nim nie zastanawiać, tylko podstawiać zmienne do potrzeby. 

Ale ja nie bardzo rozumiem gdzie szukasz dziury. Odczytujesz wartość millis(), odejmujesz wartość uzyskaną przy starcie stopera a potem możesz to nawet narysować. Gdzie widzisz jakąś niedokładność?

I nie wspominaj więcej o PLC bo ma tyle samo wspólnego z programowaniem Arduino co gra na fortepianie (trzeba mianowicie naciskać odpowiednie klawisze w odpowiedniej kolejności). 🙂

Gość
13 minut temu, ethanak napisał:

Ale ja nie bardzo rozumiem gdzie szukasz dziury. Odczytujesz wartość millis(), odejmujesz wartość uzyskaną przy starcie stopera a

No ale takie działanie da tylko tyle, że wystartujesz licznik od wartości zerowej odniesienia, a licznik nadal będzie lecieć w kierunku przepełnienia unigned long. Jeżeli na wyświetlaczu chcesz odświeżać jedynie same ms, to będzie to działać. Problem z ulotem ms zaczyna się w momencie konwersji ms na sekundy, bo właśnie wtedy program gubi ms.  

Gość
25 minut temu, ethanak napisał:

Odczytujesz wartość millis(), odejmujesz wartość uzyskaną przy starcie stopera

P.S. To o czym piszesz pierwotnie jest w moim kodzie;

if (sw1 == 1) {t1 = TT - t0;}     
else {t0 = TT - t1; sw2 = 0;}   // Stoper start

if (sw2 == 1) {sw1 = 0;}  // Stoper stop

else if (sw3 == 0) {sw1 = 0; sw2 = 0; t2 = t1 + 999; // stoper reset
t3 = 0; t4 = 0; t5 = 0; t6 = 0;} 

Tyle że masz możliwość start i stop. Ale nie w tym miejscu giną ms.

(edytowany)
44 minuty temu, rafal220 napisał:
if (sw1 == 1) {t1 = TT - t0;}     
else {t0 = TT - t1; sw2 = 0;}   // Stoper start

if (sw2 == 1) {sw1 = 0;}  // Stoper stop

else if (sw3 == 0) {sw1 = 0; sw2 = 0; t2 = t1 + 999; // stoper reset
t3 = 0; t4 = 0; t5 = 0; t6 = 0;} 

Grunt do dobre nazywanie zmiennych... XD

 

Moje podejście wyglądałoby m/w tak:

#include "stdio.h"
#include "inttypes.h"

#define TIMER_STOPPED 0
#define TIMER_RUNNING 1
#define MS_TO_S_MULTIPLIER 0.001f
  
struct timer_t
{
    uint32_t startTime;
    uint32_t endTime;
    uint8_t isRunning;
};

struct timer_t timer1;
struct timer_t timer2;

// Placeholder for Arduino.h::millis()
uint32_t millis()
{
    return 0;
}

float get_seconds(const struct timer_t * timer)
{
    return (timer->endTime - timer->startTime) * MS_TO_S_MULTIPLIER;
}

void start_timer(struct timer_t* timer)
{
    timer->isRunning = TIMER_RUNNING;
    timer->startTime = millis();    
}

void stop_timer(struct timer_t* timer) {
    timer->endTime = millis();
    timer->isRunning = TIMER_STOPPED;
}

int main(void) {

    start_timer(&timer1);
    start_timer(&timer2);
    // Do some expensive operations
    stop_timer(&timer1);
    // Do some more expensive operations
    stop_timer(&timer2);

    // Print times
    printf("It took [Timer %d]: %f", 1, get_seconds(&timer1));
    printf("It took [Timer %d]: %f", 2, get_seconds(&timer2));

    return 0;
}

Notatka: może nie działać, nie testowałem, pisane na kolanie 😉 

Prawidłowo funkcje powinny mieć jeszcze wymuszenie kompilacji w trybie inline i działać bez wskaźników by być optymalnie szybkie... Ale to już sporo zabawy i nie pamiętam czy dostęp przez wskaźnik czy referencję był szybszy...

Edytowano przez H1M4W4R1

Wybacz szczerość, ale g... gubi. Sekundy wyświetlasz, ale czas cały czas przechowujesz w milisekundach (czy mikrosekundach na innych platformach). A podzielenie czegoś przez 1000 nie powinno być problemem nawet dla programistów Lego.

A co do przepełnienia... licznik milisekund przekręci się po coś ponad dwóch miesiącach, a nawet jeśli to przy unsigned nie ma to zadnego znaczenia.

A jak się boisz przepełnienia to przejdź na RPi Pico i SDK C - 64-bitowy licznik mikrosekund nie ma szans się przekręcić przed śmiercią cieplną Wszechświata.

Gość
10 minut temu, ethanak napisał:

A podzielenie czegoś przez 1000 nie powinno być problemem nawet dla programistów Lego.

Czyli dokładnie tak samo jak w PLC. tam też robisz dwa działania dzielenia. Jedno aby uzyskać setne, a drugie sekundy. Ja na razie eksperymentuję (skoro mam większe możliwości niż na PLC). Chcę sprawdzić czy da się zrobić programową kompensację czasu pętli. Wiadomo że w dzieleniu zawsze z automatu wytniesz niepodzielną wartość z liczby i jest to najprostszy sposób. 

Mozesz nam wszystkim zrobić przyjemnośc, wstac od kompa, pójść na jakieś piwo, jak zdrowie nie pozwala to na spacer, jak na to też nie to obejrzyj sobie jakiś serial na Netfliksie, a w razie czego służyłbym listą seriali z audiodeskrypcją.

Uparłeś się na kompensację czegoś, co normalnie nie istnieje a  w Twoim przypadku jest jedynie wynikiem błędu w programie.

Nie chce mi się sprawdzać gdzie mieszkasz ale jeśli blisko to jestem w Torino.

Gość
28 minut temu, ethanak napisał:

Wybacz szczerość, ale g... gubi. Sekundy wyświetlasz, ale czas cały czas przechowujesz w milisekundach

No właśnie wygląda na to, że sposób z kompensacją czasu pętli też powinien działać poprawnie, ponieważ w przypadku dzielenia przez 1000 po 5 min zegar tak samo zaczyna późnić się o 1s. Chyba faktycznie rezonator w tym egzemplarzu jest lichej jakości. W sumie płytka za kilka zł.  Szukam problemu którego nie ma w kodzie. Ponadto czas pomiędzy linijką z kompensującą czas pętli, a kolejną będzie poniżej 1ms.  Obydwa sposoby są dobre. Jakoś nie przyszło mi do głowy aby poprzez działanie dzielenia od razu sprawdzić dokładność rezonatora. Po umiarkowanym piwie to się fajnie dłubie przy elektronice. Podwyższona endorfina dobrze służy. A tak to zamuł dziwnie blokuje myślenie. 

Gość
11 minut temu, ethanak napisał:

Nie chce mi się sprawdzać gdzie mieszkasz ale jeśli blisko to jestem w Torino.

P.S. 

Trudno jest sprawdzić lokalizację poprzez wyszukiwarkę. No chyba że Arduino IDE ma na pokładzie jakieś bonusy o których nie wiem 😉 

1) spróbuj wreszcie normalnego kodu (czyli odczytania różnicy między aktualną wartością millis() a wartością odczytaną w przerwaniu od klawisza start). Potem sprawdź czy się zgadza z czasem rzeczywistym. A w międzyczasie wyświetlaj sobie co chcesz (aby czas zajmowało).

2) zawsze możesz zapytać 🙂

Gość
42 minuty temu, ethanak napisał:

1) spróbuj wreszcie normalnego kodu (czyli odczytania różnicy między aktualną wartością millis() a wartością odczytaną w przerwaniu od klawisza start). Potem sprawdź czy się zgadza z czasem rzeczywistym. A w międzyczasie wyświetlaj sobie co chcesz (aby czas zajmowało)

Wszystko się zgadza. Przerobię dla zasady ten istniejący kod, ale już wiem że nie wyeliminuje to opóźnienia zegara ponieważ w tym przypadku na 99% jest to wina rezonatora. Skoro na czysto wyprowadzam sekundy na wyświetlacz dzieląc TT / 1000, to wiadomo że nic innego nie może być. Tak swoją drogą, to po raz pierwszy mam do czynienia z tak mocną odchyłką rezonatora 16MHz. Nie ma jak to własne sprawdzone kwarce, a nie to co tam producent wstawił na PCB. Zresztą mega328 też pewnie podrobiona, no bo nigdzie nie kupisz za 6zł Arduino nano. No ale do zabawy przy piwku w sam raz. Nawet jak coś fizycznie schrzanisz, to mała strata, aczkolwiek mocno staram się tego unikać. Na razie poznawanie Arduino idzie bez negatywnych skutków finansowych. 

(edytowany)

Masz oryginalł Arduino czy klona?

Ok, nie doczytałem. Chińskie 16 MHz to tak coś między 15.5 a 16.5)

Jak chcesz się poważnie bawić to kup sobie ESP32 DevKit. Najlepiej polskiego klona 30 pinów. 

Edytowano przez ethanak

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...