Tradutor

quarta-feira, 13 de março de 2013

Aumente a memória de seu arduino



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();
}
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.

6 comentários:

  1. Olá Magnus, tudo bom?
    Fiquei 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.

    ResponderExcluir
  2. Mas especificamente usar como acesso do microcontrolador para carregar o programa *.hex, isso eh possivel??

    ResponderExcluir
    Respostas
    1. Desculpe pela demora na resposta.
      Correto!
      Vc pode usar apenas com expansão de memória (Leitura e escrita). Pode usar para guardar algumas bibliotecas desenvolvidas para seu projeto.

      Excluir
  3. 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!

    ResponderExcluir
    Respostas
    1. Sim 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.

      Excluir
  4. Olá amigo vc sabe qual atmega de 28 pinos tem mais memoria que o atmega 328
    Preciso de um com a mesma pinagem porém maior capacidade

    ResponderExcluir