Ir al contenido

← Todas las funcionalidades

Piso móvil hidráulico (app BLE)ESP32 PLC 38RGPIOResiliencia / OTA

Un watchdog hardware que mantiene vivo un PLC ESP32 desatendido

El firmware de una máquina en campo acabará colgándose tarde o temprano: una pila BLE bloqueada, un deadlock, un bucle sin fin. La cuestión es qué pasa después. En este despliegue real en una máquina hidráulica móvil, el task watchdog del ESP32 da la respuesta: si el loop principal deja de alimentar esp_task_wdt durante 20 segundos, el PLC se reinicia solo y la máquina vuelve a estar operativa antes de que nadie suba a reiniciar un armario eléctrico.

Tres líneas para volverse autorreparable

esp_task_wdt_init(20, true) arma el watchdog, esp_task_wdt_add(NULL) suscribe la tarea actual y un único esp_task_wdt_reset() al principio de cada iteración del loop lo alimenta. El flag true es el que importa: provoca un panic y un reinicio completo en lugar de limitarse a imprimir un aviso por un puerto serie que nadie está mirando. Elige un timeout holgadamente por encima de tu operación bloqueante legítima más larga, como escrituras en flash o reconexiones BLE.

Saber por qué te has reiniciado

Un watchdog que oculta los cuelgues en silencio cría firmware zombi: la máquina sigue funcionando mientras un bug real pasa desapercibido durante meses. Al arrancar, el ejemplo lee esp_reset_reason() y, cuando la causa fue el task watchdog, incrementa un contador persistente en NVS — el mismo patrón de Preferences usado para los contadores de ciclos de la máquina. Un contador de watchdog que crece en campo es tu alerta temprana de que algún camino del código necesita un arreglo antes de convertirse en una llamada a soporte.

Demuestra que funciona antes de entregar

El sketch de ejemplo incluye un botón de "cuelgue" que entra deliberadamente en un bucle infinito sin alimentar el watchdog: el LED de heartbeat se congela y unos 20 segundos después el PLC se reinicia por sí solo. Probar la recuperación en el banco es la diferencia entre esperar que el watchdog funcione y saber que lo hace — después, el servidor BLE vuelve a anunciarse y la app móvil se reconecta automáticamente.

Un fragmento de la implementación

Tal cual del ejemplo desplegado en el ESP32 PLC 38R — cópialo libremente:

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");
}

El ejemplo completo es un programa entero — cabecera de conexionado, setup y bucle principal — listo para adaptar a tu aplicación.

Preguntas frecuentes

¿Qué timeout de watchdog debo elegir?

Varias veces más largo que tu peor iteración legítima del loop, incluyendo escrituras en flash y operaciones BLE. Los 20 segundos usados aquí son conservadores para un controlador de máquina cuyo loop normalmente gira en milisegundos.

¿Protege el watchdog contra cualquier tipo de fallo?

No. Atrapa cuelgues software de la tarea monitorizada, no bugs de lógica que mantienen el loop girando, ni fallos de hardware. Combínalo con la detección de brownout, valores por defecto seguros en las salidas al arrancar y el registro del motivo de reset que se muestra aquí.

¿Vuelven las salidas a un estado seguro tras un reinicio por watchdog?

Sí, al reiniciar todos los GPIO vuelven a su estado por defecto y tu setup() se ejecuta de nuevo, así que diseña setup() para arrancar con todas las salidas de válvulas y motores apagadas — exactamente lo que hace la máquina de estados de válvulas de esta serie.

Funcionalidades relacionadas