Usare Libreria Wire I2C Arduino con EEPROM 24AA1025

Premessa:

Abbiamo realizzato molte guide per principianti con questa guida cominceremo a realizzare guide sempre più articolate. In un articolo precedente abbiamo spiegato come usare la libreria Wire I2C di Arduino con tutte le sue varie funzioni e la logica per utilizzarla. (Consigliamo di leggere l’articolo precedente per capire bene ogni passaggio che verrà trattato). In questa guida spiegheremo come usarla. Per cominciare spieghiamo ai lettori che è replicabile con la stra grande maggioranza di memorie EEPROM sul mercato. Noi abbiamo scelto una memoria da 1024K per maggiore capienza di dati. L’integrato che andiamo ad utilizzare e che troverete nel nostro Shop si chiama EEPROM 24aa1025.

LISTA DEI MATERIALI:

Perchè usare una memoria EEPROM aggiuntiva?

Alla domanda possiamo rispondere semplicemente pensando alla memoria limitata del nostro microcontrollore Arduino, un limite che può essere facilmente superato con l’aggiunta di più memorie EEPROM che si possono gestire con un solo Arduino grazie alla libreria Wire, che permette, tramite 2 soli pin di realizzare un sistema MASTER SLAVE e riuscire a gestire contemporaneamente più memorie.

Vediamo come:

ComeUsareEEPROM1024K24aa1025conArduinoLibreriaWireI2C

i pin A0, A1, A2 permettono di specificare l’indirizzo del dispositivo sul bus I2C, i pin Vcc e Vss sono rispettivamente l’alimentazione (5Vdc) e la massa (Gnd), il pin WP (Write Protect) abilita (se collegato a Gnd) o disabilita (se collegato a Vcc) la scrittura della EEPROM, i pin SCL e SDA sono relativi al collegamento I2C.

Come abbiamo detto precedentemente abbiamo utilizzato l’integrato EEPROM 24aa1025. Questa memoria la possiamo facilmente collegare al nostro Arduino UNO Tramite i Pin Bus I2C:

  • A4 SDA
  • A5 SCL

Vediamo un’immagine per rendere l’idea dei vari collegamenti tra la memoria e l’arduino:

SchematicEEPROM24aa1025Arduino

I collegamenti sono abbastanza semplici quanto complessi nell’utilizzo. Come possiamo vedere in questo caso abbiamo abbiamo tre pin della memoria A0 A1 A2 che sono collegati a massa per un motivo ben preciso. Questi pin permettono di personalizzare l’indirizzo del dispositivo all’interno del bus I2C, quindi possiamo utilizzare più memorie eeprom contemporaneamente. Se da costruttore ogni memoria avrebbe avuto lo stesso indirizzo ci troveremo il problema di indirizzi duplicati. Invece avendo 3 bit gestibili possiamo dare loro un valore high low e avere la possibilita di n combinazioni di indirizzi da utilizzare quindi maggiore numero di eeprom.

StrutturaEEPROMWireI2C24aa1025

Vediamo infatti da immagine che il Control Code da datasheet della nostra memoria è impostato a 1 0 1 0 quindi i 4 bit più significativi sono preimpostati. mentre i bit A0, A1 e A2 sono personalizzabili da noi. Il bit meno significativo R/W, serve per selezionare una operazione di scrittura o una operazione di lettura.

Al nocciolo avendo a massa i pin A0, A1 e A2 ci troveremo un valore low e quindi tutti impostati a zero. L’indirizzo del dispositivo è quindi il seguente: 1010000

StrutturaBitOttenutaEEPROM24aa1025

Dato che ci troviamo a programmare con arduino per convenzione andiamo a convertire in esadecimale il valore dell’indirizzo binario della memoria EEPROM slave.

1010000 in esadecimale corrisponde a 0x50

La memoria 24AA1025 possiede 1024Kbit di memoria, quindi le locazioni di memoria che possiamo scrivere e leggere sono 128000 byte (1024000 / 8).
Avendo a disposizione 2 byte per selezionare l’indirizzo (Address High Byte e Address Low Byte) possiamo utilizzare una variabile int (formata appunto da 2 Byte) che impiegheremmo per specificare il valore dell’indirizzo della locazione di memoria (da 0 a 127999).

La libreria Wire non permette comunque di passare un valore intero perciò potremmo semplicemente effettuare una operazione bitwise per dividere la variabile intera in due byte. Fortunatamente esistono già delle funzioni che semplificano questa operazione, highByte e lowByte.

Vediamo il codice quello che faremo e scrivere le prime 1200 locazioni della memoria e tramite il seriale andremo a rileggere i vari valori ottenuti:

 

#include <Wire.h>
 
int indirizzo = 0;
int data = 0;
int ciclo = 0;
 
void setup()
{
  Serial.begin(9600);
  //attendiamo la seriale
  while (!Serial)
  {
    ;
  }
  delay(5000);
  //invio un messaggio al serial monitor
  Serial.println("Start");
 
  //inizializzo la porta I2C della Arduino
  Wire.begin();
}
 
void loop()
{
  //avviso dell'inizio della
  //scrittura dei dati sulla seriale
  Serial.println("Inizio Scrittura");
 
  //init variabile
  indirizzo = 0;
 
  //eseguo ciclicamente la scrittura di
  //1200 locazioni di memoria
  for(ciclo = 0; ciclo < 1200; ciclo++)
  {
    //invio il control byte specificando
    //una richiesta di scrittura
    Wire.beginTransmission(0x50);
 
    //invio due byte contenenti l'indirizzo della
    //locazione di memoria che voglio scrivere un byte
    Wire.write(highByte(indirizzo));
    Wire.write(lowByte(indirizzo));
 
    //scrivo un byte nella locazione di memoria
    //precedentemente selezionata
    Wire.write(byte(data));
    //fine trasmissione
    Wire.endTransmission();
 
    //incrementa il valore di data
    data++;
 
    //quando la variabile data arriva a 255
    //resetto il suo valore a zero
    if(data == 255)
      data = 0;
 
    //incrementa il valore dell'indirizzo
    indirizzo++;
 
    //attendi 5ms per poter terminare le operazioni di
    //scrittura sulla memoria
    delay(5);
  }
 
  //avvisami quando la scrittura di 1200 byte
  //è terminata
  Serial.println("Fine Scrittura");
 
  //attendi 1/2 secondo
  delay(500);
 
  //avvisami dell'inizio della lettura
  Serial.println("Inizio lettura");
 
  //init variabile
  indirizzo = 0;
 
  for(ciclo = 0; ciclo < 1200; ciclo++)
  {
    //invio il control byte specificando
    //una richiesta di scrittura
    Wire.beginTransmission(0x50);
 
    //invio due byte per selezionare la locazione
    //di memoria da leggere
    Wire.write(highByte(indirizzo));
    Wire.write(lowByte(indirizzo));
 
    Wire.endTransmission();
 
    //incremento la variabile indirizzo
    indirizzo++;
 
    //richiedo un byte al 24AA1025
    Wire.requestFrom(0x50, 1);
    //attendo la disponibilità di dati sul bus i2c
    while(Wire.available())
    {
      Serial.print(ciclo);
      Serial.print(": ");
 
      //leggo dal bus il dato relativo alla
      //locazione di memoria precedentemente specificata
      byte c = Wire.read();
 
      //invio il dato al serial monitor
      Serial.println(c);
   }
 }
 
 delay(1000);
}

Buon Progetto.