Objetivos
Arduino y el modo Sleep
<
Material requerido.
Arduino Uno o compatible y con el firmware para S4A cargado. |
|
Unos cables. | |
Una Protoboard | |
Un multímetro digital. |
Reduciendo el consumo de Arduino
Como vimos en el capítulo previo, Arduino está diseñado más para ser fácil de usar que para consumir poco, sencillamente porque la eficiencia nunca entró en las especificaciones de diseño, hasta muy recientemente.
En la última sesión apuntamos algunas ideas para reducir los consumos pero lo primero que vimos es que un Arduino UNO tiende a consumir uso 45 mA en vacío, mientras que un Nano apena llega a los 15 mA
Ni que decir tiene que sería absurdo usar un Arduino UNO a baterías precisamente porque los circuitos internos de control del USB y especialmente del derrochador regulador de corriente que usa a su entrada, hacen que su consumo sea mucho mayor de lo que nos gustaría y por eso el Arduino Nano aparece como una opción clara para estas ocasiones.
No he tenido ocasión de probar los Arduino Micro, que tiene fama de eficientes, pero espero recibir unos pocos en unos días y ya os daré un reporte sobre ellos (Ya tenían que haber llegado, pero el correo internacional está fatal)
Así que de momento en esta sesión nos centraremos en otra forma de reducir sensiblemente el consumo de nuestro Arduino: El modo Sleep.
El asunto es tan drástico como parece, porque no queremos tener encendido nuestro Duino como un árbol de navidad mientras no hace nada. Lo lógico es apagarlo, o por lo menos, hibernarlo, para que el consumo se reduzca al mínimo posible.
No hemos inventado nada. Los osos y muchos otros animales como serpientes y anfibios suelen invernar en los climas fríos, entrando en un estado de animación suspendida que evita consumir una energía preciosa para llegar a la primavera, en un momento en el que no hay disponible alimento.
Y eso es todo, creo que veréis que es más fácil de lo que parece.
Arduino y el modo Sleep
SI echáis una ojeada por internet con este tema encontrareis mucha información acerca del asunto y con mucha frecuencia, os hablaran de que hay que aprender a programar el chip interno de Arduino, el AVR, y os hablaran de no sé qué extravagancias que hay que hacer para ponerlo a dormir.
La Liberia estándar de Arduino, por ahora no permite acceso a las funciones que hacen dormir al MCU (Micontrolador) y hay que usar la librería AVR directamente, pero para eso están las librerías, que almas generosas ponen a disposición de la comunidad.
Recordad las reglas anti paletos. Hay que asustar a los nuevos y convencerles de que esto es muuuuy complicado y que hay que ser ingeniero para ello. Pero no. Es mucho más simple si usas la librería adecuada.
Así que lo primero que os voy a recomendar es que si eres un usuario promedio y hasta justito no se te ocurra estudiar la librería AVR, es mucho más fácil usar una librería que nos haga el trabajo sucio.
Y el caso del modo Sleep de Arduino no es una excepción. Usa la librería LowPower, es ligera y sencilla de usar, y verás como ella se encarga.
Una vez que descarguéis e instaléis la librería Low-Power-master, os propongo un sencillo ejemplo. Vamos a usar el mismo esquema de la sesión previa para medir el consumo de nuestro Arduino Nano:
El programa de control
Con el montaje descrito arriba vamos a hacer un programa, sencillo que muestre como dormir nuestro Arduino un tiempo, y después cuando despierte, encendemos dos segundos el LED incluido, y de ese modo que podamos hacer una lectura estable del consumo.
Con un poco de suerte veremos que hay dos consumos diferentes. Cuando está dormido y cuando está despierto y de ese modo podremos comparar ambos.
Lo primero es incluir la librería y definir el pin del LED
#include "LowPower.h" int LED = 13 ; void setup() { pinMode(13, OUTPUT); }
Después en el loop, dormimos el Nano un cierto tiempo, en este caso 8 segundos, y cuando despierta, encendemos el led durante 2 segundos, al cabo de los cuales, volvemos a dormir nuestro Duino:
void loop() { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); digitalWrite(LED, HIGH); delay(1000); digitalWrite(LED, LOW); }
La línea clave, por supuesto, es esta:
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
Como veis, simplemente pedimos a la librería que duerma a Arduino 8 segundos y mantenga apagados los convertidores analógico a digital, y el circuito BOD (O Brown Out Detection). Vamos con todo esto.
Si no queréis complicaros más la vida, copiando esta línea, ya dispondréis de un buen ahorro de energía porque duerme a vuestro Arduino 8 segs y después hace lo que le pidamos al despertar.
¿Por qué 8 segundos? Bueno, una de las cosas más complicadas de dormir algo, es decidir cómo despertamos a la bella durmiente, y mucho cuidado aquí, porque si te equivocas puedes dejar tu Arduino por secula seculorum, así que mucho ojo con las pruebas.
Hay tres maneras de despertar un Arduino del modo Sleep:
En este caso estamos usando el Watch Dog Timer y por ahora no quiero entrar detalles, pero nos basta con saber, que es una interrupción periódica que se dispara, si un cierto 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
Como veis, 8 segundos es el máximo valor que podemos usar, pero nada nos impide hacer un bucle de digamos 15 periodos de 4 segundos para hacer un minuto:
for (int i = 0 ; i < 16 ; i++) LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF);
Esto genera un lapso de 4 x 15 segundos = 60, en los que el WDT despierta el micro lo justo para hacer un incremento de la variable i, y volver a dormirse. Y no hay ninguna razón para no hacer lo mismo 4 x 15 x 60 = 1 hora si es lo que queremos.
Esta sencilla instrucción 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 si los necesitáis puede ser útiles:
idle adcNoiseReduction powerDown powerSave powerStandby powerExtStandby standby
Aquí os dejo la lista de modos y que hace cada uno, aunque tengo que reconocer que no veo claro muchas cosas, pero en fin quizás vosotros sí que lo veáis.
Si no queréis complicaciones usad la línea de arriba, que es la de mayor ahorro y listo.
LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF);
Le pasamos dos parámetros más además del tiempo de despertar, que son:
Vale ¿Y qué consumo podemos esperar de semejante apaño? De nuevo hay que medir para saberlo:
No está mal, bajamos de 15 mA a 4.8 al activar el modo Sleep. Y Fíjate en que no he encontrado el modo de apagar el LED testigo de tensión en el Nano, que quieras que no, consume de continuo un par de mA de los 4.8 que consume el Nano dormido.
Si no recuerdo mal, un LED típico tiene una caída de tensión unos 15 mV, que a 5V son 3mA de consumo. Así que si con una cuchilla os aseguráis de cortar una de las pistas que van al LED piloto, probablemente tendrás un consumo de unos 2 mA dormido, lo que no está nada mal.
Si tu Arduino lee un par de sensores en digamos 1 segundo a 15 mA de consumo, y lo hace dos veces por hora, podemos esperar un consumo medio de poco más de 2 mAh, pon 3 mAh, Con una batería de 1200 mA, podrás alimentar tu circuito 1.200 / 3 = 400 horas que son 16 días a palmos.
Pero elegir las baterías y sobre todo combinarlas de un modo eficiente, es un tema con su propia interés y por eso , en el la próxima sesión hablaremos como sacarlas el máximo partido, y por ahora vale la pena dejar el tema aquí.
Resumen de la sesión
Material requerido.
Arduino Uno o similar. Arduino Uno o similar. |
|
Cables de protoboard macho hembra. |
|
Un Nunchuk con adaptador de pines. |
EL NUNCHUK
En esta ocasión vamos a presentar un dispositivo que nos puede dar mucho juego a la hora de realizar proyectos con nuestro Arduino uno o Arduino mega, sobre todo en aquellos relacionados con la robótica. Estamos hablando del Nunchuk de la Wii. El pequeño de los dos mandos que utiliza normalmente esta consola, el que no parece un mando de la tele.
Y es que este mando integra en poco espacio y con un diseño estupendo, un joystick, dos botones y un acelerómetro (si no os suena no os preocupéis, ya hablaremos de este último). Tiene un precio muy razonable, de hecho los tenéis en la tienda de esta misma página por unos 11 euros, y además viene con un adaptador con una tira de pines para facilitar la conexión.
El Nunchuck funciona mediante el bus I2C, así que solo vamos a necesitar un par de cables para controlarlo, además de los propios para la alimentación del mando. Sólo tenéis que tener en cuenta que en teoría funciona a 3.3V, y por lo demás el – va a tierra, d (data) a SDA y c (Clock) a SCL, que en el Arduino Uno corresponden a los pines A4 y A5.
Y como casi siempre, hay algunas librerías que nos van a facilitar mucho la programación. Hay varias aunque todas son bastante parecidas, pero nosotros hemos utilizado esta: WiiChuck. Esta vez tenemos que incluirla de una manera diferente a la que solemos hacerlo. Lo que tenéis que hacer es descomprimir el archivo que habéis descargado dentro de la carpeta «libraries» que está en el directorio en el que instalasteis el IDE.
EL JOYSTICK Y LOS BOTONES
Bueno, pues toca meternos en harina, y vamos a empezar por el joystick y los dos botones, que son los componentes del mando con los que más familiarizados estamos.
Vamos a hacer un programa que nos permita ver en el monitor serie las medidas del joystick y si los botones están pulsados o no. Como veréis, la programación es muy sencilla gracias a la librería que estamos utilizando.
#include "Wire.h" //Libreria I2C #include "WiiChuck.h" //Libreria WiiChuck WiiChuck chuck = WiiChuck(); //Creamos la instancia de WiiChuck void setup() { Serial.begin(115200); //Configuramos la velocidad del puerto serie chuck.begin(); //Iniciamos WiiChuck } void loop() { delay(20); chuck.update(); //Actualizamos los valores //Imprimimos los valores por pantalla Serial.print("Eje X: "); Serial.print(chuck.readJoyX()); //Eje X del Joystick Serial.print(" "); Serial.print("Eje Y: "); Serial.print(chuck.readJoyY()); //Eje X del Joystick Serial.print(" "); //Boton Z if (chuck.buttonZ) Serial.print("Z"); else Serial.print("-"); Serial.print(" "); //Boton C if (chuck.buttonC) Serial.println("C"); else Serial.println("-"); }
Aquí podéis descargar el programa completo:
Y si abrimos el monitor serie veremos algo como esto:
EL ACELERÓMETRO
El otro componente que incluye este mando es un acelerómetro. Y, ¿qué es un acelerómetro? Pues un instrumento para medir aceleraciones (sí, no me he quedado calvo con esto…) , y quién más y quién menos lo usamos todos los días, porque nuestros preciados smartphones contienen uno. En nuestro caso, al igual que en los teléfonos, el acelerómetro del Nunchuk es capaz de medir aceleraciones en los 3 ejes: X, Y, Z.
Estos dispositivos pueden tener muchas aplicaciones, por ejemplo, para hacer saltar un airbag de un coche en caso de que detecte una aceleración muy fuerte. Incluso creo que están intentando usarlo para desarrollar aplicaciones en los móviles, de forma que si tienes un accidente, por ejemplo una caída en moto, el móvil detecte ese cambio brusco en la aceleración y envíe un mensaje de socorro inmediato.
Pero nosotros lo vamos a utilizar con otro fin, que es el de determinar la posición del mando a partir de las medidas de las aceleraciones. Y es q si recordamos nuestras clases de física, resulta que la fuerza de la gravedad provoca una aceleración en todos los cuerpos en la superficie de la Tierra de 9,8.
Por lo tanto si tenemos el acelerómetro en posición horizontal, paralelo al suelo, deberíamos tener esa aceleración en el eje Z y una aceleración de 0 en los otros dos ejes. Pero si inclinamos el acelerómetro en cualquier dirección (ejes X o Y), estás medidas cambiarán. Pues a partir de estas tres medidas podemos calcular utilizando la trigonometría el ángulo de los ejes X e Y y determinar la posición del mando.
¿Y qué pasa con el eje Z? Pues que es imposible saber la posición en este eje con un acelerómetro, ya que la aceleración de la gravedad es paralela a este eje.
No vamos a entrar a explicar el cálculo de los ángulos a partir de las lecturas, porque no queremos aburrir a nadie; y además la librería lo va a hacer por nosotros.
La programación va a ser igual de sencilla que en el apartado anterior, pero usando otras funciones de la librería. Además habrá que incluir la librería math.h, necesaria para el cálculo de los ángulos.
#include <math.h> #include "Wire.h" //Libreria I2C #include "WiiChuck.h" //Libreria WiiChuck WiiChuck chuck = WiiChuck(); //Creamos la instancia de WiiChuck void setup() { Serial.begin(115200); chuck.begin(); } void loop() { delay(20); chuck.update(); Serial.print("Posicion: Eje X: "); Serial.print(chuck.readRoll()); //Posicición eje X Serial.print(" Eje Y: "); Serial.print(chuck.readPitch()); //Posición eje Y Serial.print(" *** "); Serial.print("Lecturas: "); Serial.print((int)chuck.readAccelX()); //Lectura eje X Serial.print(" "); Serial.print((int)chuck.readAccelY()); //Lectura eje Y Serial.print(" "); Serial.println((int)chuck.readAccelZ()); //Lectura eje Z }
Aquí tenéis el programa completo: nunchuk_acelerometro,
Y el resultado en el monitor serie, en el que mostramos tanto las medidas del acelerómetro como la posición de los ejes X e Y. Si inclináis el mando en esos veréis como cambian las medidas y la posición en los ejes X e Y.
Resumen de la sesión
En esta sesión hemos aprendido varias cosas importantes: