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 valores descrision
memoria posibles
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.
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);
}
}
}
No hay comentarios:
Publicar un comentario