Memória EEPROM no Arduino (interna e externa)

Memória EEPROM no Arduino (interna e externa)

Olá pessoal, me chamo Fabiano Arndt e esse é meu primeiro artigo aqui no Sistemas Embarcados, (espero que o primeiro de muitos outros). Sou formado em Sistemas de informação e Técnico em Eletromecânica. Atualmente trabalho com desenvolvimento de sistemas e tenho feito alguns vídeos e artigos sobre Arduino. Pra quem tiver curiosidade, Inscreva-se no meu canal e na minha página no Facebook:

www.facebook.com/dicasarduino
www.youtube.com/fabianoallex

Nesse primeiro artigo vou falar sobre memória EEPROM (Electrically-Erasable Programmable Read-Only Memory). Ela é uma memória não volátil utilizada para guardar informações que devam ser recuperadas em momentos futuros, mesmo após o dispositivo ser totalmente desligado.

Internamente a EEPROM é dividia em bytes, podendo cada byte ser acessado individualmente através de seu endereço, que na verdade seria nada mais que a posição do byte na memória.

Há um detalhe que devemos nos atentar ao gravar dados na EEPROM: a quantidade de vezes que é permitido gravarmos dados nela. Pois a mesma é limitada. Em geral não chega ser um problema, já que a quantidade gira em torno de centena de milhares de escritas, sendo um problema apenas se as gravações forem muito constantes. Uma dica pra evitar gravações desnecessárias, seria verificar antes da gravação, se o byte que está sendo gravado, não é igual ao que já está gravado. Se for bastaria ignorar a parte da escrita, já que leituras não diminuem a vida útil da memória.

E no Arduino, como faz?

Primeira coisa que precisamos saber é o quanto de memória temos. Conforme podemos ver em seus datasheets, os Atmegas possuem as seguintes quantidades de memória:

ATmega 48A/PA ATmega 88A/PA – 168A/PA ATmega328/P ATmega 640/V-1280/V-1281/V-2560/V-2561/V
256 bytes 512 bytes 1 Kbytes 4 Kbytes
  • Pra saber quanto de memória tem seu Arduino, é só descobrir qual Atmega ele usa. 😉

Bem, como podemos ver na tabela, não é muito, mas já é alguma coisa. Coisas como Senhas, flags, configurações, modos de operação, e outros detalhes parecidos podem ser gravados na EEPROM.

No Arduino, para gravarmos dados na EEPROM podemos utilizar a biblioteca <EEPROM.h>. Para lermos um determinado byte, basta fazermos a seguinte chamada:

enquanto que para gravarmos:

E para limparmos todos os dados da EEPROM, poderíamos fazer o seguinte:

Como vimos, os dados são gravados de byte em byte, mas quando programamos o Atmega utilizamos memórias que muitas vezes são maiores que 1 byte. Um int por exemplo, ocupa dois bytes, um long 4, etc. Nesses casos, o que deve-se fazer, é dividir a informação na quantidade de bytes que compões o tipo de dado. Vamos ao exemplo de um int:

Para outros tipos de dados, deve-se criar a rotina considerando a quantidade de dados a serem gravadas. É importante observar também, que se for passado o endereço 19, por exemplo, para gravar um int, serão gravados dados nas posições 19 e 20. Se fosse implementada uma rotina para gravar long, e passássemos o endereço 19, a informação seria gravada nas posições 19, 20, 21 e 22. Portanto, essas posições não podem ser utilizadas pra gravar outras informações, sob o risco de perda de informações por sobreposição.

Dados corrompidos

No datasheet há algumas informações sobre como evitar que dados sejam corrompidos na hora da gravação. Basicamente esses erros podem ser causados por Alimentação (Vcc) insuficiente (como uma bateria fraca) a qual dificultaria a CPU e a EEPROM operarem apropriadamente. Veja o que diz o datasheet sobre como evitar esse tipo de problema (sim, em inglês):

“Keep the AVR RESET active (low) during periods of insufficient power supply voltage. This can be done by enabling the internal Brown-out Detector (BOD). If the detection level of the internal BOD does not match the needed detection level, an external low VCC reset Protection circuit can be used. If a reset occurs while a write operation is in progress, the write operation will be completed provided that the power supply voltage is sufficient.”.

#Ficaadica aí, mas hoje não iremos entrar nesses detalhes.

EEPROM Externa – AT24C256

Em algumas situações pode ser interessante o uso de um módulo de EEPROM externo. Basicamente por dois motivos, por ser necessária mais memória, ou justamente pelos benefícios oferecidos por um módulo externo. Por exemplo, Nosso Arduino poderia ter uma função que lesse informações de um modulo de EEPROM externa, o qual conteria dados de configuração da aplicação, e que seriam lidas da memória externa e gravadas na memória interna, e depois de lidas, resetaria o Arduino iniciaria com as novas configurações. Muito útil em aplicações parametrizadas.

Um CI interessante para isso é o utilizado nesse módulo, o CI Serial AT24C256:

24c256 arduino memória eeprom

Esse módulo possui 32 Kbytes de memória EEPROM (lembrando que há também o modelo de 16K, AT24C128) que pode ser acessado via I2C e opera entre as faixas de tensões de 2.7 a 5.5V. Os Jumpers nos pinos A0, A1 e A2 são utilizados para definir o endereço no barramento I2C. O Jumper no pino WP é utilizado para proteger o CI de escrita, ou seja, somente leitura.  Enquanto os demais pinos (SCL e SDA) são responsáveis pela comunicação I2C com os outros dispositivos, no nosso caso, o Arduino.

Para mais informações é bom uma conferida no datasheet:
http://www.atmel.com/Images/doc0670.pdf

Montagem

Arduino – AT24C256

5V – Vcc
GND – GND
A5 – SCL
A4 – DAS

AT24C256 - arduino memória eeprom

Depois de conectados todos os pinos, vamos à parte de programação. Pra isso iremos utilizar a biblioteca <wire.h> do Arduino. Veja mais informações sobre a biblioteca aqui: http://www.arduino.cc/en/Reference/Wire.

Endereçamento

Quando utilizamos comunicação via i2c, um ponto importante é o endereçamento de cada dispositivo, já que todos são ligados no mesmo barramento. Na figura anterior temos quatro jumpers, mas vamos nos ater nos pinos e pinos A0, A1 e A2. São eles que definem quem irá receber os dados e garantem que um dispositivo errado não receba dados que seriam de outro dispositivo. Na imagem abaixo podemos ver, como montar o código de endereçamento de um dos nossos AT24C256.

i2c_register arduino memória eeprom

Como podemos ver o endereço i2c é formado por sete bits (Slave address). Esse é o endereço que devemos utilizar sempre que pretendemos ler ou escrever alguma informação no dispositivo desejado. No caso do AT24C256, os quatro primeiros bits são fixos, ou seja, eles são ligados internamente no próprio CI e não podem ser alterados, sobrando os últimos três para serem configurados. Considerando que os três estejam ligados em LOW, teríamos a seguinte sequencia 1010 000 que convertido pra hexadecimal, seria igual a 0x50. Caso tivéssemos um segundo dispositivo ligado ao Arduino, teríamos que ter um endereçamento diferente para ele. Poderíamos, por exemplo, alterar o bit A0 para HIGH. Nesse caso nossa sequência seria a seguinte: 1010 001, ou 0x51.

Essa tabela talvez facilite a definição do endereçamento para outras combinações dos pinos A0, A1 e A2:

A2 A1 A0 I2C Address
1010 0 0 0 0x50
1010 0 0 1 0x51
1010 0 1 0 0x52
1010 0 1 1 0x53
1010 1 0 0 0x54
1010 1 0 1 0x55
1010 1 1 0 0x56
1010 1 1 1 0x57

Envio de dados (modos byte write e page write)

Quando vamos gravar um byte na eeprom, podemos enviar um byte apenas e gravá-lo em determinado endereço. Isso é o que se chama de byte write. Para isso é necessário iniciar a transmissão, informar o endereço do dispositivo, informar o endereço na memória eeprom, informar o valor a ser gravado, finalizar o envio de dados e aguardar 5 milissegundos que é o tempo que o CI demora pra gravar as informações. Como podemos notar são vários passos até que a informação seja de fato gravada. Se tivermos mais de um byte para ser gravado na memória, teríamos que repetir todos os passos. Tudo isso somando e multiplicado por várias execuções torna o envio de múltiplos bytes um pouco lento. Para isso existe a possibilidade de se iniciar a transmissão de dados, e na sequencia, enviar sucessivos bytes, de modo que os mesmos sejam gravados sequencialmente. Esse é o modo de escrita page write.

byte_page_write arduino eeprom

Exemplo básico, usando byte write:

Page Write

Em relação ao modo de envio page write há algumas considerações importantes na hora de trabalharmos com ela. Não quero me aprofundar muito no assunto, pois esse artigo ficaria bem cansativo, então vou me atear a pelo menos citar o que acontece, e vou deixar aqui um link bem interessante para quem quer entender melhor como resolver os problemas citados. http://www.hobbytronics.co.uk/eeprom-page-write. Ou ainda um vídeo que fiz sobre o assunto, que está disponível ao final do artigo.

A primeira coisa que precisamos ter em mente é que as páginas internas na EEPROM são divididas em grupos de 64 bytes. Não aceitando o envio de mais que 64 bytes por vez. Outro detalhe, é que os limites iniciais das páginas são fixos. Por exemplo, a primeira página começa no byte 0 e vai até o byte 63. A segunda página começa em 64 e termina em 127. Isso significa que não é possível o envio de informações que Iniciam em uma parte páginas e termina em outra página distinta. Por exemplo, tentar enviar uma página do byte 50 e terminar no byte 70, mesmo que não tenha ultrapassado os 64 bytes máximos de envio, violaria essa regra, e na pratico o que aconteceria, é que as informações que estão além do último byte da página (63), seriam gravadas no início da página, na posição errada. Nesse caso, a informação deveria ser dividida em duas partes, enviando os dados do byte 50 até o 63 e depois enviar do endereço 64 ao endereço 70. Ou seja, os dados seriam divididos em duas páginas. Mas isso ainda não é tudo. Temos que lidar ainda com uma limitação da biblioteca wire a qual possui um cache interno de 32 bytes. No link que eu passei anteriormente, é mostrado uma implementação em Arduino que visa tratar desses detalhes.

Vídeo

Atualização 13/04/2016

Ae Pessoal, nesses dois dias fiz uma classe pra facilitar a gravação e leitura na memória EEPROM. o Código-fonte tá no meu blog pessoal.

Confiram lá! http://fabianoallex.blogspot.com.br/2016/04/arduino-memoria-eeprom.html

 

Que tal nos encontrar no SeuTubo para ver dicas, tutoriais e Reviews de placas? Canal Sistemas Embarcados

Que tal na página do Facebook?

Ou Instagram?

Quem sabe Google Plus?

Que tal no Pinterest?

Ou talvez nos encontrar no Twitter para receber as ultimas noticias quentinhas: @SEmbarcados

E não esqueça que também tem o email, [email protected]

Conheça também nossos grupos do Facebook:

Forte abraço e até o próximo embarcado.

Related Post