Um recurso nem sempre utilizado no Arduino é a gravação de dados na memória EEPROM do microcontrolador. Com esse método de armazenamento, você grava os dados em uma parte, digamos, “protegida” da memória, de forma que eles não se perdem quando acontece uma queda de energia, ou mesmo em casos de travamento do Arduino.

gravar dados arduino memoria EEPROM

EEPROM significa Electrically-Erasable Programmable Read-Only Memory (ou, Memória Somente de Leitura Programável Apagável Eletricamente) e é uma memória que pode ser apagada e reprogramada várias vezes, apesar de possuir um limite no número de ciclos de leitura/escrita.

Gravando na EEPROM no Arduino

A quantidade de memória EEPROM varia conforme o modelo da placa. O Arduino Uno(microcontrolador ATMega328), tem 1 KB de memória EEPROM. Já o Arduino Mega (microcontrolador ATMega2560) tem 4 KB. No Arduino Nano com microcontrolador ATMega168, esse valor cai para 512 bytes.

O comando para escrever na memória EEPROM é o EEPROM.write(endereço, valor), e exige o uso da biblioteca EEPROM , que já faz parte da IDE do Arduino.

endereço tem o valor inicial em 0, e vai até a capacidade total da memória EEPROM. Assim, se você estiver trabalhando com um Arduino Uno, você tem 1024 posições de memória pra gravar os dados, um byte (8 bits) de cada vez, ou seja, o maior valor que você consegue gravar em uma posição de memória é 255:

8 bits = 1 byte

A leitura é feita pelo comando EEPROM.read(endereço). Veja neste programa de exemplo:

//Programa: Escrita e leitura EEPROM
//Autor: Arduino e Cia

//Carrega a biblioteca
#include <EEPROM.h>

//Numero a ser armazenado
int numero = 123;
int endereco = 0;

void setup()
{
  Serial.begin(9600);
}

void loop() 
{
  //Escrita
  Serial.print("Gravando numero na memoria EEPROM : ");
  Serial.println(numero);
  EEPROM.write(endereco, numero);
  delay(2000);
  //Leitura
  Serial.print("Lendo numero da memoria EEPROM : ");
  Serial.println(EEPROM.read(endereco));
  while(1)
  {}
}

Mas se cada posição armazena apenas um byte, como eu vou armazenar um número inteiro (2 bytes) na EEPROM?

Gravando um número inteiro na memória EEPROM

Um INT (inteiro) no Arduino Uno e em outras placas baseadas no ATMega, é um número entre -32.768 e 32.767, que ocupa 2 bytes (16 bits) de memória.

Uma das maneiras de gravar um número inteiro na EEPROM é separar esse número em duas partes, e gravar cada uma separadamente.

Digo “uma das maneiras”, porque você pode utilizar as próprias funções da biblioteca para gravar dados na EEPROM, usando os comandos abaixo:

void eeprom_write_word (uint16_t *__p, uint16_t __value)

void eeprom_write_float (float *__p, float __value)

void eeprom_write_block (const void *__src, void *__dst, size_t __n)

A primeira opção, por exemplo, utiliza o uint16_t, que é um unsigned int de 16 bits, cujo valor vai de 0 a 65.535.

No meu método mais arcaico, eu armazeno o INT dividindo-o em duas partes : primeiro divido o número que desejo armazenar por 256, obtendo a primeira parte, e depois uso a função % (modulo), para obter a segunda parte. Posteriormente, coloco cada uma delas em um endereço de memória diferente.

Eu faço isso no programa abaixo, gravando o número 23767 na memória separando-o assim:

Primeira parte : 23767 / 256 = 92 (apenas a parte inteira do número)

Segunda parte :  23767 % 256 = 215 (resto da divisão)

Depois de ler o valor em memória, preciso montar novamente o valor original, juntando as 2 partes. Para isso uso:

Valor original = (parte1 * 256) + parte2

//Programa: Escrita e leitura EEPROM - INT
//Autor: Arduino e Cia

//Carrega a biblioteca
#include <EEPROM.h>

//Numero a ser armazenado
int numero = 23767;
//Endereco onde sera armazenada a parte1 (primeiro byte)
int endereco1 = 0;
//Endereco onde sera armazenada a parte2 (segundo byte)
int endereco2 = 1;

void setup()
{
  Serial.begin(9600);
}

void loop() 
{
  Serial.print("Gravando numero na memoria EEPROM : ");
  Serial.println(numero);
  
  //Grava a primeira parte do numero em endereco1
  EEPROM.write(0, numero/256);
  Serial.print("Parte 1 : ");
  Serial.println(numero/256);
  
  //Grava a segunda parte do numero em endereco2
  EEPROM.write(1, numero%256);
  Serial.print("Parte 2 : ");
  Serial.println(numero%256);
  
  delay(2000);
  
  //Leitura
  Serial.println("nLendo numero da memoria EEPROM... ");
  
  Serial.print("Lendo parte 1 : ");
  int parte1 = EEPROM.read(0);
  Serial.println(parte1);
  
  Serial.print("Lendo parte 2 : ");  
  int parte2 = EEPROM.read(1);
  Serial.println(parte2);
  
  Serial.print("Valor original : ");
  int valor_original = (parte1 * 256) + parte2;
  Serial.println(valor_original);
  while(1)
  {}
}

Isso quer dizer que a partir de agora você pode gravar todos os dados na memória EEPROM do Arduino? Infelizmente não.

Segundo o datasheet do ATMega328P , temos um limite de ciclos de leitura e escrita na memória EEPROM. Esse número é de aproximadamente 100.000 ciclos.

Apesar de ser um número relativamente grande, procure usar um intervalo maior para gravação, ou utilize-o apenas para valores essenciais, como por exemplo os valores máximo e mínimo de um sensor de temperatura.

Gostou? Então confira outros posts utilizando Arduino aqui mesmo no Arduino e Cia!

3.9/5 - (11 votes)