3.27. Temporizador de vigilancia (watchdog)

Un temporizador de vigilancia (watchdog) es un componente de hardware que reinicia el microcontrolador si el script en ejecución alguna vez deja de avisarlo periódicamente. El script «alimenta» el watchdog desde algún lugar donde sabe que se ejecuta código sano; si un error, un bloqueo o una excepción inesperada impiden que la cámara alimente el watchdog dentro de un tiempo de espera configurado, el chip se reinicia a sí mismo y el script arranca de nuevo.

En un dispositivo desplegado sin nadie cerca para reiniciarlo manualmente, esta es la diferencia entre un error transitorio que se recupera en segundos y un dispositivo inutilizado que requiere una visita técnica.

Un gráfico de un contador de watchdog a lo largo del tiempo. El contador comienza en el valor del tiempo de espera, desciende linealmente hacia cero y se recarga al valor del tiempo de espera cada vez que el script llama a feed(). Tras tres llamadas exitosas a feed(), un cuarto intervalo no tiene feed() y el contador llega a cero, lo que provoca un reinicio del MCU.

El contador del watchdog cuenta hacia abajo desde su tiempo de espera. Cada feed() lo recarga; si llega a cero, el chip se reinicia.

3.27.1. La clase machine.WDT

machine.WDT habilita el watchdog y expone un único método, feed(). Una vez iniciado, el watchdog no se puede detener: las únicas salidas son alimentarlo según lo programado o dejar que reinicie el chip:

from machine import WDT

wdt = WDT(timeout=2000)    # reset if not fed within 2 seconds

while True:
    do_work()
    wdt.feed()

El timeout se expresa en milisegundos. El valor adecuado depende de cuánto tarda la iteración legítima más larga del bucle principal, con un margen cómodo: un bucle de 100 ms con un tiempo de espera de 2 s tiene amplio margen para una iteración lenta sin reinicios molestos.

3.27.2. Dónde llamar a feed()

El lugar donde vive feed() es la decisión de diseño crítica; el watchdog solo detecta errores en las partes del código que no se ejecutan entre alimentaciones.

  • Llámalo desde el bucle principal, al principio o al final. El patrón más común. El watchdog detecta cualquier cosa que bloquee el bucle principal (un interbloqueo, un while infinito, un periférico que nunca retorna) y reinicia el chip de vuelta al bucle.

  • No lo llames desde un manejador de interrupciones. El objetivo del watchdog es detectar bloqueos en la ruta de código normal. Una ISR que se dispara independientemente de si el bucle principal está atascado seguiría alimentando un watchdog que debería estar disparándose.

  • No lo llames desde dentro de una operación bloqueante larga. Una solicitud de red o una lectura de sensor que tarda diez segundos es exactamente el tipo de bloqueo que el watchdog debería detectar. Poner feed() dentro de ella anula la protección.

Una pauta que funciona para la mayoría de los programas: alimentar una vez por iteración del bucle principal, con el tiempo de espera ajustado a varias veces la duración esperada del bucle. Si una sola iteración necesita legítimamente más tiempo que el tiempo de espera (por ejemplo, una fase de calibración deliberada), estructura esa fase como una serie de fragmentos más pequeños con feed() entre ellos, o cambia el tiempo de espera con timeout_ms() (donde esté soportado) antes de entrar en ella.

3.27.3. Disponibilidad

El watchdog está expuesto en la mayoría de las cámaras OpenMV, pero no en todas: el hardware está presente en todas las piezas, pero la API de Python aún no está conectada en todas partes. Consulta la Placas OpenMV o intenta construir un WDT y captura el AttributeError si no está soportado.

Incluso en las cámaras donde WDT no está expuesto, un dispositivo desplegado en campo puede usar un equivalente por software: una tarea separada o un paso del bucle principal que monitorice el progreso y dispare machine.reset() si algo parece atascado. Es menos robusto que un watchdog por hardware (un manejador de interrupciones atascado también puede tumbar el monitor por software), pero cubre los mismos casos a nivel de aplicación.