
Arduino é uma placa de interface entre o computador e
circuitos eletrônicos porem possui limitações de portas, velocidade e tamanho
de memória fazendo com que programas mais complexos não caibam dentro da placa.
Atualmente o Arduino UNO é baseado no ATMega328 que utiliza 32kB de memória
flash onde 0,5KB é destinado para o bootloader, 2KB de memória SRAM e 1KB de
memória EPROM.
Para que possamos entender melhor cada memória vamos a
alguns termos:
- Memória Flash - é uma memória do tipo não volátil, o que significa que não precisa de energia para manter as informações armazenadas, oferece um tempo de acesso rápido, embora não tão rápido como a memória volátil DRAM ou SRAM, são extremamente duráveis, sendo capaz de resistir a uma pressão intensa, variações extremas de temperatura, e até mesmo imersão em água.
- Memória SRAM (Static Random Access Memory) - é um tipo de memória de acesso aleatório que mantém os dados armazenados desde que seja mantida sua alimentação, não precisando que as células que armazenam os bits sejam refrescadas (atualizadas de tempo em tempo), como é o caso das memórias DRAM, ou seja, enquanto existir energia os dados serão armazenados. Embora sejam mais caras e ocupem menos espaço, quando comparadas às DRAM, possuem a vantagem de serem bem mais rápidas.
- Memória EPROM (erasable programmable read-only memory) - é um tipo de chip de memória de computador que mantém seus dados quando a energia é desligada, geralmente utilizando para armazenar seus programas. Existe a EEPROM que utiliza a eletricidade para gravar e apagar os dados da memória.
Para aumentar a capacidade da placa podemos utilizar chips extras de memória como o chip AT24C com dois modelos, sendo o primeiro com 256kb (32K bytes) e o segundo com 512KB (64K bytes), este módulo utiliza conexão I2C bus para conectar ao Arduino, para comunicação da EEPROM recomendamos uma interface Arduino-I2C-COM-Cable, Arduino Special Sensor Shield V4.0, ou através de cabos.
Este módulo de armazenamento é baseado no chip AT24C que através do I2C pode endereçar 0x50 e os últimos
três endereços de memória podem ser setados de acordo com as necessidades. Ou
seja, devemos setar pelo menos três endereços quando utilizado pela primeira
vez através das quatro posições do DIP switch. Coloque a alavanca para cima e
corresponderá a 1 e coloque a alavanca para baixo e corresponderá a 0, movendo
os endereços A0, A1, A2 para cima corresponderá a 0x57, mas movendo os
endereços A0, A1, A2 para baixo corresponderá a 0x50.
Se você usar o Arduino Sensor Shield preste atenção à posição
do jumper IIC/COM que deve estar setada como IIC porque precisaremos usar I2C
para conecção.
Observe o código abaixo:
#include <Wire.h>
#define EEPROM_ADDR 0x50 // Endereço do I2C Buss para 24LC256 256K EEPROM
void setup()
{
Wire.begin(); // Acessa I2C bus (endereço opcional para master)
Serial.begin(9600);
// TESTE PARA CADA FUNÇÃO COMEÇA AQUI
Serial.println("Writing Test:");
for (int i=0; i<20; i++){ // loop dos primeiros 20 slots
i2c_eeprom_write_byte(EEPROM_ADDR,i,i+65); // escreve endereço + 65 A ou 97 a
Serial.print(". ");
delay(10); // É PRECISO ESTE ATRASO!
}
Serial.println("");
delay(500);
Serial.println("Reading Test:");
for (int i=0; i<20; i++){ // loop dos primeiros slots
Serial.print(i2c_eeprom_read_byte(EEPROM_ADDR, i),BYTE);
Serial.print(" ");
}
// Configura página de teste . . .
byte PageData[30]; // Vetor que irá conter os dados de teste para um página
byte PageRead[30]; // Vetor que irá conter o resultado dos dados para um página
for (int i=0; i<30; i++){ // Zera os dois vetores para o próximo teste
PageData[i] = 0;
PageRead[i] = 0;
}
Serial.println("");
for (int i=0; i<30; i++) PageData[i] = i+33; // preenche o vetor para o proximo teste char 33 = !
Serial.println("Writing Page Test:");
i2c_eeprom_write_page(EEPROM_ADDR, 100, PageData, 28 ); // máximo de 28 bytes/page
Serial.println("Reading Page Test:");
i2c_eeprom_read_buffer( EEPROM_ADDR, 100, PageRead, 28);
for (int i=0; i<28; i++){
Serial.print(PageRead[i],BYTE); // mostra o vetor read
Serial.print(" ");
}
}
void loop()
{
}
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data )
{
int rdata = data;
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddress & 0xFF)); // Endereça o Byte como baixo
Wire.send(rdata);
Wire.endTransmission();
}
// Endereça a pagina de endereço, 6-bit (63).
// Mas o dado pode ser no máximo 28bytes, porque a biblioteca Wire tem um buffer de 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length )
{
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddresspage >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddresspage & 0xFF)); // Endereça o Byte como baixo
byte c;
for ( c = 0; c < length; c++)
Wire.send(data[c]);
Wire.endTransmission();
delay(10); // Precisa de um pouco de atraso
}
byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress )
{
byte rdata = 0xFF;
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddress & 0xFF)); // Endereça o Byte como baixo
Wire.endTransmission();
Wire.requestFrom(deviceaddress,1);
if (Wire.available()) rdata = Wire.receive();
return rdata;
}
// Não deve ler mais que 28 bytes por vez!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length )
{
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddress & 0xFF)); // Endereça o Byte como baixo
Wire.endTransmission();
Wire.requestFrom(deviceaddress,length);
//int c = 0;
for ( int c = 0; c < length; c++ )
if (Wire.available()) buffer[c] = Wire.receive();
}
#define EEPROM_ADDR 0x50 // Endereço do I2C Buss para 24LC256 256K EEPROM
void setup()
{
Wire.begin(); // Acessa I2C bus (endereço opcional para master)
Serial.begin(9600);
// TESTE PARA CADA FUNÇÃO COMEÇA AQUI
Serial.println("Writing Test:");
for (int i=0; i<20; i++){ // loop dos primeiros 20 slots
i2c_eeprom_write_byte(EEPROM_ADDR,i,i+65); // escreve endereço + 65 A ou 97 a
Serial.print(". ");
delay(10); // É PRECISO ESTE ATRASO!
}
Serial.println("");
delay(500);
Serial.println("Reading Test:");
for (int i=0; i<20; i++){ // loop dos primeiros slots
Serial.print(i2c_eeprom_read_byte(EEPROM_ADDR, i),BYTE);
Serial.print(" ");
}
// Configura página de teste . . .
byte PageData[30]; // Vetor que irá conter os dados de teste para um página
byte PageRead[30]; // Vetor que irá conter o resultado dos dados para um página
for (int i=0; i<30; i++){ // Zera os dois vetores para o próximo teste
PageData[i] = 0;
PageRead[i] = 0;
}
Serial.println("");
for (int i=0; i<30; i++) PageData[i] = i+33; // preenche o vetor para o proximo teste char 33 = !
Serial.println("Writing Page Test:");
i2c_eeprom_write_page(EEPROM_ADDR, 100, PageData, 28 ); // máximo de 28 bytes/page
Serial.println("Reading Page Test:");
i2c_eeprom_read_buffer( EEPROM_ADDR, 100, PageRead, 28);
for (int i=0; i<28; i++){
Serial.print(PageRead[i],BYTE); // mostra o vetor read
Serial.print(" ");
}
}
void loop()
{
}
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data )
{
int rdata = data;
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddress & 0xFF)); // Endereça o Byte como baixo
Wire.send(rdata);
Wire.endTransmission();
}
// Endereça a pagina de endereço, 6-bit (63).
// Mas o dado pode ser no máximo 28bytes, porque a biblioteca Wire tem um buffer de 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length )
{
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddresspage >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddresspage & 0xFF)); // Endereça o Byte como baixo
byte c;
for ( c = 0; c < length; c++)
Wire.send(data[c]);
Wire.endTransmission();
delay(10); // Precisa de um pouco de atraso
}
byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress )
{
byte rdata = 0xFF;
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddress & 0xFF)); // Endereça o Byte como baixo
Wire.endTransmission();
Wire.requestFrom(deviceaddress,1);
if (Wire.available()) rdata = Wire.receive();
return rdata;
}
// Não deve ler mais que 28 bytes por vez!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length )
{
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // Endereça o Byte como alto
Wire.send((int)(eeaddress & 0xFF)); // Endereça o Byte como baixo
Wire.endTransmission();
Wire.requestFrom(deviceaddress,length);
//int c = 0;
for ( int c = 0; c < length; c++ )
if (Wire.available()) buffer[c] = Wire.receive();
}
Veja o resultado abaixo:
Conclusão:
Com este módulo é possível aumentar a memória do Arduino, com isso sendo possível desenvolver programas mais complexos e com mais funções, sendo uma ótima alternativa para seus projetos.
Olá Magnus, tudo bom?
ResponderExcluirFiquei com uma duvida, entendo que neste caso a memoria é usada para arquivar dados do processamento.
Mas especificamente usar como acesso do microcontrolador para carregar o programa *.hex;
Eu desenvolvi um protótipo que o básico funciona muito bem num AT328 mas preciso de mais memoria para implementar outras características funcionais do programa.
Valeu pelos post.
E obrigado pela atenção.
Silvio.
Mas especificamente usar como acesso do microcontrolador para carregar o programa *.hex, isso eh possivel??
ResponderExcluirDesculpe pela demora na resposta.
ExcluirCorreto!
Vc pode usar apenas com expansão de memória (Leitura e escrita). Pode usar para guardar algumas bibliotecas desenvolvidas para seu projeto.
Olá bom dia amigo, parabéns pelo post. Gostaria de saber, seria possível utilizar esse modulo em um arduino nano com o chip Atmega328p ? Muito grato!
ResponderExcluirSim e possivel usar em qualquer arduino ou compativeis o unico que vai precisar fazer e conectar as conexões por cabos e nao pelo shield. Fora isso é ajustar a programação para o arduino especifico que deseja usar.
ExcluirOlá amigo vc sabe qual atmega de 28 pinos tem mais memoria que o atmega 328
ResponderExcluirPreciso de um com a mesma pinagem porém maior capacidade