Arduino ESP8266 Watchdog – przykład użycia, obsługa SW/HW WDT, kod, timeout
Pytanie
arduino esp8266 watchdog przykład
Odpowiedź Sztucznej Inteligencji
Bezpośrednia odpowiedź na pytanie
- Oto dwa sprawdzone przykłady watchdog’a (WDT) dla ESP8266 w Arduino: 1) poprawna obsługa długich operacji (yield/delay), 2) „drugi” programowy watchdog na Ticker, który zrestartuje układ, gdy Twój kod się zawiesi.
- Kluczowe punkty:
- ESP8266 ma dwa WDT: programowy (SW-WDT, ~3 s) i sprzętowy (HW-WDT, ~6–8 s); oba są domyślnie aktywne.
- W Arduino „karmienie” WDT następuje automatycznie przez delay()/yield() lub powrót z loop().
- Nie używaj długich blokujących fragmentów bez yield()/delay(); nie wstawiaj yield() w ISR.
Szczegółowa analiza problemu
- Architektura:
- SW-WDT nadzoruje wykonywanie pętli i zadań tła (stos Wi‑Fi). Jeśli kod blokuje CPU zbyt długo, zobaczysz „Soft WDT reset”.
- HW-WDT jest ostatnią linią obrony; zadziała, gdy SW-WDT nie da rady (np. całkowite zablokowanie).
- Zasada działania w Arduino:
- delay(x) w ESP8266 nie „usypia” tak jak w AVR: oddaje czas procesom tła (Wi‑Fi, TCP/IP) i resetuje WDT.
- yield() to „krótki” odpowiednik – wykonuje cykl zadań tła i również resetuje WDT.
- Kiedy wyłączać SW-WDT:
- Tylko na krótko, dla krytycznych, nieprzerywalnych sekwencji (np. precyzyjny bit‑banging). Pamiętaj, że HW‑WDT i tak zresetuje MCU po kilku sekundach. Czas argumentu w ESP.wdtEnable(ms) bywa ignorowany przez SDK – traktuj go orientacyjnie.
Aktualne informacje i trendy
- W praktyce utrzymuj pętle nieblokujące (wzorzec millis()) i wstawiaj yield() w ciężkich sekcjach obliczeń. Coraz częściej dodaje się „drugi” (aplikacyjny) watchdog – prosty timer/Ticker, który niezależnie od WDT systemowego wymusza restart, gdy aplikacja nie „bije serca”.
Wspierające wyjaśnienia i detale
- Nie karmisz WDT funkcją delayMicroseconds(); długie sekwencje z tą funkcją wywołają reset.
- ISR (przerwania) muszą być bardzo krótkie; nie wywołuj w nich yield() ani operacji blokujących.
- Preferuj ESP.restart() zamiast ESP.reset() (łagodniejszy reset stosu).
Aspekty etyczne i prawne
- W urządzeniach IoT watchdog ma wpływ na niezawodność i bezpieczeństwo użytkownika. Unikaj projektów, w których błąd logiki może skutkować pętlą resetów – dodaj zwłokę i logowanie przy starcie, aby umożliwić serwis/OTA.
Praktyczne wskazówki
- Projektuj długie zadania jako stanową maszynę z millis().
- Każdą „ciężką” pętlę rozbij: co n iteracji wywołaj yield().
- Włącz rozsądne logowanie przy starcie (powód resetu), aby szybko diagnozować WDT.
Ewentualne zastrzeżenia lub uwagi dodatkowe
- Czas SW‑WDT nie jest precyzyjnie konfigurowalny; zależy od core/SDK.
- Nadmierne wyłączanie WDT maskuje problemy; lepiej przeprojektować przepływ.
Sugestie dalszych badań
- Wzorce nieblokujące (scheduler kooperatywny na millis()).
- Zewnętrzny hardware watchdog (np. dedykowany układ WDT) dla aplikacji krytycznych.
- Analiza logów: ESP.getResetInfo()/ESP.getResetInfoPtr().
Przykłady
-
Długa operacja – poprawne „karmienie” WDT (yield/delay)
#include <ESP8266WiFi.h>
void setup() {
Serial.begin(115200);
Serial.printf("\nStart, reason: %s\n", ESP.getResetReason().c_str());
}
void loop() {
Serial.println("Długa operacja 5 s z prawidłową obsługą WDT...");
const unsigned long t0 = millis();
while (millis() - t0 < 5000) {
// ... Twoje obliczenia ...
// Co pewien czas oddaj sterowanie zadaniom tła:
yield(); // lub delay(0);
}
Serial.println("OK, brak resetu.");
delay(1000); // też karmi WDT
}
-
„Drugi” (aplikacyjny) watchdog na Ticker – restart po braku „bicia serca”
#include <ESP8266WiFi.h>
#include <Ticker.h>
Ticker wdApp; // timer co 1 s
volatile uint8_t wdCount = 0; // liczymy sekundy "bez życia"
void wdISR() {
if (++wdCount >= 5) { // 5 s bez "feed" -> restart
Serial.println("APP WDT: brak serca 5 s -> restart");
ESP.restart();
}
}
void setup() {
Serial.begin(115200);
Serial.printf("Reset reason: %s\n", ESP.getResetReason().c_str());
wdApp.attach(1.0, wdISR); // co 1 s
}
void loop() {
// ... normalna praca aplikacji ...
// Gdy wszystko OK, karm aplikacyjny watchdog:
wdCount = 0;
// Symulacja pracy
for (uint32_t i = 0; i < 200000; ++i) {
// ciężkie obliczenia
if ((i & 0x3FFF) == 0) yield(); // co jakiś czas oddaj sterowanie (SW/HW-WDT)
}
delay(500); // bezpieczny delay (karmi WDT systemowy)
}
-
Tymczasowe wyłączenie SW‑WDT dla krótkiej sekwencji nieprzerywalnej
#include <ESP.h> // deklaracje WDT
void krytycznaSekwencja() {
// UWAGA: jak najkrócej!
unsigned long t0 = micros();
while (micros() - t0 < 3000000UL) { // ~3 s
// bit-banging / ściśle czasowe operacje
// żadnych yield() ani delay()
asm volatile("nop");
}
}
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println("Krótkie wyłączenie SW-WDT...");
ESP.wdtDisable(); // tylko na czas sekcji
krytycznaSekwencja();
ESP.wdtEnable(0); // parametr bywa ignorowany, ważne: włączyć z powrotem
ESP.wdtFeed(); // nakarm po włączeniu
delay(1000);
}
-
Diagnostyka przyczyny resetu
#include <ESP8266WiFi.h>
void setup() {
Serial.begin(115200); delay(200);
Serial.printf("Reset reason: %s\n", ESP.getResetReason().c_str());
// alternatywnie:
// rst_info *ri = ESP.getResetInfoPtr();
// Serial.printf("reason=%d\n", ri->reason); // np. REASON_SOFT_WDT_RST, REASON_WDT_RST
}
void loop() {
delay(1000);
}
Krótkie podsumowanie
- ESP8266 ma domyślnie aktywny SW‑WDT i HW‑WDT; utrzymuj kod nieblokujący i używaj yield()/delay(), by zapobiec „Soft WDT reset”.
- Dodaj prosty watchdog aplikacyjny (Ticker) jako dodatkowe zabezpieczenie.
- Wyłączaj SW‑WDT tylko na bardzo krótkie, uzasadnione sekwencje; zawsze włącz go z powrotem i karm.
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.
Zadaj dodatkowe pytanie Sztucznej Inteligencji