Categories
Arduino Raspberry Technological

Arduino (IoT): Simple Tutorial Arduino Durmiente: Parte 1

Arduino Honduras Santiapps Marcio Valenzuela

Tutorial WDT: Arduino Durmiente -Parte 1

En este tutorial aprenderemos sobre dormir la Arduino.  Esto es necesario para ahorrar energía en proyectos autónomos.  En el tutoríal de la Estación Ambiental usamos una librería llamada la LowPower library para dormir nuestros electrónicos después de tomar datos para ahorrar energía.  Así nuestra batería (la cual se cargaba solamente) duraría mas tiempo ya que solo era necesario tomar muestras cada tanto tiempo.

Requisitos:

  1. Computadora (mac)
  2. Arduino UNO
  3. Arduino IDE (https://www.arduino.cc/en/Main/Software)
Arduino Tutorial Sleep Wakeup Dormir Despertar Santiapps Marcio Valenzuela
Arduino Tutorial Sleep Wakeup Dormir Despertar

Dormir la Arduino es sencillo y necesitamos usar:

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/io.h>

Y código tan sencillo como:

void sleepNow(){
    // Cual modo queremos usar:
    set_sleep_mode(SLEEP_MODE_IDLE);
    // Habilitar sleep (SE) bit:
    sleep_enable();
    // Dormir:
    sleep_mode();
    // Al despertar continua aqui y deshabilitamos SE sleep bit.
    sleep_disable();
}

Arduino puede dormir en 5 distintos modos y una idea de los ahorros:

  • SLEEP_MODE_IDLE: 15 mA (ahorra poco pero retiene muchas funciones)
  • SLEEP_MODE_ADC: 6.5 mA
  • SLEEP_MODE_PWR_SAVE: 1.62 mA
  • SLEEP_MODE_EXT_STANDBY: 1.62 mA
  • SLEEP_MODE_STANDBY : 0.84 mA
  • SLEEP_MODE_PWR_DOWN : 0.36 mA (ahorra mucho pero OJO!)

Para mayor información puede visitar (http://www.gammon.com.au/forum/?id=11497)

Debido a que el modo Power Down deshabilita tanta cosa (para ahorrar tanta energía) se vuelve importante el tema “Qué tenemos a disposición para despertarla?!”  Aquí entra el tema de que formas podemos despertar una Arduino durmiente:

  • via interrupt externo. Alguna acción externa es requerida para despertarla.
  • via el UART (USB serial interface). Una acción via el puerto serial USB puede despertarla.
  • via un timer interno. La Arduino puede ser despertada por Timer1, uno de los timers internos que corren en su chip.
  • via el watchdog timer (wdt). La Arduino solo puede ser despertada por el WDT, un timer especial que corre por aparte del chip principal.

Es importante saber en que modo dormimos para saber como despertarla porque, por ejemplo, en modo Power Down, solo el WDT y los interrupts externos son opciones para despertar, ya que el puerto serial y el timer interno están deshabilitados y por ende no los podemos usar para despertarnos!

Normalmente creamos una función como sleepNow() para dormir la Arduino.  Luego en el loop hacemos algo (tomar mediciones), luego llamamos sleepNow() para dormir la Arduino y la despertamos de distintas formas dependiendo si usamos una señal interna, externa, wdt o UART.

Eventos Externos.Señal Análoga

La connexion que usaremos para eventos externos es así de sencilla:

Arduino Simple Tutorial Sleeping Durmiendo Wakeup Despertar Santiapps Marcio Valenzuela
Arduino Simple Tutorial Sleeping Durmiendo Wakeup Despertar

Veamos un ejemplo con un Interrupt Externo:

#include <avr/sleep.h>
#include <avr/power.h>
int pin2 = 2;

void pin2Interrupt(void){
  // Este corre al despertar y solo tiene código vital de despertar...
  // Como por ejemplo desconectar el interrupt para que no se vuelva a despertar
  detachInterrupt(0);
}

void enterSleep(void){
  // Pin 2 sera el receptor del interrupt = INT0 segun atmega328
  attachInterrupt(0, pin2Interrupt, LOW);
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  // Aquí se acaba de dormir...
  // y es aquí donde continuará al despertar
  sleep_disable(); 
}

void setup(){
  Serial.begin(9600);
  pinMode(pin2, INPUT);
  Serial.println("Inicio de MCU completo!");
}

int seconds=0;
void loop(){
  delay(1000);
  seconds++;
  Serial.print("Despierta por ");
  Serial.print(seconds, DEC);
  Serial.println(" segundo");
  if(seconds == 3){
    Serial.println("Durmiendome....");
    delay(200);
    seconds = 0;
    enterSleep(); //La mandamos a dormir...
  }
}

Es necesario definir el pin que recibirá el interrupt externo.  La Arduino tiene 2 pines para este fin, pin #2 y #3.  Se definen en attachInterrupt(a,b,c) usando el primer parametro “a” donde 0 = pin 2 y 1 = pin 3.  Luego con el parámetro “b” definimos la función que sera llamada al despertar. c define que tipo de interrupt esperamos en ese pin.

En este caso usamos el botón para enviar la señal al INT0, el cual activa la función pin2Interrupt(), el cual nos regresa a sleepNow() justo en la linea de sleep_disable() y continua con el loop() y la vuelve a dormir después de 3 segundos.

Ok despertar la Arduino basado en un evento externo es muy fácil de entender.  Lo que resta aquí es definir ese evento para nuestras necesidades.  Es decir, como vamos a generar el evento que enviara el interrupt a nuestra Arduino.  Esto esta fuera del alcance de este tutorial pero es sencillamente un evento como una alarma (basada en un modulo RTC) o una medición de algún sensor como cambio en luz, temperatura, un botón o SMS.

Eventos Externos.Señal UART

Ahora veamos un ejemplo usando la UART, que en realidad no es mas que un tipo especial de interrupt externo.  Recordemos que el UART (USB-Serial) esta desahabilitado en MODE_PWR_DOWN sin embargo es muy común hacer un truco para usarlo.  La razón es que es muy deseado usar MODE_PWR_DOWN ya que es el modo que mas ahorra pero al mismo tiempo es muy practico usar el puerto Serial para recibir datos y despertar la Arduino.

Primero veremos un ejemplo de usar el Serial para dormir la Arduino y explicaremos porque.

#include <avr/sleep.h>

// Resistor entre RX y pin2. Por default RX se lleva a 5V
// Asi podemos usar una secuencia de datos Seriales de RX a 0
// Esto hara que pin2 vaya a LOW, activando INT0 via external interrupt
// despertando la MCU.
// También hay un counter duerme la MCU luego de 10 secs
int wakePin = 2;                 // pin para despertar
int sleepStatus = 0;             // variable para el estatus
int count = 0;                   // counter

void wakeUpNow()  {      // El interrupt nos trae aqui al despertar
// Luego continua en la ultima linea en loop() despues de dormir.
// Funciones como timers y otros como serial.print no funcionan aquí
}

void setup(){
  pinMode(wakePin, INPUT);
  Serial.begin(9600);
}

void sleepNow()     {    // Aqui dormimos la MCU
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // Modo PWR_DOWN
    sleep_enable();      // Habilita el sleep bit en el mcucr register
                         // para poder dormir 

    // attachInterrupt(A, B, C) 
    //A Sera 0 o 1 para interrupts en pin 2 o 3. 
    //B Handler que se llamara al interrumpir. 
    //C Modo de activation del interrupt pin: 
    // LOW bajo 
    // CHANGE cambio de nivel 
    // RISING creciente 
    // FALLING decreciente 
    // En todos menos IDLE se puede usar LOW. 
    attachInterrupt(0, wakeUpNow, LOW); 
    // usar interrupt 0 (pin 2) y correr función.
    // wakeUpNow cuando pin 2 llegue a LOW 
    sleep_mode(); // Este comando la duerme
                  // y el programa continua aqui al despertar
    sleep_disable();         // Prioridad luego de despertar!
    detachInterrupt(0);      // Deshabilita interrupt 0 en pin 2 para
                             // que wakeUpNow no se vuelva a ejecutar 
                             // durante el corrido normal.
}
void loop(){
  // Mostrar counter
  Serial.print("Despierta por ");
  Serial.print(count);
  Serial.println("sec");
  count++;
  delay(1000);                           // Esperar 1 segundo

  // Procesar input del Serial
  if (Serial.available()) {
    int val = Serial.read();
    if (val == 'S') {
      Serial.println("Serial: Entrando modo dormir");
      delay(100);     // Se requiere un pequeño delay  
      count = 0;
      sleepNow();     // Aquí llamamos a dormir según input 
    }
    if (val == 'A') {
      Serial.println("Hola Caracola"); // Aqui despertamos SI en IDLE*
    }
  }

  // Revisamos si pasaron 10 segundos para también dormir
  if (count >= 10) {
      Serial.println("Timer: Entrando dormir por timer");
      delay(100);     // Delay requerido
      count = 0;
      sleepNow();     // Dormir
  }
}

Recordemos que en PWR_DOWN el Serial esta deshabilitado según el datasheet:

Arduino Tutorial Sleep Wake up Dormir Despertar Santiapps Marcio Valenzuela
Arduino Tutorial Sleep Wake up Dormir Despertar

Por eso no pudimos usar datos seriales en el código anterior para despertar la MCU.  Teníamos que usar el botón.

Si queremos usar Serial UART para despertar la Arduino tendríamos que conectar el Pin 2 con el Rx.  Así cuando enviamos datos al Serial, bajaran los 5V del Pin 2 y eso disparará el interrupt.  De otra manera, tendríamos que modificar el código cambiando el modo de dormir a SLEEP_MODE_IDLE y allí si podríamos usar Serial input directo para despertar, sin interconectar el Rx al Pin 2(INT0).

Eventos Internos.Timers

Para comprender eventos internos que puedan despertar la Arduino es necesario entender un poco sobre como funciona el MCU.  El video original esta inglés aquí () sin embargo hacemos una reseña sencilla a continuación:

Arduino Atmel Atmega328 Sleep Mode Watchdog Timer Simple Tutorial Santiapps Marcio Valenzuela
Arduino Atmel Atmega328

La Atmega tiene un counter de 16MHz que controla sus operaciones (significativamente mas lento que nuestras computadoras de escritorio, portátiles e incluso nuestros celulares).  Pero adicionalmente tiene otro counter de 128kHz que es aun MAS lento, llamado el wdt.  Este otro counter se puede usar como alarma con un timeout o alarma.  Esto también es conocido como “la mordida del perro”.  El perro guardian muerde cuando se dispara la alarma o se termina el timeout.  Al suceder esto se puede generar un interrupt o un reset del sistema.  Esto se usa comúnmente en proyectos remotos donde, si algo llegara a pasar como falta o fluctuación de energía o algo que “atasca” la operación normal del MCU, se puede resetear automáticamente.

Como podemos ver en la imagen, el reloj principal que maneja el código principal del loop (el azul), tiene la habilidad de resetear el timer wdt.  Es decir, configuramos el wat (verde) para que cuente (desde 16ms hasta 8s) hasta el timeout que deseamos.  Al llegar al valor del timeout, la alarma de dispara, o el perro muerde.  Pero desde el código principal (azul) podemos reiniciar el counter (verde) nuevamente a 0, antes que llegue a su valor de timeout.  Esto se conoce como “Patting the Dog” o darle una palmada de cariño al perro, para que no nos muerda y se vuelva a dormir!

Veremos muchos valores de estos “relojes” y del chip que tenemos que setear al usar el wdt o cualquier de los otros 3 timers internos de la atmega328.  Pero algo importante de notar es que cuando el timer se dispara y se genera un interrupt, se hace a través del ISR(), una función que veremos en los siguientes ejemplos.

Ahora veamos como despertar la Arduino via el Timer1, interno:

#include <avr/sleep.h>
#include <avr/power.h>
#define LED_PIN (13)
volatile int f_timer=0;
ISR(TIMER1_OVF_vect){
// Set la flag llamada f_timer
if(f_timer == 0){
f_timer = 1;
}
}
void enterSleep(void){
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
/* Deshabilitar los peripherals para reducir consumo y también para que no generen interrupts que puedan despertar la Arduino sin querer
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer2_disable();
power_twi_disable();
// Dormir
sleep_mode();
// Ejecucion continua aquí luego de timer1 timeout. Es critico deshabilitar sleep aqui
sleep_disable();
// Rehabilitar peripherals
power_all_enable();
}
void setup(){
Serial.begin(9600);
// Pin LED de Arduino
pinMode(LED_PIN, OUTPUT)
// Configurar el Timer1 interno
TCCR1A = 0x00;
// Resetear el timer counter register.
// Aquí se puede asignar un valor para reducir el timeout.
TCNT1=0x0000;
// Configurar el prescaler a 1:1024 para un timeout de 4.09 segundos
TCCR1B = 0x05;
// Habilitar el timer overlook interrupt
TIMSK1=0x01;
}
void loop(){
if(f_timer==1){
f_timer = 0;
// Encender una LED
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
// Dormir!
enterSleep();
}
}

Aquí nuevamente tenemos el setup() y la función de dormir llamada enterSleep().  En el setup() configuramos el timer según el datasheet.  En enterSleep() contiene al igual que sleepNow, el código para dormir la MCU.  loop() revisa cuando dormir.  Finalmente ISR es nueva, es una rutina que ejecuta el MCU cuando recibe un interrupt.

Eventos Internos.WDT

Finalmente veamos un ejemplo con WDT:

#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#define LED_PIN (13)
volaile int f_wdt=1;
ISR(WDT_vect){
if(f_wdt == 0){
f_wdt=1;
}else{
Serial.println("WDT Overrun!!!");
}
}
void enterSleep(void){
set_sleep_mode(SLEEP_MODE_PWR_SAVE); // O usar SLEEP_MODE_PWR_DOWN para menor consumo
sleep_enable();
// Dormir
sleep_mode();
// Programa continua aquí luego del WDT Overrun
sleep_disable(); // Impt prioridad deshabilitar sleep
// Re-habilitar peripherals
power_all_enable();
}
void setup(){
Serial.begin(9600);
Serial.println("Inicializando...");
delay(100); // Delay requerido para el Serial
pinMde(LED_PIN,OUTPUT);
// Configurar WDT
// Clear reset flag
MCUSR &amp;= ~(1<<WDRF);
// Para cambiar WDE o el precaver, debemos set WDCE
// Esto permite updates por 4 ciclos
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Configurar nuevo watchdog-timeout prescalar
WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 segundos */
// Habilitar WD interrupt (note no reset)
WDTCSR |= _BV(WDIE);
Serial.println("Inicio completo");
delay(100); // Delay requerido para el Serial
}
void loop(){
if(f_wdt == 1){
// Encender LED
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
// Set la flag
f_wdt = 0;
// Entrar modo de dormir
enterSleep();
}else{
// Hacer algo o nada
}
}

Puede que encuentren otra manera mas sencilla de usar el WDT como esta:


//Al correr, Arduino Rebooted se muestra y wdt comienza a contar 8s
//Ya que ifdef, calmamos al perro y no muerde e imprime
//Arduino Running. Luego de 1 segundo
//Si ifdef se comments, no calmamos al perro y muerde cada 8 segundos
#include <avr/wdt.h>
#define RESETWATCHDOG
void setup(){
Serial.begin(57600);
Serial.println("");
Serial.println ("Arduino Rebooted");
Serial.println("");
wdt_enable(WDTO_8S);
}
void loop(){
#ifdef RESETWATCHDOG
wdt_reset(); //pat the dog
#endif
Serial.println("Arduino Running");
delay(1000);
}

Esto lo que hace es reiniciar la MCU, no la duerme.  Todo esto depende de que queremos lograr. Con lo que hemos visto podemos dormir o reiniciar.

DORMIR.  Es para cuando queremos ahorrar energía ya que estamos corriendo nuestro proyecto de una fuente de energía limitada, como ser una batería cargada de un panel solar u otra fuente intermitente.

RESETEAR.  Esta función es util cuando tenemos un proyecto remoto y debemos asegurarnos que cualquier problema con el código o con la fuente de energía que pueda “atascar” el correr normal del main loop del programa, pueda ser resuelto reiniciando la MCU.

Categories
Arduino Iphone Developer Raspberry Technological

Arduino (IoT): Simple Tutorial Ethernet W5100 Arduino Shield

Arduino Honduras Santiapps Marcio Valenzuela

Tutorial Ethernet 5100 Arduino Shield

En este tutorial exploramos la shield original de Arduino, Ethernet, W5100.  Tambien esta la Arduino CC3000 WiFi, la cual acaba de ser reemplazada (Nov 2015) por la WiFi 101.  Veremos estas en tutoriales futuros.

Ahora veamos los componentes requeridos.

Requisitos:

  1. Computadora (mac)
  2. Arduino UNO
  3. Arduino Ethernet Shield W5100
  4. Arduino IDE (https://www.arduino.cc/en/Main/Software)
Arduino Simple Tutorial W5100 Ethernet
Arduino Simple Tutorial W5100 Ethernet

Las shields son muy practicas y fáciles de usar.  Simplemente se conectan sobre los headers de la Arduino UNO.  Cuidado porque hay shields para distintas placas.  Es decir que una shield es especifica para la UNO y no funciona sobre la MEGA y vv.

Ya conectada podemos repasar el código rápidamente para montar un servidor que muestre datos de sensores análogos (o digitales) de nuestra AVR como para montar rápidamente un servidor de datos de sensores.

[code]
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);
// Iniciar en puerto 80
EthernetServer server(80);
void setup() {
//Inicializar
Serial.begin(9600);
while (!Serial) {
; // esperar el puerto (necesario solo en Leo)
}
Ethernet.begin(mac, ip);
server.begin(); //Iniciar conexión
Serial.print(“servidor en “);
Serial.println(Ethernet.localIP());
}
void loop() {
// Buscar clientes activamente
EthernetClient client = server.available();
if (client) {
Serial.println(“Cliente Nuevo”);
// Un HTTPRequest termina con una linea en blanco
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// Si se llego al final de una linea (via un caracter de linea nueva
// y la linea esta en blanco, el HTTPRequest ha terminado,
// asi que podemos responder asi…
if (c == ‘\n’ && currentLineIsBlank) {
// Enviar header de HTTPResponse tipico…
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-Type: text/html”);
client.println(“Connection: close”); // La conexion cerrara luega de la HTTPResponse
client.println(“Refresh: 5”); // Refrescar cada 5 segundos
client.println();
client.println(“<!DOCTYPE HTML>”);
client.println(“<html>”); //tambien puede insertar php
// Escribir en pantalla los niveles de los puertos analogos
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print(“Input analogo “);
client.print(analogChannel);
client.print(” es “);
client.print(sensorReading); //algun sensor conectado a cada pin/channel
client.println(“<br />”);
}
client.println(“</html>”);
break;
}
if (c == ‘\n’) {
// Nueva linea
currentLineIsBlank = true;
}
else if (c != ‘\r’) {
// Nuevo caracter en la linea actual
currentLineIsBlank = false;
}
}
}
// Dar tiempo para que browser reciba datos
delay(1);
// Cerrar conexion
client.stop();
Serial.println(“cliente desonectado”);
Ethernet.maintain();
}
}
[/code]

Categories
Arduino Raspberry Technological

Arduino (IoT): Simple Tutorial WDT: Parte IV – WatchDog Timer (WDT)

Arduino Honduras Santiapps Marcio Valenzuela

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:

  1. Computadora (mac)
  2. Arduino UNO
  3. Breadboard
  4. Arduino IDE (https://www.arduino.cc/en/Main/Software)
Arduino Tutorial Real Time Clock RTC DS1307 Santiapps Marcio Valenzuela
Arduino Tutorial Real Time Clock RTC DS1307

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.

Translate »