Watchdog w Arduino to bardzo pożyteczna funkcja, w szczególności gdy zakończyliśmy już testy programu i chcemy użyć go w warunkach rzeczywistych. Na przykład zaprogramowaliśmy układ zamka szyfrowego do mieszkania i zainstalowaliśmy go na drzwiach wejściowych. Co jeśli z różnych przyczyn procesor płytki arduino zawiesi się? Na przykład na skutek zakłóceń elektromagnetycznych lub nieznanego wcześniej błędu w kodzie.
Nie wejdziemy w tej sytuacji do mieszkania…
Aby tak się nie stało dołączamy do kodu programu watchdog, który w przypadku gdy program zawiesi się, resetuje Arduino.
Użycie jest bardzo proste, co zademonstrowano na poniższym przykładzie.
Przykład 1
1 2 3 4 5 6 7 8 9 10 11 |
#include <avr/wdt.h>//włączamy bibliotekę do programu void setup() { wdt_enable(WDTO_1S); //aktywujemy watchdog z argumentem czasu - w tej sytuacji 1 sekunda //wstawiamy w dowolnym miejscu w setup...od tego momentu watchdog już działa;) } void loop(){ wdt_reset(); //reset zegara watchdog //(jeśli w ciągu w tym wypadku sekundy program nie zrealizuje funkcji wdt_reset() - Arduino zresetuje się samoczynnie. } |
Użycie funkcji wdt_reset() musi być przemyślane. W powyższym przykładzie reset zegara watchdog „wdt_reset()” musi nastąpić w czasie nie dłuższym niż jedna sekunda. Jeśli to się nie stanie płytka Arduino zresetuje się (tak jakbyśmy nacisnęli na niej przycisk „reset”). Dlatego, nie możemy wprowadzić w kod programu np. komendy delay(2000), ponieważ funkcja watchdog zadziała i zresetuje nam płytkę zanim program odczeka te 2000 ms.
Dodatkowo należy szczególnie uważać należy na pętle „for” i „while”, ponieważ program może wykonywać się w pętlach dłuższy czas. Dlatego, jeśli to konieczne można użyć wdt_reset() w kodzie kilkukrotnie – również wewnątrz pętli.
Jednak jeśli Arduino z jakiegoś powodu zawiesiło się i program w ciągu sekundy nie odczyta funkcji „wdt_reset()” nastąpi samoczynny reset programu.
Można zapisywać liczbę resetów spowodowanych przez watchdog w pamięci eeprom. Po jakimś czasie użytkowania urządzenia można sprawdzić czy program lub układ elektroniczny jest stabilny, odczytując pamięć EEPROM.
Tabela dostępnych argumentów funkcji „wdt_enable” – tzn. okres w jakim funkcja sprawdza czy Arduino się nie zawiesiło:
1 2 3 4 5 6 7 8 9 10 11 12 |
Czas oczekiwania: Argument funkcji "wdt_enable": 15mS WDTO_15MS 30mS WDTO_30MS 60mS WDTO_60MS 120mS WDTO_120MS 250mS WDTO_250MS 500mS WDTO_500MS 1S WDTO_1S 2S WDTO_2S 4S WDTO_4S 8S WDTO_8S |
Na przykład jeśli chcemy sprawdzać Arduino co ćwierć sekundy wpisujemy w sekcji „seup”: wdt_enable(WDTO_250MS);
Uwaga praktyczna: Zdarza się, że watchdog jest w konflikcie z bootloaderem płytki. Dzieje się tak np. na płytce nano. Dlatego, aby wykorzystać w tej sytuacji watchdog, płytkę należy zaprogramować przez SPI a nie przez USB – wtedy wszystko działa.
Watchdog może być użyty również do oszczędzania energii zasilania w Arduino.
Przykład
Poniższy przykład demonstruje użycie funkcji watchdog w praktyce. Celem programu jest miganie diody na płytce co 1 sekundę. Zdefiniowaliśmy sobie, że watchdog sprawdzać będzie co 0,25 sekundy, czy płytka pomyślnie realizuje swój kod. W tym przypadku, gdy użyjemy polecenia delay(1000) program nie zadziała poprawnie. Program zrealizowany został przy użyciu funkcji millis():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <avr/wdt.h>//włączamy bibliotekę do programu const int nr_pinu = 13; //definicja numer pinu do którego podłączona jest dioda int stan_diody = LOW; //definicja zmiennej stanu diody (HIGH-świeci, LOW-nie świeci) unsigned long ostatni_czas = 0; //definicja zmiennej pomocniczej, do której przypisana będzie ostatnia wartość czasu zmiany staniu diody const long okres_czasu = 1000; //definicja okresu migania diody (500 to znaczy 0,5s) void setup() { pinMode(nr_pinu, OUTPUT); digitalWrite(nr_pinu, LOW); ostatni_czas = millis(); // przypisanie aktualnej wartości czasu do zmiennej wdt_enable(WDTO_250MS);//od tego miejsca watchdog sprawdza co 0,25 sekundy czy arduino nie zawiesiło się } void loop() { if (millis() - ostatni_czas >= okres_czasu) { stan_diody =!stan_diody ;//zmiana stanu zmiennej diody na przeciwny digitalWrite(nr_pinu, stan_diody); ostatni_czas = millis(); // przypisanie aktualnej wartości czasu do zmiennej } wdt_reset(); //reset zegara watchdog } |
Resetowanie zegara watchdog, można również wykonać za pomocą przerwań zegara.
Dziękujemy za przeczytanie naszego artykułu. Jeśli doceniasz naszą pracę, prosimy o zapisanie się do bezpłatnego newslettera.
Więcej informacji o watchdog można uzyskać na oficjalnej stronie Arduino: link do strony
Przetestuj nasz generator przerwań typu PCINT (https://arduinowo.pl/generatory/pin_int/)