Saltar al contenido

EEPROM con Arduino

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:

EEPROM Arduino

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.

EEPROM 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

EEPROM Arduino 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.