Memória não Volátil EEPROM do ESP8266
EEPROM é um tipo de memória não volátil presente na maioria dos sistemas e micro controladores, já que quase sempre é preciso guardar dados para que sejam lidos mesmo após a uma queda de energia por exemplo. Nesse tutorial você aprenderá a usar essa memória não volátil do ESP8266 usando o NodeMCU
O principal propósito da EEPROM, é guardar as informações (em Bytes) para que possamos ler a qualquer momento, e caso o sistema venha a reiniciar ou algo do tipo, as informações se manterão intactas
[toc]
Sobre a EEPROM
EEPROM, é uma memória não volátil, mas tem um limite relativamente pequeno de gravações (no ESP8266). Isto faz com que devemos tomar cuidado para por exemplo, não colocar as funções de gravação em loop’s. Normalmente é utilizada para armazenar dados sobre a inicialização do sistema ou algo relacionado que não seja necessário ser alterado com muita frequência.
O ESP8266 não tem EEPROM dedicada, porém, há uma emulação em um segmento da FLASH de 4B até 4096KB. Cada Byte da EEPROM no ESP8266, tem um limite de 10mil gravações e “infinitas” leituras. Sabendo disto, tome cuidado para não extrapolar nas gravações; a leitura é permitida quantas vezes forem necessárias.
Alguns exemplos práticos para a EEPROM:
- Manter a maior temperatura alcançada de um sensor.
- Guardar variáveis que o usuário inserir após o inicio padrão do sistema também é comumente usado, por exemplo, alocar as novas credenciais do WiFi após o cliente comprar o produto novo.
- Salvar o último dia em que um motor parou de funcionar para gerar relatórios.
As aplicações da EEPROM são as mais diversas e variadas. Pode estar presente na maioria dos projetos já que é facilmente manipulável.
Mãos à obra – Utilizando a EEPROM do NodeMCU
Componentes utilizados
Software
#include <EEPROM.h> void setup() { Serial.begin(9600);//Inicia a comunicação Serial. Serial.println();//- Serial.println();//-Apenas para "limpar" a tela. EEPROM.begin(4);//Inicia a EEPROM com tamanho de 4 Bytes (minimo). Serial.println(EEPROM.read(0));//Mostra no Monitor oque há antes de efetuar a gravação if (EEPROM.read(0) != 18)//Se não existir o numero escolhido (18), irá gravar. Isto é necessário para evitar regravações desnecessárias. { EEPROM.write(0, 18);//Escreve no endereço "0", o valor "18". EEPROM.commit();//Salva o dado na EEPROM. Serial.println(EEPROM.read(0));//Mostra o valor no endereço 0 novamente. } else//Se já existir o valor, irá avisar. { Serial.println("Dado ja cadastrado"); } EEPROM.end();//Fecha a EEPROM. } void loop() { }
Entendendo a fundo
Software
-Função EEPROM::begin()
EEPROM.begin(4);
Necessária sempre que for ler ou escrever na EEPROM. O parâmetro é o tamanho de inicialização, que precisa estar entre 4 até 4096. Neste caso, foi iniciado o mínimo possível, 4 Bytes.
-Função EEPROM::read()
EEPROM.read(0);
Faz a leitura do endereço desejado, retornando um valor UINT8 (0 até 255). No caso do exemplo do tutorial, usamos o primeiro endereço da EEPROM, que é “0”. Você pode escolher qualquer endereço desde que esteja entre o parâmetro usado no begin().
-Função EEPROM::write()
EEPROM.write(0, 18);
Escreve no endereço X, o valor Y. No caso do exemplo, escrevemos no endereço “0“, um número qualquer, “18“. Esta escrita deve ser feita em UINT8 (0 até 255), caso seja necessário valores maiores, precisara usar mais Bytes da EEPROM.
-Função EEPROM:commit()
EEPROM.commit();
Esta função salva o que escrevemos anteriormente, sem isto, não irá salvar! Também pode ser feito pelo comando EEPROM.end(), que também efetua o commit().
-Função EEPROM::end()
EEPROM.end();
Fecha a EEPROM. Lembre-se que após usar esta função, não é possível escrever ou ler valores da EEPROM!
Curiosidades
Ao efetuar um teste que mostra o valor de cada Byte da EEPROM, os 4 primeiros Bytes do meu ESP8266 já estavam com valores modificados. Penso que tenha sido alguma biblioteca externa ou ?…. Teste você mesmo e diga nos comentários se também havia algo alterado!
Código para efetuar a leitura completa da EEPROM:
#include <EEPROM.h> void setup() { Serial.begin(9600); Serial.println(); Serial.println(); EEPROM.begin(4096);//Inicia toda a EEPROM. for (int i = 0; i < 4097; i++)//Loop que irá mostrar no Serial monitor cada valor da EEPROM. { Serial.print(EEPROM.read(i)); Serial.print(" "); } EEPROM.end();//Fecha a EEPROM. } void loop() { }
Desafio
O desafio desta vez, é maximizar a eficiência da EEPROM, salvando dados de um sensor apenas quando for maior que o anterior. Assim, estendendo a vida útil dela.
Fechamento
Você aprendeu a usar a EEPROM de micro controladores de um jeito muito fácil. Agora, podemos salvar dados e mante-los mesmo caso a alimentação seja cortada, ou o MCU seja reiniciado. Dúvidas? Sugestões? Críticas? Comente abaixo!
Estudante de Engenharia da Computação pela USC, pretende se aprimorar e fazer a diferença nesta imensa área da tecnologia. Apaixonado por IoT, sistemas embarcados, microcontroladores e integração da computação nos mais diversos fins práticos e didáticos.
22 Comments
Deixe uma pergunta, sugestão ou elogio! Estamos ansiosos para ter ouvir!Cancelar resposta
Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.
tenho uma duvida quanto a velocidade de leitura da eeprom, costumo transferir dados da eeprom para Ram que serão usados depois . Seria sensato ler diretamente da eeprom sem precisar ocupar espaço em ram. A velocidade de leitura é muito pode trazer problemas ?
Olá, gostaria de saber como declarar uma constante na memoria eeprom, por exemplo, gostaria de gravar um código na eeprom durante a gravação do programa. Algo parecido com o PROGMEM . Como fazer?
Uma pergunta: SPIFFS também tem vida útil ? Pois usa a memoria flash…
Claro!
Muito bom
Obrigado José,
a linha “EEPROM.commit();” fez toda a diferença no meu caso. Estou usando NODEMCU e querendo salvar na EEPROM as configurações passadas por formulários WEB. Procurei em vários fóruns e só aqui achei a causa do erro.
gravei dados de um contador e estava indo tudo bem mais depois de alguns reset começou aparecer números muito autos. Augues sabe o porque ou de onde vem
É possível gravar letras? Gostaria de gravar uma palavra.
Letras individuais por endereço sim. Para salvar palavras, terá que salvar letra a letra e ler letra a letra…
Uma duvida, o ESP32, tem que ser uma outra programação?
Creio que não, mas como é um micro bem diferente, talvez possa dar algum problema. Só vai saber testando :S
Pergunta besta: o contador das 10 mil gravações possíveis de serem feitas zera após o EEPROM.end ou após limparmos a EEPROM? Como limpar a EEPROM? Se selecionar o mesmo espaço alocado ele substituirá o valor já existente?
Cada byte (posição) da memória tem uma vida útil e você não pode “apagar ou zerar” esse “contador”. O que fazem normalmente é escrever o dado em outras posições (wear leveling).
Eu ponho o commit dentro do laço for, ou pode ser fora? Exemplo:
for ( uint8_t j = 0; j < 4; j++ ) { // Loop 4 times
EEPROM.write( start + j, a[j] ); // Write the array values to EEPROM in the right position
}
Pode ser fora ou dentro! Porém, acho mais interessante dentro para garantir escrita caso falte alimentação no MCU e etc, assim, não perderá todos os dados. Mas a diferença é mínima e possivelmente não vai perceber na pratica.
Se a epron é emulador na memória FLASH pq o que gravamos na memória FLASH Não permanece após reiniciar o esp?
Permanece sim! Tanto que seu código continua lá mesmo após você reiniciar. As informações que são perdidas é da RAM.
Boa noite! Pergunta besta…. essas 10 mil gravações valem apenas para quando eu dou o comando “commit” ou quando eu já dou o comando “EEPROM.write” ele já consome esse contador?
Obrigado!
Bem Renan, creio que seja apenas com o commit(), visto que se você não der o commit() e tentar ler a EEPROM após o restart, não terá o valor salvo. Eu nunca fiz o teste pra ver os limites da EEPROM pois tenho amor aos poucos Bytes do meu ESP, mas você pode testar e chegar a alguma conclusão, embora eu realmente ache que só “conta” após o commit().
Show! eu tbm acho! me parece que quando eu dou o comando write, o numero fica em alguma memória flutuante mesmo… Era só para somar conhecimento, muito obrigado!
Na verdade, os dados são escritos na RAM quando write é executado e no CHIP quando o commit é executado.
Yep!