
Tutorial WDT: Parte IV – WatchDog Timer (WDT)
En esta parte utilizamos nuestro el WatchDogTimer (WDT) interno del Arduino para resetear nuestra Arduino UNO cada 8 segundo. El WDT es otra manera de “despertar” una Arduino o resetearla. Es muy común a la hora de revivir una Arduino que por mal código o malas condiciones electrónicas puede haber caído en un loop y esta atascada.
Requisitos:
- Computadora (mac)
- Arduino UNO
- Breadboard
- Arduino IDE (https://www.arduino.cc/en/Main/Software)

El código:
#include <avr/wdt.h> #define RESETWATCHDOG void setup(){ Serial.begin(57600); Serial.println(""); Serial.println ("------->Arduino Rebooted"); Serial.println(""); wdt_enable(WDTO_8S); // Reseteara la Arduino c/8s } void loop(){ #ifdef RESETWATCHDOG wdt_reset(); // Reiniciar el WDT (Pat the Dog) #endif Serial.println("Arduino Running"); delay(1000); }
Con este código despertamos la Arduino cada 8 segundos usando el WDT, o mejor dicho, habilitamos el wat timer para que cuente 8 segundos y si no le damos un wdt_reset(), rebotes el mcu. Al definir RESETWATCHDOG, corremos el bloque que incluye wdt_reset(). Este comando es conocido como “Pat the Dog” lo cual se traduce a “tranquilizar al perro dandole unas palmadas suaves sobre la cabeza”. Esto es por lo siguiente: Consideramos que el timer así como cualquier alarma es como tener un perro despertador que muerde. Cuando la alarma se dispara se dice que el perro mordió! Pero si al perro enojado, antes que muerda, se le da unas palmadas en la cabeza, el perro se tranquiliza por un rato y no muerde. En resumen, al configurar un timer cada 8S, estamos esperando que el perro nos muerda a los 8 segundos de arrancar el timer. Pero si queremos que no nos muerda, le damos un “Pat” en la cabeza para que se vuelva a dormir.
8 segundos es el máximo sin embargo podemos usar un poco de ingenio de programación para alargar ese tiempo. Por ejemplo:
#include <avr/sleep.h> #include <avr/wdt.h> /********************* * PRESCALER - modifies the clock times. For delay(1000) with Mode 4, delay would be 16x longer. * Mode 0 - Do nothing - normal 16Mhz clock * Mode 1 - Clock divide by 2 - 8MHz * Mode 2 - Clock divide by 4 - 4MHz * Mode 3 - Clock divide by 8 - 2MHz * Mode 4 - Clock divide by 16 - 1MHz * Mode 5 - Clock divide by 32 - 500kHz * Mode 6 - Clock divide by 64 - 250kHz * Mode 7 - Clock divide by 128 - 125kHz * Mode 8 - Clock divide by 256 - 62.5kHz *********************/ #define Set_prescaler(x) (CLKPR = (1<<CLKPCE),CLKPR = x) //for any delays, theyre multiplied by the prescaler time #define LED 5 int Prescaler_mode = 4; const int A0_pin = A0; /********************* * WATCHDOG INTERRUPT *********************/ ISR(WDT_vect) { wdt_disable(); // disable watchdog } void myWatchdogEnable(const byte interval) { MCUSR = 0; // reset various flags WDTCSR |= 0b00011000; // see docs, set WDCE, WDE WDTCSR = 0b01000000 | interval; // set WDIE, and appropriate delay wdt_reset(); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_mode(); // now goes to Sleep and waits for the interrupt } void setup(){ Set_prescaler(Prescaler_mode); // 1/16 clock speed int i; for(i = 0; i <= 19; i++) // all pins set as input w/ pulp resistor { pinMode(i, INPUT); digitalWrite(i, HIGH); } pinMode (LED, OUTPUT); pinMode(A0_pin, INPUT); } void loop(){ if (analogRead(A0_pin) >= 1000){ digitalWrite (LED, LOW); } else { digitalWrite (LED, HIGH); } delay(65); /********************* * SLEEP BIT PATTERNS * 1 second: 0b000110 * 2 seconds: 0b000111 * 4 seconds: 0b100000 * 8 seconds: 0b100001 *********************/ // sleep for a total of 240 seconds [240/8=30] int i; for (i = 0; i < 30; i++) { myWatchdogEnable (0b000110); // 1 seconds } }
Aquí estamos durmiendo la UNO por 30 unidades de 8 segundos cada una, ósea 240 segundos en total o 4 minutos. Referencia: http://forum.arduino.cc/index.php/topic,173850.0.html
Que hemos aprendido con este tema de dormir el MCU? Pues tenemos una manera de ahorrar energía y de resetear la MCU para que se puede recuperar de algún error. La primera function tiene una utilidad clara, ahorrar energía en momentos donde es limitada, como cuando corremos un proyecto desde una fuente de energía limitada como ser un battery pack recargado por un panel solar u otra fuente temporal. Esto nos obliga a usar nuestra energía de manera conservadora.
La segunda función es util para recuperar el MCU de un problema de código o algo externo que haya interrumpido la operación normal del programa base (setup() -> loop() ). Esto nos permite revisar la MCU cada tanto tiempo y ella debe responder correctamente, conocido como “patting the dog”. De no ser así, la alarma se dispara, el perro nos muerde y procedemos a reiniciar la MCU.
Este es un tema bien complejo y espero que si tienes dudas nos las hagas llegar. Cualquier cosa lee nuestra serie de Arduino Durmiente para entender un poco mas sobre el WatchDog Timer.