Budując nowe innowacyjne urządzenie staramy się by było niezawodne. Przewidujemy każdą możliwą sytuację i staramy się jej zaradzić. Pomimo szczerych chęci, zaangażowania i często dużego doświadczenia nie wszystko udaje się przewidzieć. W efekcie czasami nasze urządzenie zawiesza się i nie chce wykonywać tego, do czego zostało stworzone. Stara informatyczna metoda naprawy to wyłączyć i włączyć ponownie. Często przynosi to właściwy skutek, czyli urządzenie pracuje prawidłowo do czasu... następnego nieoczekiwanego zdarzenia.

Czas na konkrety

Nieoczekiwane problemy zdarzają się nie tylko w rozwiązaniach projektowanych amatorsko. Komercyjne układy borykają się z identycznymi problemami, choć nie powinno się coś takiego wydarzyć, to jednak się zdarza. Producenci mikrokontrolerów wynaleźli sposób na takie sytuacje - nazywa się to WatchDog timer, czyli układ, który pilnuje prawidłowej pracy mikrokontrolera, a w razie konieczności potrafi go zrestartować. W układach ESP również mamy do dyspozycji WatchDoga. Programista musi jedynie zadbać o to, by w odpowiednich miejscach w programie poinformować układ, że jeszcze działa poprawnie i się nie zawiesił... Jak to działa? Zasada jest prosta. W kodzie programu cyklicznie musimy resetować licznik układu WatchDog. Dopóki jest to wykonywane nasz program wykonuje się bez przeszkód. W momencie, gdy zapomnimy wykonać reset licznika, lub układ się zawiesi nastąpi reset sprzętowy mikrokontrolera i program zacznie wykonywać się od początku. Proste i skuteczne, a jak je zaimplementować przedstawię poniżej. W pierwszej kolejności musimy załączyć bibliotekę obsługującą WatchDoga.

#include <esp_task_wdt.h>

Następnie określamy czas, w którym nasz program musi "wyrobić się" z resetowaniem WatchDoga. W zależności od specyfiki budowanego układu musimy dobrać wartość doświadczalnie.

//3 sekundy
#define WDT_TIMEOUT 3

Następnie w funkcji setup załączamy obsługę WatchDoga.

esp_task_wdt_init(WDT_TIMEOUT, true); //włączenie obsługi watchdog ESP32
esp_task_wdt_add(NULL); //dodanie bieżącego wątku do "pilnowania" przez WDT

Pozostaje tylko co jakiś czas kasować licznik WDT.

esp_task_wdt_reset();

Poniżej kompletny kod ilustrujący działanie WDT.

#include <esp_task_wdt.h>
//3 sekundy
#define WDT_TIMEOUT 3
void setup() {
  Serial.begin(115200);
  Serial.println("Konfiguracja WDT...");
  esp_task_wdt_init(WDT_TIMEOUT, true);
  esp_task_wdt_add(NULL);
  Serial.println("WDT skonfigurowano");
  for(int i=0;i<10;i++)
     {
       Serial.println("WDT działa");
       delay(1000);
       esp_task_wdt_reset();
     }
}

void loop() {
  Serial.println("Tym razem nie resetuję WDT..");
  delay(1000);
}

W przykładzie w funkcji setup wstawiono pętlę for, w której co sekundę jest resetowany WDT. W efekcie pętla wykonuje się 10 razy, czyli 10 sekund układ działa bez problemu. Po przejściu do funkcji loop nie resetujemy WDT. Po trzech sekundach układ wykonuje reset sprzętowy ESP32.

Podsumowanie

Obsługa WatchDoga nie jest skomplikowana i warto ją zaimplementować w naszych układach. dzięki temu będziemy mieli pewność, że żaden dziwny zbieg okoliczności nie spowoduje zawieszenia układu. Warto tylko pamiętać, że WDT samo nie obroni nas przed błędami programistycznymi. Przykładowo możemy zaprogramować nieskończoną pętlę, w której będziemy resetować WDT i program nie będzie wykonywał się prawidłowo, a WDT nie zadziała...