← Watchdog hardware en PLC ESP32 para máquinas desatendidas
Piso móvil hidráulico (app BLE)ESP32 PLC 38RGPIOResiliencia / OTA
Watchdog hardware en PLC ESP32 para máquinas desatendidas — ejemplo completo
Haz autorreparable el firmware de un PLC ESP32 con esp_task_wdt. Un watchdog hardware de 20 s reinicia solo un controlador colgado, con diagnóstico en NVS.
Programa completo y ejecutable para el ESP32 PLC 38R (hardware-watchdog-38r.ino): incluye cabecera de conexionado, requisitos y notas de integración.
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales
Vista de solo lectura.
/*
* COMPLETE EXAMPLE — ESP32 hardware watchdog (esp_task_wdt)
*
* Hardware: ESP32 PLC 38R (Industrial Shields)
* Based on: hydraulic moving floor project, main.cpp (resilience)
*
* Wiring:
* I0_0 "Simulate hang" push button (blocks the loop on purpose)
* R0_1 Heartbeat LED (blinks while the firmware is healthy)
*
* Logic:
* - esp_task_wdt_init() arms a 20 s watchdog on the loop task.
* - Every loop iteration "feeds" it with esp_task_wdt_reset().
* - If the firmware hangs (deadlock, infinite loop, blocked BLE
* stack...), the watchdog reboots the PLC by itself: the machine is
* operational again without anyone climbing up to power-cycle it.
* - The reason of the last reboot and a watchdog reboot counter are
* stored in NVS for field diagnostics.
*
* Integration with other catalog modules:
* - The reboot counter uses Preferences, just like the cycle
* counters (see ejemplos/piso-movil/nvs-persistent-counters-38r.ino).
* - After the reboot the BLE server advertises again and the app
* reconnects by itself (see ejemplos/piso-movil/ble-mobile-app-control-38r.ino).
*/
#include
#include
#define BTN_HANG I0_0
#define LED_ALIVE R0_1
#define WDT_TIMEOUT 20 // seconds without feeding -> reboot
Preferences prefs;
int wdtResets = 0;
// Translation of the reset reason for the diagnostics log
const char* resetReasonText(esp_reset_reason_t r) {
switch (r) {
case ESP_RST_POWERON: return "power-on";
case ESP_RST_SW: return "software reboot";
case ESP_RST_TASK_WDT: return "WATCHDOG (firmware hung)";
case ESP_RST_BROWNOUT: return "brownout (power supply)";
default: return "other";
}
}
void setup() {
Serial.begin(115200);
pinMode(BTN_HANG, INPUT);
pinMode(LED_ALIVE, OUTPUT);
// 1. Diagnostics: why did we boot?
esp_reset_reason_t reason = esp_reset_reason();
Serial.print("Reason of the last reboot: ");
Serial.println(resetReasonText(reason));
// 2. Persistent counter of watchdog reboots (NVS pattern)
prefs.begin("nvdata", false);
wdtResets = prefs.getInt("wdt_resets", 0);
if (reason == ESP_RST_TASK_WDT) {
wdtResets++;
prefs.putInt("wdt_resets", wdtResets);
}
prefs.end();
Serial.println("Accumulated watchdog reboots: " + String(wdtResets));
// 3. Arm the watchdog: 20 s and panic=true (reboots instead of just warning)
esp_task_wdt_init(WDT_TIMEOUT, true);
esp_task_wdt_add(NULL); // watches the current task (loop)
Serial.println("Watchdog armed: " + String(WDT_TIMEOUT) + " s");
}
void loop() {
// Feed the watchdog: as long as the loop keeps spinning, nothing happens
esp_task_wdt_reset();
// Heartbeat LED at 1 Hz: at a glance you can see the firmware is healthy
digitalWrite(LED_ALIVE, (millis() / 500) % 2);
// Hang simulation: infinite loop WITHOUT feeding the watchdog.
// After 20 s the PLC reboots by itself and the NVS counter increments.
if (digitalRead(BTN_HANG)) {
Serial.println("Firmware 'hung' on purpose. Rebooting in ~20 s...");
while (true) {
// no esp_task_wdt_reset() and no delay(): a real hang
}
}
delay(50);
}
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales