Watchdog, come evitare i dead loop
Il watchdog è un sistema molto interessante impiegato per supervisionare il normale ciclo di istruzioni eseguite dalla cpu.
L’idea è quella di monitorare l’esecuzione del programma per evitare blocchi o cicli infiniti (dead loop), dovuti a bug logici o situazioni esterne che portano il microcontrollore ad attender, per esempio, a input che non arriveranno mai.
In questo caso il watchdog interviene resettando il microcontrollore e riavviando automaticamente l’esecuzione del codice.
Questo meccanismo è solitamente implementato in hardware e, anche Arduino, basato sul microcontrollore ATMega328, supporta questa funzione
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
Codice da utilizzare
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 reset | Parola Chiave |
15mS | WDTO_15MS |
30mS | WDTO_30MS |
60mS | WDTO_60MS |
120mS | WDTO_120MS |
250mS | WDTO_250MS |
500mS | WDTO_500MS |
1S | WDTO_1S |
2S | WDTO_2S |
4S | WDTO_4S |
8S | WDTO_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.
Related posts
10 Comments
Lascia un commento Annulla risposta
Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.
Articoli popolari
Sorry. No data so far.
.Net micro framework Arduino Arduino Webserver Domotica Flyport I2C IOT Netduino OpenPicus raspberry RTC Speed Test
Ciao,
utile come al solito… ho finalmente capito come utilizzare WatchDog.
Mi fa piacere,
grazie
Marco
ciao, volevo sapere se esiste un modo per aumentare il tempo tempo di reset
Ciao
i valori di reset dipendono dal prescaler e dalla frequenza dell’oscillatore, credo non sia possibile cambiare questi valori, la soluzione più veloce potrebbe essere quella di utilizzare un circuito esterno che resetti il chip.
Ciao,
grazie al tuo articolo riesco ad usare benissimo il WDT su Arduino Uno…. ;)
Ho la necessità di utilizzarlo anche con l’ATmega328, si può fare? Ho cercato su google ma non ho trovato informazioni.
Tu sai qualcosa?
Grazie!
Ciao Fabrizio
Arduino UNO monta il chip ATmega328 quindi puoi usare il wdt anche con questo chip.Naturalmente devi aver caricato il bootloader sul chip
Ciao
Ciao,
ho caricato su Arduino Mega 2560 uno sketch con il WDT impostato a 60MS, siccome sembrava non funzionasse ho provato a ricaricare il vecchio sketch senza successo. La procedura di caricamento parte normalmente, esegue la compilazione e poi si pianta, ho provato ad aspettare 10 minuti, ma non si muove. Iled della seriale circa ogni 10 sec. lampeggiano ma non succede di più. Quando si carica uno sketch Arduino blocca l’esecuzione di quello che sta girando? Può essere lo sketch caricato che blocca la seriale? Si può fare un caricamento di “emergenza” o “pulire” la cpu?
Scusa per la raffica di domande, ma non so più cosa fare.
Hai qualche idea?
Grazie
giorgio
Ciao Giorgio
prova a fare questo tentativo, stacca la board dalla usb , dall’ ide Arduino carica lo sketch e appena vedi la scritta ‘Sto caricando’ ricollega velocemente la board all’usb, Ti serviranno alcuni tentativi prima di riuscire a caricare lo sketch
a presto
Marco
Ciao Marco,
ha funzionato, GRAZIE!
Ho letto la risposta che hai dato a Rocco, come dovrebbe essere il circuito esterno di cui parli?
Grazie ancora.
Ciao
Ottimo!
il circuito esterno puo resettare Arduino tramite il pin /reset. questo circuito resetta la scheda ad esempio ogni 5 secondi (puoi usare un NE555), per avitare il reset devi usare, entro i 5 secondi un’uscita di Arduino per resettare il 555.
Non so se mi sono spiegato, è un circuito ‘agricolo’ ma funziona!
a presto