między zdarzeni

Do tej pory nie potrzebowałem jednoczesnego odmierzania kilku różnych wartości, w związku z czym timerów w Atmedze8 wystarczało do moich zastosowań. Mogłem sobie pozwolić na zaangażowanie konkretnego licznika do konkretnego zadania i resetowanie go wedle upodobań. Nie zawsze jednak tak się da...

W Arduino jest taka funkcja jak millis(), która zwraca ilość milisekund jakie upłynęły od uruchomienia układu. Wartość przechowywana w long int, wystarczy na trochę mniej niż 50 dni. Gdy zachodzi konieczność podjęcia jakiejś akcji w określonym czasie od jakiegoś zdarzenia wystarczy przepisać aktualną wartość do zmiennej, a potem sprawdzać jak różnica miedzy wartością aktualną a zapisaną ma się do żądanego interwału.

Zastanawia mnie tylko jedna kwestia. Jakie mogą być skutki ewentualnego przepełnienia zmiennej i rozpoczęcia odliczania od nowa? Można sobie wyobrazić, że urządzenie pracujące cały czas będzie miało taki uptime. Można jakoś bronić się przed taką sytuacją?

Reply to
Atlantis
Loading thread data ...

Atlantis snipped-for-privacy@wp.pl napisał(a): [wycinam, bo tak naprawdę brak związku między pytaniem a AVR, Arduino :) ]

  1. Miej jakieś zdarzenie generowane z częstotliwością większą niż przepełnienia tego licznika. Zapamiętuj w nim wartość zwróconą przez milis(). Jak będzie niższa niż ostatnio, będziesz wiedział, że upłynął okres tego licznika.
  2. Użyj RTC z podtrzymywaniem bateryjnym. Mała inwestycja a życie stanie się prostsze a niezawodność większa.
Reply to
Grzegorz Niemirowski

W dniu 2013-09-24 23:26, Grzegorz Niemirowski pisze:

Hmm... Na dobrą sprawę przecież mogę to zrobić w przerwaniu przepełnienia tego licznika. Tak czy inaczej będzie tam instrukcja warunkowa sprawdzająca czy zmienna osiągnęła swoją maksymalną wartość i resetująca ją. Równie dobrze można wtedy postawić flagę.

Reply to
Atlantis

Tak swoją drogą nie mogę się doszukać informacji na temat czasu, jaki zajmuje takiej Atmedze8 wyjście z idle mode. Czy przy przerwaniu wywoływanym co 1 ms (do tego dochodzą jeszcze przerwania od USART, INT0 albo INT1) usypianie MCU po każdej iteracji pętli głównej ma sens?

Reply to
Atlantis

Atlantis snipped-for-privacy@wp.pl napisał(a):

Trudno powiedzieć, bo nie podałeś ile czasu MCU spędza w tych przerwaniach. A po co usypiasz? Masz zasilanie bateryjne? Może po prostu zmierz pobór prądu z usypianiem i bez.

Reply to
Grzegorz Niemirowski

W dniu 2013-09-25 00:33, Grzegorz Niemirowski pisze:

Trudno powiedzieć. Jednak staram się, żeby w przerwaniach nie było zbyt rozbudowanych instrukcji, oczywiście nigdy nie używam funkcji opóźniającej (ani niczego co ją wykorzystuje) w procedurze obsługi przerwania.

Tak, chodzi o urządzenia zasilane z baterii/akumulatorka.

Reply to
Atlantis

W dniu 24.09.2013 23:14, Atlantis pisze:

Nie ma po co się bronić. Jeśli nie posługujesz się wartością bezwzględną licznika, tylko różnicą wskazań to spokojnie możesz mierzyć przedziały mniejsze niż te 50 dni (niezależnie czy licznik się w tym czasie przekręci, czy nie). Wystarczy sprawdzić kilka przypadków na palcach:

- stan początkowy licznika: 00000000h, końcowy: 00000200h, różnica 200h

- stan początkowy licznika: FFFFFF00h, końcowy: 00000100h, różnica 200h

Reply to
Zbych

W dniu 2013-09-25 16:10, Zbych pisze:

Czekaj, coś mi tu nie pasuje...

Dla ułatwienia unsigned short int, wartości zapisane systemem dziesiętnym.

prevMillis = 65000 (czas zapisany przy rozpoczęciu pomiaru) millis = 65200 (obecny czas) millis-prevMillis = 200 (czas trwania mierzonego zjawiska, wszystko się zgadza)

I w przypadku przekręcenia licznika: prevMillis=65435 (czas zapisany na chwilę przed przekręceniem licznika) millis=100 (obecny czas, już po przekręceniu licznika) millis-prevMillis = -65335

Zdecydowanie nie jest to jedno i to samo. ;)

W przypadku signed short int: prevMillis = 32667 millis = -32668 millis-prevMillis = -65335

Reply to
Atlantis

Atlantis snipped-for-privacy@wp.pl napisał(a):

Jak unsigned to skąd znak?

Reply to
Grzegorz Niemirowski

W dniu 2013-09-25 20:42, Grzegorz Niemirowski pisze:

Hmm... Tego nie wziąłem pod uwagę. Jak w takim razie zachowa się program w poniższym przypadku?

unsigned int zmienna1 = 4000 unsigned int zmienna2 = 5000 unsigned int zmienna3 = 200

if (zmienna1-zmienna2 > zmienna3) { //instrukcje do wykonania }

Innymi słowy: do jakiego typu zmiennej zostanie podstawiony wynik odejmowania i co nim będzie? ;)

Reply to
Atlantis

W dniu 25.09.2013 18:52, Atlantis pisze:

Masz braki w znajomości sposobów reprezentacji liczb w systemach cyfrowych. Poczytaj sobie do poduszki na temat U2.

int main(int argc, const char *argv[]) { unsigned short start = 65435; unsigned short stop = 100; printf("start: %u, stop %u, delta %u\n", start, stop, (unsigned short)(stop-start)); return 0; }

Wynik: start: 65435, stop 100, delta 201

int main(int argc, const char *argv[]) { short start = 32667; short stop = -32668; printf("start: %d, stop %d, delta %u", start, stop, (unsigned short)(stop-start)); return 0; }

Wynik: start: 32667, stop -32668, delta 201

Reply to
Zbych

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.