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:
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:
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.
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
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.