Watchdog, come creare un sistema che auto resetti la scheda in caso di blocchi o attese infinite

Il watchdog è un sistema molto interessante atto a supervisionare il normale ciclo di istruzioni della cpu. L’idea è quella di monitorare l’esecuzione del programma; in caso di blocchi o cicli infiniti, che rischiano di mettere il microcontrollore in uno stato di inutilizzo, il watchdog interviene resettando il microcontrollore e riavviandolo automaticamente.

Questo meccanismo è solitamente implementato in hardware e, anche Arduino, basato sul microcontrollore ATMega328, supporta questa funzionalità

Arduino atmega328 watchdog timer

Se il programma che andiamo a scrivere per la board Arduino è progettato considerando tutti gli aspetti e le variabili che possono bloccare la cpu, non è necessario gestire il Watchdog, che di default è disabilitato.
Capita comunque che si verificano delle particolari condizioni che portano il programma a rimanere in attesa, ad esempio, di un particolare input che per cause esterne, non gestibili, potrebbe non arrivare mai. Il watchdog quindi attende per un certo periodo e se, allo scadere di questo tempo l’input non è arrivato il Watchdog resetta la cpu facendola riavviare. In caso contrario, quando l’input arriva entro questo tempo, è fondamentale che il codice resetti il watchdog per evitare che questo resetti continuamente la cpu.

Il diagramma a blocchi seguente illustra in modo banale il meccanismo del watchdog

Schema esecuzione watchdog

Per utilizzare il Watchdog inseriamo nello sketch il riferimento alla libreria wdt.h

#include <avr/wdt.h>

 

I tempi di reset del Watchdog sono prestabiliti e possono essere scelti utilizzando i valori specificati nella tabella seguente

Tempo resetParola Chiave
15mSWDTO_15MS
30mSWDTO_30MS
60mSWDTO_60MS
120mSWDTO_120MS
250mSWDTO_250MS
500mSWDTO_500MS
1SWDTO_1S
2SWDTO_2S
4SWDTO_4S
8SWDTO_8S

Nel blocco setup() decidiamo di abilitare il watchdog specificando il tempo di reset utilizzando la seguente funzione:

//abilito il watchdog e imposto come tempo di reser 2 secondi
wdt_enable(WDTO_2S);

 

questo significa che se entro 2 secondi non resettiamo il conteggio del watchdog, esso eseguirà automaticamente il reset della cpu.
Per resettarlo impieghiamo la seguente funzione:

//resetto il watchdog
wdt_reset();

 

Il codice seguente mostra meglio il funzionamento del sistema

#include <avr/wdt.h>

void setup()
{
  //attivo il watchdog e lo imposto
  //per una soglia di tempo di 2 Secondi
  wdt_enable(WDTO_2S);

}

void loop()
{
  //eseguo qualcosa...
  delay(500);

  //resetto il watchdog
  wdt_reset();
}

 

All’interno del blocco loop() eseguo un delay di 500 ms e poi resetto il watchdog, in questo caso il watchdog non resetterà mai la cpu poiché non arriverà mai a contare i due secondi preimpostati, dato che il reset avviene ogni 500 ms.
Vediamo invece questa situazione:

#include <avr/wdt.h>

void setup()
{
  //attivo il watchdog e lo imposto
  //per una soglia di tempo di 2 Secondi
  wdt_enable(WDTO_2S);

}

void loop()
{
  //eseguo qualcosa...
  delay(3000); //3 secondi

  //resetto il watchdog
  wdt_reset();
}

 

Il codice precedente mette in funzione il sistema di auto reset in quanto, il delay di 3 secondi, fa in modo che il watchdog arrivi a contare i 2 secondi preimpostati facendo resettare la cpu. Di fatto l’istruzione wdt_reset() non verrà mai eseguita.

Consiglio di utilizzare questo meccanismo in tutte le situazioni critiche che richiedono una certezza che la cpu esegua costantemente il suo compito evitando blocchi che porterebbero all’interruzione del servizio.