opóźnienie Arduino [Tutorial]

w tym samouczku dowiesz się, jak prawidłowo korzystać z funkcji delay(), aby dodać opóźnienie między działaniami 2 w programach Arduino. Następnie odkryjesz, dlaczego używanie delay() często nie jest dobrym pomysłem, gdy chcesz skalować swoje programy i jak to naprawić.

dobra, zaczynajmy!

spis treści

dlaczego potrzebujesz opóźnień w programach Arduino?

Cóż, program Arduino opiera się w dużej mierze na zewnętrznych wejściach/wyjściach do pracy.

biorąc prosty przykład: możesz monitorować stan przycisku 100 razy na sekundę lub migać DIODĄ LED co 0,5 sekundy.

jak można to osiągnąć? Programy Arduino działają tak:

  • najpierw funkcja setup() jest wykonywana raz.
  • następnie loop() funkcja jest wykonywana w kółko, dopóki nie wyłączysz swojego Arduino.

każdy program, który napiszesz, zostanie uruchomiony z pełną prędkością. Jeśli więc w kodzie mruga DIODA LED, stanie się tak, że dioda będzie migać z bardzo wysoką szybkością (co najmniej kilka tysięcy razy na sekundę).

uczysz się używać Arduino do budowania własnych projektów?

Sprawdź Arduino dla początkujących i ucz się krok po kroku.

jeśli chcesz kontrolować czas-to znaczy upewnij się, że dioda LED miga tylko co 0,5 sekundy, a nie z pełną prędkością – musisz dodać pewne opóźnienie w kodzie.

implementacja opóźnienia Arduino w kodzie

funkcja opóźnienia Arduino ()

oto kod, aby migać DIODĄ LED (tutaj wybieramy wbudowaną diodę LED, nie trzeba dodawać żadnych zewnętrznych diod LED) co 0,5 sekundy-jest to jeden z najczęstszych przykładów, które zobaczysz, jeśli zaczniesz od Arduino.

#define LED_PIN 13void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { digitalWrite(LED_PIN, HIGH); delay(500); digitalWrite(LED_PIN, LOW); delay(500);}

jak działa ten kod?

najpierw używasz „define”, więc nie musisz wielokrotnie kodować liczby” 13 ” w kodzie, co sprawia, że twój program jest bardziej czytelny.

ustawiasz tryb pinu do wyjścia za pomocą funkcji pinMode().

następnie, w funkcji loop(), można:

  1. Włącz diodę LED
  2. użyj delay(500), aby program usypiał przez 500 milisekund, lub 0,5 sekundy
  3. Wyłącz diodę LED
  4. użyj delay(500), aby program ponownie usypiał przez 0,5 sekundy
  5. i wróć do kroku 1, Ponieważ funkcja loop() wciąż jest wykonywana.

funkcja delay() oczekuje, że podasz liczbę milisekund – a nie sekund – na sen. Tak więc, jeśli pomyślisz w sekundach, pomnóż liczbę przez 1000 i masz potrzebną wartość.

zrób opóźnienie Arduino na 1 minutę

jeśli chcesz, aby Arduino spało przez 1 minutę lub przez wiele minut, jest to dość łatwe.

weź liczbę minut, pomnóż ją przez 60, aby uzyskać liczbę sekund, a następnie pomnóż przez 1000, aby uzyskać liczbę milisekund.

Ex: delay(3 * 60 * 1000); spowoduje, że program uśpi na 3 minuty.

funkcja Arduino delayMicroseconds ()

jeśli chcesz być bardziej precyzyjny, być może będziesz musiał użyć funkcji delayMicroseconds(). Z delayMicroseconds() możesz zapewnić kilka mikrosekund do uśpienia. Minimalny czas trwania delay() wynosi 1 milisekundę, więc jeśli chcesz spać tylko przez 400 mikrosekund, tutaj masz nowe rozwiązanie.

ta funkcja może być bardzo przydatna podczas komunikacji z niektórymi komponentami sprzętowymi. Na przykład Arduino musi wysłać niektóre dane do komponentu, a następnie odczytać odpowiedź. Załóżmy, że komponent potrzebuje 6 mikrosekund, aby przetworzyć żądanie i dostarczyć dokładne dane.

wtedy w swoim programie możesz mieć coś takiego:

...void loop() { // send data to component delayMicroseconds(6); // reach out to component again to read data}

Non blocking delay – dlaczego powinieneś unikać używania delay ()

więc teraz, gdy rozumiesz, co to jest opóźnienie w Arduino i jak je zaimplementować za pomocą delay() i delayMicroseconds(), zobaczmy, jak korzystać z funkcji opóźnienia – ale bez tych funkcji.

dlaczego?

gdy używasz delay(), wykonywanie programu zostanie zatrzymane i wznowione dopiero po zakończeniu opóźnienia.

to jest OK, jeśli masz tylko jedną akcję do zrobienia-przykład: mrugnij pojedynczą DIODĄ LED-ale co, jeśli musisz zadbać o wiele komponentów sprzętowych lub komunikować się z innymi urządzeniami, takimi jak płyty Arduino lub własny komputer?

korzystając z poprzedniego przykładu, jak można sprawić, że jedna dioda LED mruga co 0,5 sekundy, a druga co 0,8 sekundy?

w takim przypadku utkniesz dość szybko. Jeśli nadal chcesz używać delay(), możesz znaleźć rozwiązanie, w którym używasz krótszych opóźnień między wieloma akcjami, ale to sprawi, że twój program będzie bardziej skomplikowany za każdym razem, gdy dodasz nową akcję.

rozwiązaniem jest po prostu monitorowanie czasu bez użycia funkcji delay(), zasadniczo w celu znalezienia sposobu na odtworzenie zachowania delay() bez użycia go.

przykład kodu – Arduino delay without delay ()

przepisajmy nasz przykład blink LED bez użycia delay().

#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); if (timeNow - lastTimeLedBlinked > delayBetweenBlink) { if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState); lastTimeLedBlinked = timeNow; }}

przeanalizujmy ten kod linia po linii.

Inicjalizacja

#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;

najpierw inicjujesz 3 zmienne w globalnym zakresie:

  • lastTimeLedBlinked: ta zmienna będzie używana do przechowywania ostatniego migotania diody LED. Zasadniczo za każdym razem, gdy dioda LED zacznie migać, zaktualizujemy tę zmienną o bieżący czas-używając funkcji Milis ().
  • delayBetweenBlink: jest to czas, w którym chcesz czekać między 2 akcjami – tutaj akcją jest mrugnięcie DIODĄ LED.
  • ledState: będziemy musieli przechowywać aktualny stan Diody LED (wysoki lub niski), abyśmy mogli wiedzieć, jaki był poprzedni stan i podjąć odpowiednie działania.

dlaczego w skali globalnej? Cóż, planujemy zaktualizować te zmienne w funkcji loop() i uzyskać do nich dostęp następnym razem, gdy wejdziemy do loop(). Jeśli utworzymy zmienne wewnątrz loop(), będą to zmienne lokalne i zostaną zniszczone po wyjściu z funkcji loop(). Tak więc, przy następnym wywołaniu loop() wszystkie wartości zostaną utracone i ponownie utworzysz zmienne bez poprzedniej wartości w środku. Tutaj, tworząc zmienne poza funkcją, możemy sprawić, że „przetrwają” i zachowają swoją wartość za każdym razem, gdy wejdziemy do loop().

implementacja funkcji opóźnienia Arduino w funkcji pętli

teraz zobaczmy, co dzieje się w funkcji loop().

void loop() { unsigned int timeNow = millis();

najpierw odczytujesz aktualny czas za pomocą funkcji millis().

 if (timeNow - lastTimeLedBlinked > delayBetweenBlink) {

a teraz porównujesz aktualny czas, który właśnie przeczytałeś, z poprzednim czasem dioda mignęła. Jeżeli minęło wystarczająco dużo czasu (więcej niż wartość zapisana w delayBetweenBlink), wtedy oznacza to, że można wprowadzić if().

ta struktura kodu – odczytywanie czasu i porównywanie go z poprzednim czasem, w którym wykonałeś akcję – jest sposobem zastąpienia funkcji delay(). Po prostu obliczasz czas trwania. I jak widzisz, oznacza to, że twój program zawiera więcej linii dla prostej aplikacji, ale daje Ci znacznie większą kontrolę i jest znacznie bardziej skalowalny.

co się stanie? Cóż, loop() będzie nadal wykonywany z pełną prędkością. Za każdym razem twój program sprawdzi, czy minęło wystarczająco dużo czasu. Jeśli nie, to loop() kończy się tutaj, ponieważ nie wejdzie do struktury if.

i gdy upłynie wystarczająco dużo czasu, wchodzimy do if().

wykonywanie akcji

 if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState);

ok, właśnie wszedłeś do akcji if() i tutaj zrobisz wszystko, co musisz zrobić.

tutaj LED mruga. A ponieważ nie możemy bezpośrednio wiedzieć, jaki był poprzedni stan dla diody LED (ponieważ wiele razy weszliśmy do loop() i straciliśmy wszystkie zmienne lokalne utworzone wewnątrz), otrzymujemy ten stan ze zmiennej globalnej.

to, co robimy z tą zmienną globalną, jest proste: jeśli była niska, ustawiamy ją na wysoką, a jeśli była wysoka, ustawiamy ją na niską. A następnie, oczywiście, odpowiednio aktualizujemy stan fizycznej diody LED, za pomocą digitalWrite().

 lastTimeLedBlinked = timeNow; }}

wreszcie, i to jest bardzo ważne, zapisujemy aktualny czas jako ostatni raz, gdy mrugnęliśmy diodę LED. Jeśli tego nie zrobimy, program zacznie migać DIODĄ LED z pełną prędkością, ponieważ warunek wewnątrz if() zawsze będzie prawdziwy.

ustawiając poprzedni czas na bieżący czas „resetujemy timer”.

Tak więc w tym przykładzie wartość if() będzie wprowadzana tylko co 500 milisekund, czyli 0,5 sekundy.

a teraz to jest świetne, ponieważ twój program się nie zatrzymuje, więc możesz nadal wykonywać różne niezależne akcje, wciąż „czekając” na mrugnięcie diody LED.

2 akcje „w tym samym czasie”

na przykład, powiedzmy, że chcesz migać DIODĄ LED co 0.5 sekund, a kolejne co 0,8 sekundy.

#define LED_1_PIN 13#define LED_2_PIN 10unsigned int lastTimeLed1Blinked = millis();unsigned int delayBetweenBlink1 = 500;byte led1State = LOW;unsigned int lastTimeLed2Blinked = millis();unsigned int delayBetweenBlink2 = 800;byte led2State = LOW;void setup() { pinMode(LED_1_PIN, OUTPUT); pinMode(LED_2_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); // Action 1 - Blink LED 1 if (timeNow - lastTimeLed1Blinked > delayBetweenBlink1) { if (led1State == LOW) { led1State = HIGH; } else { led1State = LOW; } digitalWrite(LED_1_PIN, led1State); lastTimeLed1Blinked = timeNow; } // Action 2 - Blink LED 2 if (timeNow - lastTimeLed2Blinked > delayBetweenBlink2) { if (led2State == LOW) { led2State = HIGH; } else { led2State = LOW; } digitalWrite(LED_2_PIN, led2State); lastTimeLed2Blinked = timeNow; }}

jak widzisz, powtarzamy strukturę kodu dla drugiej akcji, którą dodaliśmy. I obie akcje nie będą sobie przeszkadzać!

Podsumuj

jeśli chcesz zrobić opóźnienie Arduino bez użycia delay():

  1. Utwórz zmienną globalną, która będzie przechowywać ostatni raz, gdy wykonałeś określoną akcję.
  2. utwórz kolejną zmienną globalną, aby przechowywać żądany czas między 2 działaniami.
  3. w funkcji loop() odczytaj aktualny czas za pomocą millis().
  4. zaraz po tym użyj struktury if I użyj warunku (timeNow - lastTimeActionWasExecuted > delayBetweenActions).
  5. po wejściu do if() wykonaj akcję.
  6. i nadal w if(), Zapisz bieżący czas jako poprzedni czas.

możesz powtórzyć te kroki dla każdej akcji, dla której potrzebujesz opóźnienia Arduino.

kiedy można użyć delay () i delayMicroseconds ()

istnieją szczególne okazje, gdy użycie delay() w kodzie jest nadal w porządku.

Oto 2 takich:

  • musisz zainicjować komponent podczas konfiguracji programu, a ten komponent potrzebuje trochę czasu, aby go zainicjować – na przykład 1,5 sekundy. W tym przypadku użycie delay(1500) w funkcji setup() jest całkowicie w porządku. Zasadniczo każdy delay() w funkcji setup() Twojego programu Arduino NIE będzie problemem.
  • jak wyjaśniono w części delayMicroseconds(), musisz poczekać kilka mikrosekund (nie milisekund!) podczas komunikacji z komponentem zewnętrznym. Jeśli okaże się, że użycie delayMicroseconds() z małą liczbą (na przykład 10) nie zakłóca reszty programu, nadal możesz go używać bez martwienia się zbytnio. Ale potraktuj to jako wyjątek, a nie wspólną regułę.

wniosek – używaj Arduino delay() ostrożnie

ze względu na naturę programów Arduino, często będziesz musiał dodać opóźnienia w kodzie, dzięki czemu możesz wybrać, kiedy wykonać niektóre akcje i jak często chcesz je wykonywać.

funkcje delay() i delayMicroseconds() są bardzo prostymi funkcjami w użyciu i zostały dodane do języka Arduino, aby początkujący mogli zacząć od czegoś prostego.

jednak, jak widziałeś w tym samouczku, użycie delay() może sprawić, że utkniesz naprawdę szybko. Najlepiej więc najpierw zrozumieć, dlaczego go potrzebujesz, jak go używać, a następnie jak uzyskać to samo zachowanie bez bezpośredniego używania funkcji Arduino delay().

po zrozumieniu struktury kodu, aby pozbyć się delay(), będziesz w stanie znacznie poprawić swoje programy Arduino, a wielozadaniowość stanie się dość łatwa.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.