Icono del sitio Programar fácil con Arduino

#127 Memoria de Arduino y alimentación ESP8266

Hoy nos toca otro capítulo de las preguntas de los oyentes donde resuelvo dudas sobre cuestiones relacionadas con Arduino, ESP8266 y programación. En esta ocasión hablaré de la memoria de Arduino y opciones a la hora de alimentar un ESP8266.

Recuerda que puedes mandar tus preguntas a través del formulario de contacto. Intenta, antes de mandar la pregunta, hacer una búsqueda en Internet. Seguro que alguien ha tenido el mismo problema que tu y ya está resuelto.

En el podcast también hablo de la Feria Lucentum Maker que se celebrará los días 17 y 18 de febrero en Las Cigarreras en Alicante. Dentro de la feria va a haber charlas, talleres, expositores y carreras de drones.

Por supuesto que yo estaré allí como parte de la organización. Si vas no dudes en saludarme, me encanta charlar con todos vosotros sobre Arduino o lo que surja.

Dicho esto vamos a comenzar resolviendo la primera pregunta de memoria de Arduino.


Problema con la memoria de Arduino

Angel Ropero

Hola Luis,

Estoy esperando un proyecto que me tiene que entrar para inscribirme a tu campus, ya que voy a necesitar ayuda importante sobre NodeMCU. Me voy a tomar la licencia de hacerte una consulta que espero tengas a bien ayudarme, por favor, ya que de esto también depende el proyecto que te comento.

Tengo un problema con la memoria RAM de un programa en Arduino NANO, ya que defino una serie de mensajes a Display como “const” en un archivo.cpp y me está guardando todos esos datos en la RAM en vez de en memoria de programa. Como consecuencia de esto, al declarar como 40 mensajes del display (16×2), la reserva de memoria llega casi al 70%, mientras la memoria de programa se queda en el 35%. Supongo que te habrá pasado algo similar en el pasado, ya que cuando esto ocurre, sale un mensaje del compilador que se está llegando a una situación donde podría “haber resultados inesperados”.

He leído en algún sitio que definiéndolo como #define MENSAJE1 “Esto es una prueba”, o similar, ahí realmente sí se declara en memoria de programa, pero la verdad he sido incapaz de que me compile la aplicación.

Una vez más discúlpame abordarte así de esta manera, pero me resultaría de gran ayuda resolver este problema y pasar todos esos mensajes a memoria de programa y liberar RAM.
¿Serías tan amable de ayudarme por favor? Muchas gracias de antemano.

Lo primero que tenemos que saber es que tenemos 3 tipos de memorias en un Arduino o en cualquier otro microcontrolador. Existe la memoria Flash, la SRAM y la EEPROM. Vamos a ver para qué se utilizan cada una de ellas.

Memoria Flash de Arduino

Básicamente se utiliza para guardar el programa que hemos escrito en el IDE de Arduino. Normalmente es la más grande y es como el disco duro de nuestro ordenador. Esta memoria no se borra o elimina si la placa se queda sin alimentación.

En ocasiones viene integrado dentro del propio chip y en otras, como sucede con el ESP8266, no viene integrado dentro del propio chip pero si en la placa o en el SoC.

Por ejemplo, Arduino UNO tiene el microcontrolador ATmega328 que tiene una memoria Flash de 32 kb. No podemos utilizar todo el espacio ya que 5 kb están reservados para el gestor de arranque. Así que tendríamos 27 kb disponibles.

Otro ejemplo es NodeMCU. Dependiendo de la versión, lo típico es que la memoria se integre en el SoC ESP-12E. Este chip tiene 4 Mb de memoria Flash lo que viene a ser 4.000 kb es decir, 125 veces más memoria que el ATmega328.

La memoria Flash es un punto crítico en nuestros proyectos con Arduino o ESP8266, sin embargo tenemos bastante margen como hemos visto.

Memoria EEPROM de Arduino

Se trata de una memoria del mismo tipo que la memoria Flash, no volátil es decir, que aunque se quede sin energía se mantienen los datos. La diferencia es que utiliza una tecnología más antigua. Su uso principal es guardar ajustes y otros parámetros para ser cargados al iniciar la placa.

Otra diferencia entre estas dos memorias son las escrituras. Estas memorias tienen una fecha de caducidad y es cuando se llega al máximo de escrituras en la memoria.

Para la memoria Flash el máximo es de 10.000 escrituras y para las EEPROM es de 100.000 escrituras. Estos máximos son para cada celda de memoria. Se suele utilizar el acceso aleatorio de la memoria para ir repartiendo el consumo de escrituras.

¿Cómo podemos acceder a la EEPROM? Pues gracias a una librería podemos guardar, modificar y obtener datos de esta memoria de una forma muy sencilla a través de un programa de Arduino.

Memoria SRAM de Arduino

La memoria estática de acceso aleatorio o SRAM (del inglés Static Random Access Memory) se encarga de almacenar las variables cuando se ejecuta el programa. Cuando hablo de guardar las variables me refiero al valor que hay dentro.

Se trata de una memoria volátil es decir, que cuando se queda sin energía los datos se borran. Pasa lo contrario que con la memoria Flash y la EEPROM.

Pero tengo que hacer una aclaración. Ya hablé en el Curso de Arduino de cómo funcionan las variables y las memorias. Cuando declaras una variable, estás reservando la memoria SRAM que necesita esa variable.

Por ejemplo, si queremos almacenar un número entero positivo y negativo utilizamos el tipo de dato más común, el entero o int. Este tipo de dato ocupa 2 bytes y puede almacenar números del -32.768 al 32.767.

Pero da lo mismo si almacenas el 0 o el 30.000, en los dos casos, cuando declaras la variable se reservan esos 2 bytes en la memoria SRAM de Arduino. Aquí es donde puede complicarse más la cosa.

Para un Arduino UNO, el microcontrolador ATmega328 tiene una SRAM de sólo 2 kb es decir, 2.000 bytes. Esto significa que si un int ocupa 2 bytes, sólo podremos almacenar 1.000 variables.

La verdad es que es complicado encontrar un programa que tenga 1.000 variables de este tipo, pero todo puede pasar.

En cambio, el SoC ESP-12E tiene una memoria SRAM de 64 kb, 32 veces mayor que el ATmega328.

Aunque parezca mucho también podemos llegar a tener problemas la memoria SRAM. Por ejemplo, cada letra que almacenamos en la memoria de Arduino, ocupa 1 byte. Si quieres almacenar textos largos puede que no tengas suficiente ni con los 64 kb del ESP-12E.

Así que debemos tener mucho ojo en este sentido. Siempre tenemos que ser conscientes del rango de valores que vamos a almacenar en una variable y elegir el tipo de dato más adecuado.

Si por ejemplo queremos almacenar el número de pin en una variable ¿qué tipo de dato es el más adecuado? En estos casos siempre tenemos que utilizar el tipo de dato byte. Su rango es de 0 a 255 y es más que suficiente para todos los pines de cualquier tipo de Arduino.

Además sólo ocupa 1 byte y así estaremos optimizando la memoria SRAM de nuestro microcontrolador.

Solución

El problema de Angel es debido al gran número de mensajes que tiene que enviar al display LCD 16×2. Esto hace que su memoria SRAM se consuma muy rápidamente. Existen varias soluciones al respecto que voy a pasar a enumerar.

Si tienes una comunicación con otro sistema ya sea a través de una red o del puerto serie, intenta transferir todos los datos y cálculos a ese sistema. Puede ser, por ejemplo, una Raspberry Pi.

Optimiza todo lo que puedas el tipo de datos de array o matrices. Como hemos visto antes con el ejemplo del pin, utiliza el tipo de dato que menos ocupe.

Pero también existe otra opción para optimizar el uso de la memoria RAM. En este caso sería guardar ciertas variables en la memoria Flash. Esto sólo es válido si esas variables no se van a modificar en todo el programa como es el caso de Angel.

En este caso puedes utilizar el modificador de variables PROGMEM que es parte de la librería pgmspace pero se incluye automáticamente dentro del IDE de Arduino.

Lo que hace es decir al compilador que guarde la información en la memoria Flash y siempre se tiene que utilizar con variables constantes.

Para indicar que guarde los datos en la memoria Flash con declarar la variable sólo tienes que poner el modificador cuando declaras la variable después del nombre.

Sin embargo, a la hora de obtener el valor de la variable se deben utilizar funciones especiales que propornciona la librería pgmspace. Se recomienda ver la referencia de esta librería para utilizar la función dependiendo del tipo de dato.

Y con esto, damos por zanjado el problema de memoria de Arduino de Angel.

Fuentes

Alimentación ESP8266 con baterías

Felipe Cupito de Buenos Aires Argentina

Hola como estas,

Estoy haciendo un proyecto con el esp8266 conectado con Thingspeak.

La idea es alimentarlo con una batería y mandar el voltaje a Thingspeak para saber cuanta carga le queda a la batería.

La pregunta sería qué tipo de batería y mAh me recomiendas y como seria el código en el IDE de Arduino para medir el voltaje.

Gracias

Se trata de una pregunta muy interesante y difícil de dar una respuesta única. Por eso he acudido a un experto en estos temas, el gran Germán Martín que nos habla de las baterías de fosfato de litio y hierro o LiFePo4.

Según nos cuenta Germán, esta pregunta la podemos encontrar en el canal de YouTube de Andreas Spiess donde en los vídeos 64 y 65 trata este tema.

En estos vídeos, Andreas habla de las baterías recomendadas para alimentar el ESP8266. La conclusión es que las baterías recomendadas son las LiFePo4.

Esto es debido a que estas baterías tienen una tensión más adecuada para alimentar el ESP8266 al contrario que las típicas LiPo.

Tienen una tensión máxima de 3,6 V y una tensión mínima de 2 V entando dentro del rango de tensiones válidas para alimentar el ESP8266 que está entre 3 V y 3,6 V.

Esto supone varias ventajas. Lo primero es que no necesitas tener un regulador de tensión para alimentar el ESP8266 lo que nos lleva a que nuestro sistema gane en eficiencia.

Por otro lado, puedes medir la tensión directamente con el ADC (Conversor Analógico Digital o pines analógicos). Si utilizas por ejemplo un NodeMCU puedes conectarlo al pin analógico A0 directamente.

Por último, las baterías LiFePo4 aguantas más ciclos de carga que las baterías LiPo y son más seguras ya que no tienen peligro de explosión como las baterías LiPo.

Sin embargo, las baterías LiFePo4 también tienen pegas. Una de ellas es su capacidad ya que es menor que las baterías LiPo.

Elegir una capacidad u otra depende de cada proyecto. Es importante conocer cuál es el consumo de cada proyecto. Si además hacemos una estimación de cuánto queremos que duren las baterías, esto nos dará los mAh que deberán tener nuestras baterías.

Para ayudarte a saber cuánto durará una batería, te recomiendo que entres en alguna calculadora del tiempo de vida de una batería donde poniendo unos cuantos datos, te dará una aproximación de cuánto durará tu batería.

En cuanto al código es muy sencillo. Sólo tienes que conectar la salida de la batería al pin analógico de tu ESP8266. Luego con la sentencia analogRead(A0) te dará la tensión que está suministrando dicha batería.

Pero para que esto funcione correctamente, tendrás que calibrar los valores obtenidos. Primero cuando la batería está cargada y segundo cuando está descargada y ya no es posible suministrar la suficiente energía al ESP8266.

Por otro lado, también se pueden utilizar baterías LiPo o pilas de 1,5 V. En el primer caso, como comenta Germán, necesitarás utilizar un regulador de tensión debido a que las baterías LiPo pueden suministrar una tensión entre 3,5 V y 4,3 V.

Dependiendo de la placa que estés utilizando, superar el máximo voltaje permitido para la alimentación puede dañar la placa. Un ejemplo lo tenemos con Arduino MKRFOX1200 donde la documentación oficial hace especial énfasis en no alimentar esta placa con este tipo de baterías.

Otro ejemplo puede ser Arduino MKR1000 donde hay un conector JST para baterías LiPo. La propia placa ya incorpora un regulador de tensión y podríamos alimentar un Arduino MKR1000 directamente con una batería LiPo.

Si por el contrario lo que quieres es alimentar con dos pilas de 1,5 V, ya sea AA o AAA, necesitarás utilizar un Boost DC DC. Esto hace lo contrario que un regulador de tensión. El Boost DC DC sube la tensión a 3,3 V manteniendo estable esta tensión.

En todos los casos, la forma de medir el voltaje de la batería es el mismo, a través de un pin analógico. También puedes ver el tutorial donde te muestro cómo medir la carga de una pila o batería con un Arduino UNO.

Esperamos haberte ayudado Felipe con estas opciones y muchas gracias por contactar con nosotros.

Conclusiones de memoria de Arduino y alimentación ESP8266

Hemos visto en este artículo cómo debemos tener mucho cuidado con la memoria de Arduino y cualquier otro microcontrolador. Al final, debemos ser conscientes que estamos trabajando con un chip que su finalidad es hacer una cosa concreta.

No se trata de un ordenador, un dispositivo al que nos acostumbramos a utilizar muchos recursos. La memoria Flash es donde se almacenan los programas y, aunque esta dotada de más capacidad, debemos ser muy cuidadosos.

Con respecto a la memoria RAM de un microcontrolador, es donde tenemos que poner todo nuestro énfasis a la hora de optimizar el código. En esta memoria almacenamos los datos volátiles es decir que se eliminan cuando el microcontrolador se queda sin alimentación.

Es importante conocer qué tipo de datos vamos a almacenar para elegir el tipo de variable que vamos a utilizar. No te importe perder algo de tiempo en este aspecto ya que será muy beneficioso para tu proyecto.

Por otro lado hemos visto como podemos alimentar un ESP8266. Existen diferentes formas que te paso a enumerar:

Y con esto damos por finalizado este artículo.

¿Has tenido el mismo problema con una memoria de Arduino?

¿Cómo alimentas un ESP8266 en tus proyectos del IoT?

Me encantaría que compartieras tus proyectos y experiencias en los comentarios de este artículo :)


Puedes escuchar este programa en,  iVooxiTunes y en Spreaker. Si lo haces, por favor valora y comenta, así podremos llegar a más gente.

Gracias a Shutterstock por la la cesión de la Imagen.

Salir de la versión móvil