Hola controleros y controleras en el día de hoy vamos a aprender a usar la memoria interna EEPROM con Arduino, para evitar que los datos importantes almacenados en las variables de nuestro proyecto se pierdan al momento de des energizar nuestra placa de Arduino.
Antes de comenzar el Arduino EEPROM, te hago la invitación para que veas nuestro CURSO GRATIS DE ARDUINO.
EEPROM Arduino
Sabemos que cuando programamos una aplicación en nuestra placa de desarrollo del Arduino, al momento de reiniciar la placa, toda la memoria donde se almacenan las variables y los datos de nuestro proyecto es borrada.
En muchas ocasiones, se hace interesante el poder almacenar datos en Arduino y que estos no se borren al momento de des energizar o reiniciar nuestro Arduino, porque puede ser información crítica o importante que el Arduino calculó o leyó previamente.
Para conseguir esto, el Arduino posee internamente una memoria interna que no se borra cuando es des energizada (memoria no volátil) conocida como la EEPROM (Electrically Erasable Programable Read-Only Memory).
Con esto, podemos entender que el Arduino internamente va a poseer tres tipos de memoria diferentes:
- Memoria Flash Arduino: Es NO Volátil donde es almacena el código que hemos programado en el sketch.
- Memoria SRAM Arduino: (Static Random Acces Memory) Es Volátil y es la encargada de almacenar temporalmente las variables de nuestro programa de Arduino.
- Memoria EEPROM Arduino: Es NO Volátil y será donde almacenaremos los valores de nuestras variables importantes que no queremos perder al reiniciar la placa.
Características de la Memoria EEPROM
Dentro de nuestro Arduino, podremos notar que no disponemos de mucha memoria EEPROM para ser implementada en nuestros proyectos, generalmente disponemos de 1KB de memoria para la mayoría de las placas y de 4KB para el Arduino MEGA. Cada microcontrolador tiene un tamaño específico, segmentado 1 byte por dirección (celda). La lista a continuación ilustra la cantidad de memoria disponible para microcontroladores utilizados en plataformas como Arduino Nano, Arduino Uno y Arduino Mega:
- ATmega8, ATmega168 – 512 bytes
- ATmega328 – 1024 Bytes
- ATmega1280, ATmega2560 – 4096 Bytes
A modo de ejemplo, en la siguiente imagen podemos ver como se distribuye la memoria EEPROM Arduino UNO:
Algo importante para tener en cuenta con esta memoria es que su escritura es lenta, en torno de los 3.3ms y la lectura de cada byte es entorno de 0.3ms.
Las memorias EEPROM tienen una vida útil de aproximadamente 100000 escritas en cada celda de la memoria por lo que no puedes indiscriminadamente estar grabando en esta memoria constantemente porque vas a alcanzar ese límite.
Por eso almacena los datos de tu programa en periodos espaciados en el tiempo, o cuando algún evento especifico suceda.
Como Usar la Memoria EEPROM con Arduino
El propio IDE Estándar del Arduino ya incorpora la librería para la utilización de la memoria, conocida como EEPROM.h, por lo tanto, procederemos de la siguiente forma:
En el encabezado del programa vamos a incluir la librería
#include <EEPROM.h>
Para leer y escribir sobre la memoria interna EEPROM del Arduino usamos las funciones Read y Write respectivamente, donde la direccion corresponde al espacio de memoria (con tamaño de 1byte=8bits). Dicha dirección puede tener valores desde 0 has N-1, donde N es el numero de bytes máximos disponibles en la memoria.
EEPROM.Read(direccion);
EEPROM.Write(direccion,valor);
Con estas funciones podremos salvar diferentes tipos de datos que ocupen 1 byte.
Guardar string en EEPROM arduino
Por ejemplo sabemos que un string está conformado por un arreglo o vector de caracteres, y cada carácter ocupará en la memoria EEPROM 1 BYTE, por lo tanto si deseamos guardar un string en la eeprom de arduino vamos a hacerlo carácter por carácter.
Supongamos que queremos guardar el string = {‘Control’}, que posee 7 caracteres, podríamos valernos de un ciclo for para almacenarlo en la eeprom, supongamos que deseamos guardarlo desde la posición = 0 hasta la posición = 6
char msg[7]={"Control"}; for(i=0;i<7;i++) { EEPROM.Write(i,msg[i]); }
Guardar FLOAT o STRUCTURE en EEPROM Arduino
En muchas ocasiones, vamos a querer grabar datos mayores a 1 byte. Por ejemplo esto es muy usado cuando queremos guardar un float en la eeprom arduino. Recordemos que:
Tipo | Tamaño en memoria | Valores posibles | Descripción |
char | 1 byte | -128 a 127 o 0 a 255 | Guarda caracteres del codigo ASCII |
int | 2 or 4 bytes | -32,768 a 32,767 o -2,147,483,648 a 2,147,483,647 | Guarda numeros enteros, |
float | 4 bytes | 1.2E-38 a 3.4E+38 | Guarda numeros decimales con precisión de 6 digitos decimales |
short | 2 bytes | -32,768 a 32,767 | Guarda numeros enteros con menor capacidad de almacenamiento(y rango) que int |
double | 8 bytes | 2.3E-308 a 1.7E+308 | Igual que Float pero con mayor precisión (hasta 15 digitos decimales) y mayor rango |
long | 4 bytes | -2,147,483,648 a 2,147,483,647 | Guarda numeros enteros con mayor capacidad de almacenamiento que int |
long double | 10 bytes | 3.4E-4932 to 1.1E+4932 | Mucho mayor precisión en calculo decimal, incluso mayor que double (hasta 19 digitos decimales) |
Para esto la librería dispone de las funciones Put, Get y Update:
Para escribir una variable en la dirección address, donde la variable puede ser cualquier tipo.
EEPROM.Put(address, variable)
Para leer una variable en la dirección address
EEPROM.Get(address, variable)
Para Actualizar el valor de una variable si su valor es distinto del que vamos a guardar. Conveniente para reducir el número de escrituras, y alargar la vida útil de la memoria.
EEPROM.Update(address, variable)
Es importante tener cuidado con el tamaño de cada variable que estamos almacenando, para saber cual es la próxima dirección que iremos a escribir y así evitar solapar datos dentro de la memoria. Una forma rápida de saber cuántos bytes ocupa un determinado tipo de variable, es usar el comando de C:
sizeof(tipo);
Por último, si deseamos saber la cantidad de memoria disponible podemos usar
EEPROM.length()
Cuando usamos la librería, se crea internamente una variable que puede ser usada como si fuera un Arreglo llamada EEPROM[índice], de esa forma podríamos grabar o leer directamente cualquier índice de la memoria EEPROM usando ese arreglo.
Ejemplo 1 – Uso del EEPROM con Arduino
En el siguiente ejemplo veremos várias posibilidades para guardar datos en la EEPROM del Arduino, desde guardar 1 byte (via String), guardar un float en la eeprom arduino y mucho más. Todo esto es extensible para otros Arduinos como Arduino UNO, MEGA, NANO, etc.
Cree un sistema de lectura y almacenamiento de voltaje para un potenciómetro. Para eso usaremos el ADC Arduino y el Arduino Keypad 4×4.
Para almacenar (tecla A) o ver (tecla C) el voltaje, haremos un control de acceso con Arduino donde el usuario debe ingresar una contraseña. Se Almacenan 4 valores de voltaje espaciados por 1 segundo a cada lectura dentro de la EEPROM de Arduino.
La contraseña será un número entero de 4 dígitos almacenado en las direcciones EEPROM 0 y 1. El usuario puede cambiar la contraseña con la tecla B, y se debe guardar la contraseña en Arduino dentro de la EEPROM.
El código que veremos a continuación es la base de como hacer una cerradura electrónica con Arduino.
i estás usando pantallas LCD en tus proyectos Arduino, el bus I2C puede ser tu mejor aliado. Descubre cómo hacer la conexión LCD I2C en Arduino para reducir el uso de pines y simplificar el cableado.
Esquema en Proteus
Para descargar el código, basta con compartir este post con cualquiera de los siguientes botones, así contribuyes a que el sitio web continue aportando más contenido de calidad y gratuito. Adicionalmente permites que otras personas que quieran aprender Arduino comiencen a entender esta placa de desarrollo.
Decarga el Archivo .ino y el archivo de proteus 8.7 CLICK AQUI
#include <Keypad.h> #include <LiquidCrystal.h> #include <EEPROM.h> const byte rows = 4; const byte col = 4; const int POT = A3; // Define o pino Analógico (Potenciometro) int value,PW,CurrentPW=1234; float volt; char Key; byte pRows[] = {3,2,1,0}; byte pCol[] = {7,6,5,4}; char teclas[4][4] = {{'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'}}; Keypad teclado = Keypad( makeKeymap(teclas), pRows, pCol, rows, col); LiquidCrystal lcd(13, 12, 11, 10, 9, 8); //(RS, E, D4,D5, D6, D7) void setup() { lcd.begin(16, 2); // Inicia o LCD 16x02 (colunas,linhas) teclado.setHoldTime(1000); //Tempo de espera para o teclado EEPROM.get( 0, PW ); if(PW!=CurrentPW && PW>0){ CurrentPW=PW; } //lcd.print("PW: "); //lcd.print(CurrentPW); //delay(5000); } int password(void){ int pass,i=0; String KeyWord; //Pergunta por os 4 digitos da senha lcd.setCursor(0, 1); while(i<4){ Key=teclado.waitForKey(); //Espera até presionar botão if(Key>='0' && Key<='9'){ lcd.print('*'); KeyWord += Key; //Armazena os caracteres i++; } if(Key=='D'){ i=4; } } if(KeyWord.length()>0){ pass=KeyWord.toInt(); //Converte para Inteiro }else{ pass=0; } return(pass); } void loop() { char KeyOp; int i,j; float vEE[4]; //Leitura do Pino A3 (ADC) value=analogRead(POT); // Armazena o valor inteiro. //Converte o valor inteiro em Tensão volt=(value*5/1023.0); lcd.home(); // Coloca el cursor en las coordenadas (0,0) lcd.print("LEITURA VOLTAGEM"); // Escreve no LCD lcd.setCursor(0,1); // Coloca el cursor en las coordenadas (0,0) lcd.print("POT (V): "); // Escreve no LCD lcd.print(volt); // Escreve no LCD Key=teclado.getKey(); if(Key>='A' && Key<='C'){ KeyOp=Key; lcd.clear(); lcd.home(); // Coloca el cursor en las coordenadas (0,0) lcd.print("Digite a Senha:"); // Escribe no LCD PW=password(); //Valida a senha if(PW == CurrentPW){ if(KeyOp=='A'){ //Gravar 4 valores de Voltagem lcd.clear(); lcd.home(); // Coloca el cursor en las coordenadas (0,0) lcd.print("Salvando..."); // Escribe no LCD //Incrementa o for de 4 em 4 até pegar 4 valores for(i=2;i<2+ 4*sizeof(float);i+= sizeof(float)){ value=analogRead(POT); // Armazena o valor inteiro. volt=(value*5/1023.0); EEPROM.put( i, volt ); //Grava na EEPROM delay(1000); } } if(KeyOp=='B'){ //Trocar a Senha lcd.clear(); lcd.home(); // Coloca el cursor en las coordenadas (0,0) lcd.print("Nova Senha:"); // Escribe no LCD PW=password(); EEPROM.put( 0, PW ); //Grava na EEPROM lcd.clear(); lcd.home(); // Coloca el cursor en las coordenadas (0,0) lcd.print("Senha Salvada!!!"); // Escribe no LCD CurrentPW=PW; delay(2000); } if(KeyOp=='C'){ //Gravar 4 valores de Voltagem lcd.clear(); lcd.home(); // Coloca el cursor en las coordenadas (0,0) j=0; //Incrementa o for de 4 em 4 até pegar 4 valores for(i=2;i<2+ 4*sizeof(float);i+= sizeof(float)){ EEPROM.get( i, vEE[j] ); //le na EEPROM j++; } lcd.setCursor(0,0); for(j=0;j<2;j++){ lcd.print(j+1); lcd.print(')'); lcd.print(vEE[j]); lcd.print("; "); } lcd.setCursor(0,1); for(j=2;j<4;j++){ lcd.print(j+1); lcd.print(')'); lcd.print(vEE[j]); lcd.print("; "); } delay(10000); lcd.clear(); } }else{ lcd.clear(); lcd.home(); // Coloca el cursor en las coordenadas (0,0) lcd.print("Senha ERRADA!!"); // Escribe no LCD delay(2000); } } }
Eso es todo por la entrada del dia de hoy, espero les haya gustado y hayan aprendido algo nuevo. Si te ha servido el contenido de esta entrada, de los videos y los códigos de implementación y deseas apoyar mi trabajo invitandome a un café super barato, puedes hacerlo en el siguiente link:
👉 Invitar a Sergio a un Café ☕️
Que esten muy bien, nos vemos en la siguiente entrada.
Mi nombre es Sergio Andres Castaño Giraldo, y en este sitio web voy a compartir una de las cosas que mas me gusta en la vida y es sobre la Ingeniería de Control y Automatización. El sitio web estará en constante crecimiento, voy a ir publicando material sobre el asunto desde temas básicos hasta temas un poco más complejos. Suscríbete al sitio web, dale me gusta a la página en Facebook y únete al canal de youtube. Espero de corazón que la información que comparto en este sitio, te pueda ser de utilidad. Y nuevamente te doy las gracias y la bienvenida a control automático educación.