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!