Arduino Sleep Mode

En muchos proyectos donde no es posible tener alimentación eléctrica o de movilidad tenemos que alimentar el microcontrolador mediante batería, para conseguir alimentar un microcontrolador durante mucho tiempo con batería podemos usar el modo sleep donde el consumo se reduce drásticamente.

Ya vimos en el apartado de alimentación Arduino que no tiene sentido alimentar una placa de Arduino con una batería, incluso aunque pongamos la MCU en modo sleep, puesto que los componentes de la placa son altamente ineficientes. Sencillamente porque la eficiencia nunca entró en las especificaciones de diseño, hasta los nuevos modelos.

Normalmente, hay muchos proyectos en los que hay que realizar acciones periódicas de tiempo en tiempo, como tomar lecturas de sensores o enviar mensajes a un servidor central, pero la mayor parte del tiempo nuestro Arduino no está haciendo nada más que un loop continuo.

Sin embargo no hacer nada para un procesador, sigue suponiendo miles de instrucciones por segundo que consumen una energía preciosa, cuando funciona a baterías.

Cuando el microcontrolador entra en modo de suspensión (sleep) por su código, la ejecución del código se detendrá en ese punto. Para reanudar la ejecución de su código, el microcontrolador debe ser despertado desde el modo de suspensión por uno de sus módulos internos de hardware, temporizador expirado, interrupción externa, WDT, etc.

La librería estándar de Arduino, por ahora no permite acceso a las funciones que hacen dormir al MCU (Microcontrolador) y hay que usar la librería AVR directamente o librerías de terceros que nos ayuden a usar el modo sleep.

Para más información ver la documentación del ATmega328p http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf en las página 62

Tenemos en el Atmega328p seis modos de Sleep:

  • Idle
  • ADC Noise Reduction
  • Power-save
  • Power-down
  • Standby
  • Extended Standby

El consumo para cada modo es:

  • SLEEP_MODE_IDLE: 15 mA
  • 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

Los registros usados para manejar el modo sleep:

  • Sleep Mode Control Register The Sleep Mode Control Register contains control bits for power management. When addressing I/O Registers as data space using LD and ST instructions, the provided offset must be used. When using the I/O specific commands IN and OUT, the offset is reduced by 0x20, resulting in an I/O address offset within 0x00 – 0x3F.
    Name:  SMCR
  • MCU Control Register When addressing I/O Registers as data space using LD and ST instructions, the provided offset must be used. When using the I/O specific commands IN and OUT, the offset is reduced by 0x20, resulting in an I/O address offset within 0x00 – 0x3F.
    Name:  MCUCR
  • Power Reduction Register
    Name:  PRR

Sleep mode select del registro SMCR:

En avr-libc la librería que gestiona el modo sleep es <avr/sleep.h>

Más información:

Librerías Modo Sleep Arduino

La librería más ampliamente usada es la low power:

También hay otras librerías como Enerlib http://playground.arduino.cc/Code/Enerlib o usar las funciones de avr-libc http://www.engblaze.com/hush-little-microprocessor-avr-and-arduino-sleep-mode-basics/

Con la librería lowpower es muy fácil poner en modo sleep a Arduino con una línea como:

LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

Hay tres maneras de despertar un Arduino del modo Sleep:

  • Interrupciones hardware
  • Timers y WDT que es un timer un tanto peculiar
  • UART o puerto serie.

Si por un error de programación dejamos arduino en modo sleep permanente, hay que vaciar la flash de programa y la forma más sencilla es reinstalar reprogramarlo con el blinking led o cualquier otro programa que no incluya instrucciones de dormir.

En este caso estamos usando el Watch Dog Timer y es una interrupción periódica que se dispara, si el contador llega a 0. EL WatchDog Timer acepta diferentes periodos de disparo, de entre una tabla:

  • SLEEP_15MS
  • SLEEP_30MS
  • SLEEP_60MS
  • SLEEP_120MS
  • SLEEP_250MS
  • SLEEP_500MS
  • SLEEP_1S
  • SLEEP_2S
  • SLEEP_4S
  • SLEEP_8S
  • SLEEP_FOREVER

Esta sencilla instrucción (powerdown) es la de menor consumo de energía, pero hay otros modos que pueden mantener encendidos ciertos circuitos del procesador interno del UNO y del Nano y pueden ser útiles:

  • idle
  • adcNoiseReduction   
  • powerDown
  • powerSave
  • powerStandby   
  • powerExtStandby
  • standby

Lista de lo que hace cada modo:

Le pasamos dos parámetros más además del tiempo de despertar, que son:

  • ADC_OFF: Apaga los convertidores Analógico a digital
  • BOD_OFF: Apaga el circuito de Brown Out Detection, que es un circuito para detectar niveles bajos de tensión. Si no fuera por este detector BOD, cuando las pilas se fueran agotando la tensión podría descender de un cierto nivel y dañar los circuitos. Apagarlo ayuda a reducir consumo, pero ciertamente corres otros peligros.

Usar el WatchDog Timer (del que ya hemos hablado) para despertar cada 8 segundos es una solución, sin embargo en un proyecto que requiera tomar lecturas cada media hora, despertar nuestro MCU cada 8 segundos es excesivo, cuando tenemos que estrujar al máximo la capacidad de la batería.

Para solucionar esto hay un modo de dormir nuestro procesador especialmente útil, que es el de duérmete sin fecha de despertar, pero despierta cuando recibas una interrupción, es decir cuando ocurra algo que estamos esperando.

Para ello usamos el ejemplo:

void loop()
   {   	attachInterrupt( 0, ServicioBoton, FALLING);
   	LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
   	detachInterrupt(0);

   	if (n != contador)
      	{     Serial.println(contador);
            	n = contador ;
            	Serial.flush();
      	}
   }

La primera línea del loop() engancha una interrupción llamada ServicioBoton que se dispara cuando usamos el pulsador, y que simplemente incrementa contador, para saber cuántas veces se ha pulsado.

La segunda línea, pone nuestro Arduino a dormir ay va a seguir así hasta que reciba una interrupción. Cuando detecte una interrupción hardware en el pin 2, despierta súbitamente, Incrementa el valor de contador y sigue el ciclo normal del programa, donde se encuentra lo primero con un detachInterrupt, es decir, deshabilitamos las interrupciones hasta que hagamos nuestra tarea, que en este caso son simplemente comprobar si contador (Que se incrementó con la interrupción) es diferente de n (El valor último registrador de contador) y si es así imprime el valor de contador.

Fijaros que no estamos haciendo un debouncing del pulsador. Sería una muy mala idea hacerlo aquí con un delay, porque el tiempo que durase el delay, nuestro procesador está activo y consumiendo y eso es algo que no interesa.

También usamos un flush() al final para asegurarnos de que se vacía la cola.

Ejemplo de reducción de consumo:

Tutorial en 5 partes sobre modo sleep:

También hay otra librería de bajo consumo de JeeLib. Para reducir el consumo al máximo lo mejor es utilizar un microcontrolador solamente y en el skech incluir la librería de bajo consumo JeeLib.

JeeLib es una colección de ficheros de cabecera, clases y sketches de muestra para su uso con el IDE de Arduino. Fue escrito y extendido durante los años para simplificar la experimentación y la exploración del JeeNode y otros productos de JeeLabs.

La clase sleepy es muy sencilla de usar y muy eficaz para hacer sketchs de bajo consumo y su uso está documentada en: http://jeelabs.org/pub/docs/jeelib/classSleepy.html

Más información:

Arduinos Compatibles Bajo Consumo

En el mercado tenemos modelos de Arduino y compatible diseñados para tener bajo consumo y ser alimentados por batería. Combinando este HW con una programación eficiente podemos lograr dispositivos alimentados por batería durante años:

Estas placas están diseñadas para consumir poco y usan elementos eficientes. Como se puede ver son placas que prescinden de elementos innecesarios simplificando mucho las placas.

El arduino UNO es altamente ineficiente puesto que el diodo de protección y el regulador de tensión consumen mucho aunque la MCU esté en modo sleep. Intentar alimentar una placa Arduino UNO con una pila de 9V no es posible si quieres que dure más de un día.

Moteino es una plataforma de desarrollo compatible con Arduino inalámbrico de bajo coste de bajo consumo basada en el popular chip ATmega328p utilizado en Arduinos tradicionales, lo que la hace 100% compatible con el IDE de Arduino. Moteino no incluye un convertidor USB-Serial (como los Arduinos tradicionales), en su lugar es necesario utilizar un adaptador FTDI externo para cargar los sketches, las ventajas son un menor costo y menor tamaño. Sin embargo, hay una variante MoteinoUSB que el convertidor serie integrado. Son dispositivos compatibles con Arduino que utilice el popular transceptor HopeRF RFM69 o el RFM12B más antiguo. Moteino también viene con un chip de memoria flash SPI opcional para programación inalámbrica o registro de datos.

Más información:

Para Arduinos alimentados por batería es interesante usar un dispositivo de medida de voltaje de la batería y saber su capacidad.Esto puede medirse directamente de la batería usando un divisor de tensión:

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s