Traficando datos en la memoria EEPROM de Arduino
Buenas ejército! Después de hablar de cómo reducir la memoria de los programas de Arduino se me escapó algo sobre la EEPROM. Hoy es un buen día para terminar aquello que empezamos. Así que voy a intentar destripar la memoria EEPROM y nos quedamos todos contentos.
¿Por qué lo hago? Porque visto lo visto la memoria es un problema ya que hay la que hay. Y no sé tú, pero yo siempre quiero más 😛
¿Para qué sirve la memoria EEPROM?
La memoria EEPROM es una memoria interna de Arduino. En el fondo es una memoria ROM, que si eres un poco viejuno sabrás que son las imborrables. Pues esta te deja hacer cambios pero pocos (100.000 escrituras). Como lo de pocos cambios es relativo la gente se ha puesto a modificar esta memoria y a utilizarla como la memoria base.
En el fondo es la memoria base ya que es la que contiene cosas como la carga de tus programas a través de USB. Si esta memoria fallase tendrías que pasar tu información por ISP (otro protocolo) y olvidarte de la comodidad del USB. Pero volvamos al redil. ¿Para qué utiliza la gente esta memoria?
Pues la verdad es que se utiliza como la memoria que nunca se toca… o algo así. Me explico. Imagínate que tienes un Arduino que vas a utilizar como estación meteorológica. Tienes tu programa en el IDE de Arduino que se graba en la memoria flash (la típica de Arduino) y has declarado tus variables para calibrar tu sensor de temperatura, el de humedad y el de luz.
Pasa el tiempo y tu estación meteorológica va perfecta y ahora hay dos versiones de la historia:
- Tu estación meteorológica va tan bien que creas una empresa genial que vende miles de estaciones meteorológicas libres que cualquiera puede reprogramar (vaya idea de negocio te acabo de dar… para quien la coja 😉 )
- Tu cuñado dice que puede mejorar la estación añadiendo un nuevo sensor de presión y tú le dejas que lo instale, porque al fin y al cabo, los cuñados lo saben todo.
Al final, sea cual sea la historia lo que acaba pasando es que el sensor de temperatura ya no mide correctamente. Parece que alguien ha tocado algo que no debía, una variable que calibraba el sensor. Y te toca a TI ir a repararlo, claro está. Pues vaya faena…
Para este caso sería útil programar esta calibración que tiene que hacer sí o sí tu Arduino (y que siempre la tendrá que hacer hasta el día que deje de ser una estación meteorológica) en la memoria EEPROM, lejos de manazas que puedan cambiar el código principal y cargarse el objeto principal de tu invento.
Cómo pasar datos a la EEPROM
Lo primero es ver de la memoria de que dispones. En la mayoría de los Arduinos es de 1Kb. ¿Eso es mucho o poco? Comparado con los teras y teras que estamos acostumbrados a guardar en nuestros ordenadores es muy poco. Comparado con la memoria flash de Arduino (32K) es 32 veces menor…
Pero bueno, aún así es suficiente. Al final aquí lo que se manejan son bits y bytes y te están dando espacio para 1024 bytes… ya es. Para manejar estos bytes se utilizan dos comandos básicos: leer y escribir. La nomenclatura en C++ sería:
EEPROM. read(direccion) EEPROM.write(direccion, dato)
Como puedes ver esta memoria funciona a base de direcciones. En realidad todas lo hacen pero Arduino nos oculta ese proceso de dar de alta espacios de memoria y de posicionar variables y datos en ella. La dirección es un simple número: un 1, un 0, un 2… así hasta la 1023 que es el final (1024 menos la posición 0 que también cuenta).
Luego está el dato. Un byte son 256 posibilidades por lo que podrás escribir números del 0 al 255. Si quieres expresar el número 256 ya tendrás que utilizar otro byte. Digamos que el número 256 sería el 255 a tope +1: b11111111 + 00000001.
La b es de binario. Cada byte tiene 8 bits y si cada bit puede ser 1 o 0 (dos estados) te encuentras con 2⁸ oportunidades, que son 256. Empiezo con un ejemplo de escritura y lectura de un byte:
#include <EEPROM.h> int direccion = 90;/*Recuerda que es la posicion 91*/ byte dato; void setup() { } void loop() { dato = EEPROM.read(direccion); direccion = direccion +1; EEPROM.write(direccion, dato); }
Como ves, todo correcto. Ahora vamos a por el caso de 256 bytes que te decía antes:
#include <EEPROM.h> int direccion = 90;/*Recuerda que es la posicion 91*/ int dato = 256; byte byte1; byte byte2; void setup() { byte1 = dato & 0xFF; byte2 = (dato>>8) & 0xFF; } void loop() { EEPROM.write(direccion, byte1); direccion = direccion + 1; EEPROM.write(direccion, byte2); direccion = direccion + 1; }
Ahora son dos bytes y es por eso que hago la movida de el & y el >>. Te explico, el & lo que hace es multiplicar, de manera que multiplico por uno aquello que me interesa y por cero lo que no. 0xFF en hexadecimal es lo mismo que 1111 1111 en binario. Y justo eso es la parte final de mi binario original, es mi último byte.
Luego con el >> lo que hago es mover 8 posiciones (el byte) y se me queda al final la parte que me interesa. Y vuelvo a hacer la operación del & de manera que se me queda mi byte porque el resto se multiplica por cero o ya ha desaparecido porque lo he rotado. La rotación o desplazamiento lo que hace es que la parte delantera se rellene con ceros por lo que al hacerlo el byte anterior se pierde. Al final tendrás los dos bytes rellenos de ceros.
Información básica sobre Proteción de datos
Responsable ➥ Sergio Luján Cuenca
Finalidad ➥ Gestionar el envío de correos electrónicos con artículos, noticias y publicidad. Todo relacionado con los temas de rufianenlared.com
Legitimación ➥ Consentimiento del interesado
Destinatarios ➥ Estos datos se comunicarán a MailRelay para gestionar el envío de los correos electrónicos
Derechos ➥ Acceder, rectificar y suprimir los datos, así como otros derechos, como se explica en la política de privacidad
Plazo de conservación de los datos ➥ Hasta que se solicite la supresión por parte del interesado
Información adicional ➥ Puedes encontrarla en la política de privacidad y el aviso legal
Descifrando los datos de la EEPROM
Claro , esto de varios bytes se utiliza sobretodo cuando estás utilizando un int o un long. Es por eso que supongo que querrás recomponerlos para utilizarlos en tu calibración de la estación meteorológica.
Siguiendo la misma filosofía de antes puedes hacerlo.
#include <EEPROM.h> int direccion = 90;/*Recuerda que es la posicion 91*/ int dato; byte byte1;/*Supongo que es la parte baja*/ byte byte2;/*Supongo que es la parte alta del número*/ void setup() { byte1 = EEPROM.read(direccion); direccion++; byte2 = EEPROM.read(direccion); } void loop() { dato = (byte2 & 0xFF)<<8; dato = byte1 & 0xFF; }
Ya ves, antes cogía y partía en bytes y ahora lo que hago es crear un elemento de muchos bytes al que voy sumando uno a uno (en este caso solamente 2 XD)
Pues estamos buenos con tanto byte saltando por ahí…
Así que aquí me quedo con mis cálculos en binario y en hexadecimal. Espero que no llenes tu memoria. Aunque con lo complicado que lo han puesto para mandar un simple número, a ver quién se atreve a programarse ahí más de cuatro variables sin volverse loco.
¿Nos vemos pronto en los comentarios de ahí debajo? 😉