Samouczek Arduino: używanie millis () zamiast delay()

dobrze znaną funkcją Arduino jest delay(), która zatrzymuje program na ilość milisekund określoną jako parametr.

millis(), z drugiej strony, jest funkcją, która zwraca ilość milisekund, które minęły od uruchomienia programu.

na pierwszy rzut oka możesz wątpić w przydatność tej funkcji. Faktem jest, że jest niezwykle przydatny w wielu scenariuszach, często całkowicie „zastępując” delay(). Przyjrzyjmy się najpierw, jak możemy użyć millis() prawie dokładnie tak, jak delay().

problemy z czasem są często obecne w programowaniu.

używanie millis () jak delay()

int period = 1000;unsigned long time_now = 0;void setup() {Serial.begin(115200);}void loop() {time_now = millis(); Serial.println("Hello"); while(millis() < time_now + period){//wait approx. ms}}

jeśli chcesz, aby Twój kod zatrzymał się na 1000 ms na końcu każdej iteracji pętli, powyższy kod jest nieco głupi. Możesz zamiast tego użyć delay(1000). Jedyną różnicą między powyższym kodem a kodem z delay(1000) na końcu jest to, że pętla w powyższym kodzie będzie działać dość dokładnie raz na sekundę. Pętla w kodzie z delay(1000)będzie działać nieco rzadziej, ponieważ wykonanie Serial.println("Hello") również zajmuje trochę czasu.

dlaczego warto używać millis () zamiast delay()?

przyjrzymy się teraz dwóm zaletom z millis()w porównaniu do delay().

dokładny czas

pierwszą zaletą, którą omówimy, jest dokładny czas. Pod względem kodu omówiliśmy to w ostatnim rozdziale. Z millis() możemy zapewnić, że pętla będzie działać tak często, jak chcemy, bez względu na czas wykonania (oczywiście o ile czas wykonania jest krótszy niż żądany okres). W przypadku delay() nie jest to możliwe, ponieważ nie wiemy, jak długi jest czas wykonania pętli.

dokładny czas, taki jak ten, jest bardzo przydatny między innymi podczas próbkowania z określoną częstotliwością lub uruchomionych filtrów.

Non-blocking

inną zaletą millis() jest to, że nie uniemożliwi nam uruchamiania kodu podczas „oczekiwania”.

powiedzmy, że chcemy wydrukować „Hello” przez serial raz na sekundę podczas robienia innych rzeczy w międzyczasie. Nie jest to możliwe w przypadku delay(), ponieważ wstrzymuje cały kod. Oto jeden sposób, w jaki możemy to zrobić:

int period = 1000;unsigned long time_now = 0;void setup() {Serial.begin(115200);}void loop() {if(millis() >= time_now + period){time_now += period;Serial.println("Hello");} //Run other code}

ten fragment kodu jest dość podobny do pierwszego kawałka, z tą różnicą, że nie blokuje reszty programu, gdy nie drukuje przez serial.

przykład: prosty harmonogram

napiszmy prosty przykład, w którym tworzymy harmonogram, który drukuje pewne fragmenty tekstu w różnych odstępach czasu.

#define INTERVAL_MESSAGE1 5000#define INTERVAL_MESSAGE2 7000#define INTERVAL_MESSAGE3 11000#define INTERVAL_MESSAGE4 13000unsigned long time_1 = 0;unsigned long time_2 = 0;unsigned long time_3 = 0;unsigned long time_4 = 0;void print_time(unsigned long time_millis);void setup() {Serial.begin(115200);}void loop() {if(millis() >= time_1 + INTERVAL_MESSAGE1){time_1 +=INTERVAL_MESSAGE1;print_time(time_1);Serial.println("I'm message number one!");} if(millis() >= time_2 + INTERVAL_MESSAGE2){time_2 +=INTERVAL_MESSAGE2;print_time(time_2);Serial.println("Hello, I'm the second message.");} if(millis() >= time_3 + INTERVAL_MESSAGE3){time_3 +=INTERVAL_MESSAGE3;print_time(time_3);Serial.println("My name is Message the third.");} if(millis() >= time_4 + INTERVAL_MESSAGE4){time_4 += INTERVAL_MESSAGE4;print_time(time_4);Serial.println("Message four is in the house!");}}void print_time(unsigned long time_millis){Serial.print("Time: ");Serial.print(time_millis/1000);Serial.print("s - ");}

oto jak wygląda pierwsze 60 sekund w monitorze szeregowym:

jest to miły i łatwy sposób na synchronizację egzekucji w kodzie. Możesz również uruchomić inny kod jednocześnie.

micros() i przepełnienie

tak jak delay() ma wersję mikrosekundową o nazwie delayMicroseconds(), millis()ma micros(). Jeśli potrzebujesz lepszej rozdzielczości, micros() może być drogą do zrobienia.

należy jednak pamiętać, że micros() przepełni się po około 70 minutach, w porównaniu do millis()50 dni. Oznacza to, że wartości zwracane przez funkcje zaczną się od zera.

co ważniejsze: aby dowiedzieć się, jak można uniknąć problemu przepełnienia, przeczytaj ten post na blogu.

podsumowanie

millis() i micros() są naprawdę przydatnymi funkcjami do użycia podczas radzenia sobie z zadaniami czasowymi. Jeśli nie jesteś tego świadomy, możesz zamiast tego użyć delay(), co nie zawsze będzie działać tak dobrze (jeśli w ogóle).

aby uzyskać więcej porad Arduino & trików, sprawdź naszą kategorię Blog Arduino Tutorials. Wypatrujcie kolejnych treści związanych z Arduino także w przyszłości!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.