Arduino e i2c eeprom

Salve a tutti. Sto cercando di gestire una eeprom i2c Microchip con Arduino. Ho alcuni problemi quando inserico molti dati in breve tempo nella eeprom. Sto gestendo la eeprom a record, ogni record sono 10 byte. A volte accade che quando vado ad inserire il record 25 che scrive dati da una cerca locazione in poi, mi ritrovo correttamenre il dato appena scritto ma in verità viene corrotto un altro record, ad esempio il 13 che nulla c'entra. Avete idea da cosa dipenda? Ho provato anche a modificare la frequenza del bus i2c senza però ottenere vantaggi.

A proposito, ho preso le funzioni da qui http://playground.arduino.cc/Code/I2CEEPROM

Credo che serva vedere il codice per capire dove capita l' errore. Come dice Guglielmo, tutti i caratteri contano. A volte sfugge e magari un paio d' occhi in più aiutano. Io son veramente agli inizi, sto imparando. Ho notato che la funzione più utile è passare il debug sulla seriale. Quindi dovresti inserire in diversi punti qualche Serial.print(Var_da_controllare) per capire cosa succede.

Fai una cosa, tra una scrittura e la successiva, inserisci una delay(10) per dare alla EEPROM il tempo di scrivere fisicamente i dati.

Guglielmo

Ma, mia curiosità, la libreria Wire, lavora sotto interrupt? Da cui dedurrei che sia richiesto una certa paura. Ma se Wire.available() risponde a modo, credo che si possa continuare a scrivere.

Con le EEPROM esterne, se non vuoi avere problemi, dopo la Wire.endTransmission() è necessario inserire una delay() dai 5 ai 20 ms in funzione della velocità della EEPROM e del blocco scritto.

Le chiamate della libreria Arduino, per la EEPROM interna del ATmega, vi nascondono cosa avviene veramente, ma basta andare a vedere nella AVRlibc, <avr/eeprom.h> per scoprire che viene sempre chiamata la “eeprom_is_ready()” prima di fare operazioni sula EEPROM, proprio perché le EEPROM sono oggetti lenti.

All of the read/write functions first make sure the EEPROM is ready to be accessed. Since this may cause long delays if a write operation is still pending, time-critical applications should first poll the EEPROM e. g. using eeprom_is_ready() before attempting any actual I/O.

Guglielmo

Le EEprom le puoi scrivere dato per dato o intera page (page Write). A secondo modello della EEprom i PAGE sono diversi (vedi datasheet) Prendo come esempio una con 6byte: puoi scrivere 16 byte in una volta con un unico ciclo di scrittura. Questo lo si fai aprendo la comunicazione, passando l' indirizzo di partenza e scrivendo 16 byte di dati e poi chiudere la comunicazione I2C.

Ma ATTENZIONE. I page del esempio sono sempre in multipli di 16 percui percui la prima page va da 0 a 15, la seconda da 16 a 31, la terza da 32 a 47 ecc. Puoi scrivere solo all interno della page e non in 2 cconsecutive. Se incominci a scrivere 16 byte a partire dall'indirizzo 8 i primi 8 saranno scritto nelle celle di memoria da 8 a 15 e i succesivi nelle celle 0 a 7 e NON nelle celle 16 a 23. Se vuoi scrivere a cavallo di 2 PAGE devi fare 2 scritture separate una per i byte della prima PAGE e una scrittura per i restanti byte nella successiva PAGE.

Ciao Uwe

Guardando l’ esempio della liberia citata http://playground.arduino.cc/Code/I2CEEPROM :
Scrittura di un byte:

  void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.send((int)(eeaddress >> 8)); // MSB
    Wire.send((int)(eeaddress & 0xFF)); // LSB
    Wire.send(rdata);
    Wire.endTransmission();
  }

Page Write; in questo caso 32 Byte ma la libreria permette solo 30 byte:

// WARNING: address is a page address, 6-bit end will wrap around
  // also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
  void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.send((int)(eeaddresspage >> 8)); // MSB
    Wire.send((int)(eeaddresspage & 0xFF)); // LSB
    byte c;
    for ( c = 0; c < length; c++)
      Wire.send(data[c]);
    Wire.endTransmission();
  }

Il Warnig dice che devi mettere un indirizzo di inizio PAGE.
Ciao Uwe