Salve ragazzi, mi è da poco venuta l'idea di creare un data logger con il mio Arduino UNO, da collegare al pc ed interfacciare con un programma in C# che riceva e visualizzi i dati.
Dispongo di questa EEPROM I2C: I2C EEPROM - 256k Bit (24LC256) - COM-00525 - SparkFun Electronics
E' ho trovato questo codice per poterla gestire: Arduino Playground - I2CEEPROM
Mi servirebbe qualche spiegazione in più su come è fatta un memoria EEPROM, ho cercato su internet ma non ho trovato ciò che mi interessava. Girovagando per il web ho visto che si accennava a "pagine" di memoria, cosa significa? (Fra l'altro nel codice per gestire l'eprom si trova una funzionechiamata i2c_eeprom_write_page(), a cosa si riferisce?).
Come mi ricavo l'indirizzo del dispositivo (deviceandress)? Nel codice è 0x50 dove ha preso questo valore?
'deviceaddress' refers to the EEPROM I2C address, eg. 0x50.
per la ram funziona così, credo che sia lo stesso:
dato che con un solo indirizzo non riusciresti ad accedere a tutti i byte, i byte vengono raggruppati in pagine. quindi si può dire che una pagina è un array di byte. Tu prima accedi alla pagina:
Una EEPROM non è altro che una memoria non volatile.
Può essere di tipo seriale o parallelo. Le seriali le gestisci appunto con il protocollo I2C.
Puoi leggere 1 byte alla volta oppure 1 pagina alla volta. Una pagina altro non è che un blocco di byte che iniziano da un determinato indirizzo.
Per leggere passi l'indirizzo nella forma byte alto/byte basso e poi il numero di byte da leggere: se ometti questo valore, ne chiedi solo 1.
La scrittura avviene nello stesso modo: spedisci l'indirizzo e poi invii il o i byte da salvare.
leo72:
Una EEPROM non è altro che una memoria non volatile.
Può essere di tipo seriale o parallelo. Le seriali le gestisci appunto con il protocollo I2C.
Puoi leggere 1 byte alla volta oppure 1 pagina alla volta. Una pagina altro non è che un blocco di byte che iniziano da un determinato indirizzo.
Per leggere passi l'indirizzo nella forma byte alto/byte basso e poi il numero di byte da leggere: se ometti questo valore, ne chiedi solo 1.
La scrittura avviene nello stesso modo: spedisci l'indirizzo e poi invii il o i byte da salvare.
Quegli esempi sono completi, c'è scritto tutto.
Ma nel codice del playground non vedo una funzione di lettura pagina.
EDIT:
Adesso ho capito, io alla funzione di scrittura pagina gli do come dati il puntantore al dato (che si presume sia superiore a 8bit no?) e la lunghezza di questo dato in modo che lui in automatico si salva i valori.
Beh potrei farlo anche a mano con un ciclo no?
Xfox:
Ma nel codice del playground non vedo una funzione di lettura pagina.
// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer........
Adesso ho capito, io alla funzione di scrittura pagina gli do come dati il puntantore al dato (che si presume sia superiore a 8bit no?) e la lunghezza di questo dato in modo che lui in automatico si salva i valori.
Beh potrei farlo anche a mano con un ciclo no?
La lunghezza del puntatore non ti interessa. Tu non passi alla EEPROM il puntatore ma i dati puntati dal puntatore.
Xfox:
Ma nel codice del playground non vedo una funzione di lettura pagina.
// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer........
> Adesso ho capito, io alla funzione di scrittura pagina gli do come dati il puntantore al dato (che si presume sia superiore a 8bit no?) e la lunghezza di questo dato in modo che lui in automatico si salva i valori.
> Beh potrei farlo anche a mano con un ciclo no?
La lunghezza del puntatore non ti interessa. Tu non passi alla EEPROM il puntatore ma i dati puntati dal puntatore.
Cosa cambia fra passare il dato, il puntatore ed il valore del puntatore?
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length )
Xfox:
Adesso ho capito, io alla funzione di scrittura pagina gli do come dati il puntantore al dato (che si presume sia superiore a 8bit no?) e la lunghezza di questo dato in modo che lui in automatico si salva i valori.
Beh potrei farlo anche a mano con un ciclo no?
non ho ancora ban capito la eeprom è un semplice array di byte o se è un'array di pagine, che a loro volta contengono un'array di byte..
se è la seconda affermazione, ogni pagina va scritta a partire dalla posizione 0 (quindi di fatto sovrascrivi l'array di dati contenuto), quindi dvi dare attenzione a quando scrivi a non chiudere la comunicazione i2c o vai a riscrivere i dati uno sull'altro. in compenso puoi leggere all'interno della pagina dove vuoi
a scegliere la pagina, ma non per posizionarsi all'interno di essa...
ah e mi son sbagliato a dire che nella lettura ti puoi posizionare dovev vuoi. ogni pagina si legge e si scrive sequenzialmente, solo l'accesso alle pagine è random.
E perchè passa il puntatore e non il dato direttamente?
il dato è un array, e gli array in realtà sono puntatori alla prima cella dell'array...
scegli la cella di memoria dove scrivere, poi ogni volta che scrivi un byte il LSB aumenta di uno, praticamente passa alla cella successiva. il problema è che LSB, arrivato a 64 si azzera (overflow)
quindi s', puoi usare tranquillamente un for, aprendo e chiudendo la comunicazione i2c quando ti fa più comodo.
Se mandi i byte in una pagina, hai la dimensione della pagina che ti limita, e del buffer di ricezione della EEPROM, che sono 64 byte. Passato l'indirizzo della prima cella della pagina, poi spedisci i byte uno alla volta.
Chiusa la trasmissione, la EEPROM salva tutto nella pagina.
C'è però un "però": lato Arduino sei limitato dal buffer I2C, che è preimpostato a 32 byte compresi i 2 byte per l'indirizzo per cui effettivi puoi spedire solo 30 byte dati.
Normalmente, però, vista la lentezza della EEPROM (3/5 ms per ogni scrittura), si spediscono pochi byte alla volta.
leo72:
C'è però un "però": lato Arduino sei limitato dal buffer I2C, che è preimpostato a 32 byte compresi i 2 byte per l'indirizzo per cui effettivi puoi spedire solo 30 byte dati.
Era uno dei pochi pezzi che ero riuscito a tradurre sul codice del playground xD
Comunque grazie ragazzi
Edit:
Ultima domanda e vi lascio in pace xD
Se io ho questo numero: 258 ovviamente lo scompongo in due byte B00000001 e B11111111
Come li faccio a concatenare quando li leggo?
Allora riasumendo.
Per scrivere 1 Byte devi dare prima il comando di write protection (pin WP) messo a massa e poi trametti l' indirizzo del EEprom e i 2 Byte del indirizzo seguendo dal dato da scrivere e alla fine un stop.
È possibile scrivere fino a 64 byte spedendoli uno dopo l' altro:
Uguale come scrivere un byte e poi al posto del stop scrivi gli altri 63 byte seguiti da un stop.
Come Leo scrive per un limite della libreria puoi scrivere solo 30 Byte.
Il secondo limite e che non puoi scrivere su 2 pagine. Devi scrivere prima i byte per riempire la pagina e poi il resto in una seconda scrittura blocco.
Page write operations are limited to writing bytes within a single physical page, regardless of the number of bytes actually being written. Physical page boundaries start at addresses that are integer multiples of the page buffer size (or ‘page size’) and end at addresses that are integer multiples of [page size – 1]. If a Page Write command attempts to write across a physical page boundary, the result is that the data wraps around to the beginning of the current page (overwriting data previously stored there), instead of being written to the next page, as might be expected. It is, therefore, necessary for the application software to prevent page write operations that would attempt to cross a page boundary.
Dopo un operazione di scrittura devi controllare se il EEprom ti dice che ha finito di scrivere i dati nelle celle EEprom (puó durare intorno ai 5msecondi) controllando il Acknowledge
(ACK = 0)?
Stessa cosa vale per la lettura. ecetto il ritardo di programmazione.
Ci sono FRAM della Ramtron che sono RAM che mantengono i dati memorizzati e questi non necessitano un tempo di scrittura. esempio FM24C512-G http://it.rs-online.com/web/p/nvram/7165738/ (costicchiano un po).