[Projekt] I2C EEPROM

Hi.

Hier möchte ich euch mal meine neueste Errungenschaft vorstellen.
Eine Library für I2C EEProms.

Perfekt ist sie ganz sicher noch nicht, aber bereit für die ersten Tests im Feld.

Download: siehe Anhang
Eine kleine Doku findet sich in der Zip Datei.

Ich setze hier stark auf “Templates”.
Das zeigt sich schon bei der Instanziierung der Objekte:

AT24C32<> eep; // Das EEProm auf der china üblichen RTC, default Adresse 0x50 (80)
AT24C32<0x51> eep; // Alternative Adresse (A0 = High)

Das sorgt, bei der Verwendung von mehreren EEProms, für etwas mehr Code im Flash. Spart dagegen einiges an Ram ein.
(Und vor allen Dingen erspart es mir viel Schreibarbeit)

Was mir bei anderen Libs teilweise fehlte, und hier jetzt funktionieren soll:

  1. Weitgehende Kompatibilität mit der original Arduino EEPROM Lib
  2. Viele EEProms abdecken
  3. Schreiben und Lesen im Page Modus, nicht nur einzelne Bytes
  4. Nutzen der Wartezeit, nach dem Schreiben

Ich würde mich freuen, wenn ihr die Lib mal testen könntet. Gerade von den kleineren EEProms habe ich keine da. Gerne nehme ich auch Vorschläge für EEProms an, welche noch in der Liste aufgenommen werden sollen.

Die Doku ist noch etwas “schwach”. Auch hier würde ich mich über Vorschläge freuen, wie man diese etwas klarer bekommt.

Bitte spart nicht mit Kritik!

I2C_EEPROM.zip (13.3 KB)

Bitte spart nicht mit Kritik!

Das mußtest Du nicht extra sagen ;) ;) ;) ;) Hätten wir sowieso gemacht. Grüße Uwe

Hallo,

ist ein ST 24C08 klein genug? Ich würde das mal testen. Finde das eine feine Sache von Dir.

Doc_Arduino:
Hallo,

ist ein ST 24C08 klein genug? Ich würde das mal testen.
Finde das eine feine Sache von Dir.

Das ist genau richtig, zum testen.

Der Baustein ist schon in der Lib definiert, unter dem Namen ST24C08. In der Doku noch nicht aufgenommen, weil die Bezeichnung wohl demnächst auf M24C08 geändert werden wird.

Beispiel:

#include <Wire.h>
#include <I2C_EEPROM.h>




ST24C08<> eep; // STMicroelectronics M24C08  auf default Adresse 0x50 

void setup() 
{
   Serial.begin(9600); 
   Wire.begin();
 
   // die Speichergröße des EEProm wird in der Klasse gespeichert
   // kann also ausgelesen werden, ohne dass das EEProm wirlich
   // bereit ist 
   Serial.print("EE Prom lenth: "); 
   Serial.println(eep.length()); 

   if(eep.ready()) // eeprom bereit ?
   {
      // eeprom wurde gefunden, und ist bereit
      Serial.println ("EEProm ist bereit!");
   }else
   {
      // eeprom hat nicht geantwortet
      // Auch direkt nach dem schreiben blockiert das eeprom ein paar ms
      Serial.println("EEProm ist nicht bereit, Verkabelung prüfen ");
   }
}

void loop() 
{

}

Hallo,

bin gerade am Aufbau und verkabeln. Bin aber jetzt total verunsichert was ich mit den Pins
PRE, E und Mode machen muß. Genau genommen habe ich hier einen ST 24C08WP

Edit:
wenn ich den Sketch von oben kompliere, erhalte ich Warnungen. IDE 1.6.7 auf Mega2560

In file included from C:\Users\Worker\AppData\Local\Temp\arduino_c9d36c1d8c7605f5d3b249f4cd568f68\sketch_jan04a.ino:2:0:

C:\Users\Worker\Documents\Arduino\libraries\I2C_EEPROM/I2C_EEPROM.h:42:94: warning: large integer implicitly truncated to unsigned type [-Woverflow]

template<uint8_t I2CADDRESS=0x50> class AT24C512 : public eephandler<I2CADDRESS,65536U,2,32>{};

^

C:\Users\Worker\Documents\Arduino\libraries\I2C_EEPROM/I2C_EEPROM.h:49:92: warning: large integer implicitly truncated to unsigned type [-Woverflow]

template<uint8_t I2CADDRESS=0x50> class M24512 : public eephandler<I2CADDRESS,65536U,2,32>{};

^

Der Sketch verwendet 4.316 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 253.952 Bytes.
Globale Variablen verwenden 488 Bytes (5%) des dynamischen Speichers, 7.704 Bytes für lokale Variablen verbleiben. Das Maximum sind 8.192 Bytes.

ST 24C08 Datasheet.pdf (128 KB)

warning: large integer implicitly truncated to unsigned type

Danke! Wird in der nächsten Version behoben sein. Bis dahin bitte keine 24C512 nutzen.

Die Meldung steht der Nutzung kleinerer EEProms nicht im Wege.

Hallo,

so, habe jetzt

Pin 1 "PRE" auf Masse Pin 3 "E" auf Masse Pin 7 "MODE" auf Masse

gelegt und mit Warnungen geflasht. Ergebnis:

EE Prom lenth: 1024 EEProm ist bereit!

Reicht das? Nochwas testen? Irgendwas schreiben und wieder lesen?

Irgendwas schreiben und wieder lesen?

Gerne! 8) hoffentlich gelingt das 8)

combie: Wird in der nächsten Version behoben sein.

So, der Fehler ist behoben.

Nochmal Danke, dafür.

Hallo,

ist die online Version schon aktuell? Weil ich bekomme immer noch die gleichen Warnungen.

Das Bsp. CharArray mit
ST24C08<> eep;

Sollte hier nicht der Text vom String stehen?

EE Prom lenth: 1024
EE Prom ist bereit!
eep.get() 294308
fastBlockRead 50732

Wenn du nochmal sagst, jetzt sollte es passen, versuche ich schreiben und lesen. :slight_smile:

ist die online Version schon aktuell?

Eigentlich ja! Müssten auch eigentlich behoben sein.

Weil ich bekomme immer noch die gleichen Warnungen.

Die Meldungen kann ich nicht reproduzieren. Aber das kommt noch! Wie gesagt, der Überlauf zeigt sich nur bei 512 KBit EEProms. Und Auswirkungen hat er sowieso nicht. Also kein Problem bei kleineren.

Die Ausgabe von CharArray sollte so aussehen!

EE Prom lenth: 4096
EE Prom ist bereit!
eep.get()  68980
fastBlockRead 33640
Dieses ist ein total langer Teststring. Eigentlich muesste hier ein ganzer Roman stehen.

getestet mit AT24C32

Schreiben und lesen ist da eigentlich schon drin.

Da scheint noch ein Wurm zu stecken...... Du hast keine Ausgabe?

Hallo,

ich hab die Lib nochmal runterladen und an Ort und Stelle gepackt. Also. Die Warnungen sind weg. Wer weis was ich verhauen hatte. :)

Nur der Text vom String fehlt noch.

EE Prom lenth: 1024 EE Prom ist bereit! eep.get() 294308 fastBlockRead 50732

Tja…
Das ist ja spannend!

Noch bereit, zum Testen?

Erstmal schauen, ob dein EEProm das tut, was es tun muss!

Hier mal ein Testprogramm, ganz ohne meine Lib:

#include <Wire.h>

void meldung(byte fehler)
{
  switch(fehler)
  { 
    case 0 : Serial.println("0:success"); break;
    case 1 : Serial.println("1:data too long to fit in transmit buffer"); break;
    case 2 : Serial.println("2:received NACK on transmit of address"); break;
    case 3 : Serial.println("3:received NACK on transmit of data"); break;
    case 4 : Serial.println("4:other error"); break;

    // eigene Fehler
    case 100 : Serial.println("100:Keine Daten gelesen"); break;
    default : Serial.print(fehler);Serial.println(":unbekannt"); break;
  }  
}

const uint8_t M24C08_addr = 0x50;

uint8_t eepread(uint16_t address)
{
   int Adresse =  M24C08_addr + (address >> 8);
   Wire.beginTransmission(Adresse); 
   Wire.write(address & 0x00ff);       
   meldung(Wire.endTransmission());    
   Wire.requestFrom(Adresse,1);
    if(Wire.available()) return Wire.read();
   meldung(100); 
}

uint8_t eepwrite(uint16_t address, uint8_t value)
{
   int Adresse =  M24C08_addr + (address >> 8); 
   Wire.beginTransmission(Adresse); 
   Wire.write(address & 0x00ff);       
   Wire.write(value);       
   meldung(Wire.endTransmission());  
   delay(30);  
}


void setup() 
{
   Serial.begin(9600); 
   Wire.begin();

   Serial.println("Starte lesen");
   byte data = eepread(0);
   Serial.print(data,HEX);
   Serial.println(" gelesen ");

   data++;    
   Serial.println("Starte schreiben");
   eepwrite(0,data);
   Serial.print(data,HEX);
   Serial.println(" geschrieben ");
}

void loop() {}

Bei jedem Druck auf den Resetknopf sollte eine Zelle im EEProm hochzählen.

Die Ausgabe sollte so aussehen:
Nach dem ersten Reset:

Starte lesen
0:success
ff gelesen <<-- leereZellen sind immer 0xff
Starte schreiben
0:success
0 geschrieben

Nach dem zweiten Reset:

Starte lesen
0:success
0 gelesen <<-- leereZellen sind immer 0xff
Starte schreiben
0:success
1 geschrieben

Hallo,

so lange ich Zeit habe teste ich gern mit dir. Mein Schwippbogen mit Helligkeitssteuerung ist fertig. Werde ich noch vorstellen.

Dein Testsketch bringt Ausgaben. fängt aber nicht mit 1 sondern mit 61 an.

Starte lesen 0:success 61 gelesen Starte schreiben 0:success 62 geschrieben Starte lesen 0:success 62 gelesen Starte schreiben 0:success 63 geschrieben Starte lesen 0:success 63 gelesen Starte schreiben 0:success 64 geschrieben Starte lesen 0:success 64 gelesen Starte schreiben 0:success 65 geschrieben Starte lesen 0:success 65 gelesen Starte schreiben 0:success 66 geschrieben

Jetzt dachte ich das hängt mit dem Page-Mode zusammen. Habe Mode auf + gelegt, was Multibyte Write entspricht, aber da kommt nur Müll raus.

Starte lesen 0:success 66 gelesen Starte schreiben 3:received NACK on transmit of data 67 geschrieben Starte lesen 0:success 66 gelesen Starte schreiben 3:received NACK on transmit of data 67 geschrieben

Habe Mode wieder auf Masse gelegt für Page Mode.

Hallo,

ackern wir wirklich auf dem kleinen EEProm rum? Ich frage, weil ich mit Adresse 0x50 beim reinen auslesen mit dem EEprom Monitor Sketch alle Zellen mit 255 angezeigt bekomme? Als wenn da noch nie drauf geschrieben wurden wäre.

Und dieser "Device Select Code" auf Seite 3 im Datenblatt macht mich auch langsam stutzig. Als wenn man den anders ansprechen muß.

Herzlichen Dank!

Dein Testsketch bringt Ausgaben. fängt aber nicht mit 1 sondern mit 61 an.

Wenn es mit 61 anfängt, dann standen in der Zelle vorher schon Daten drin. z.B. der Buchstabe "a"

Ansonsten sieht die erste Ausgabe gut aus! Sehr gut. Dein EEProm scheint zu funktionieren. Meine Lib leider nicht.

Gut, dann werde ich nochmal ordentlich in mich gehen und die Wurst überprüfen.

EEprom Monitor Sketch alle Zellen mit 255 angezeigt bekomme? Als wenn da noch nie drauf geschrieben wurden wäre.

Hmm... Ackert der EEprom Monitor Sketch nicht auf dem im AVR eingebautem EEProm rum? Bzw: Ich habe KA, welches Script du meinst...

Hallo,

bin ich völlig gahgah? I2C Verbindung getrennt. Dein Sketch bringt received NACK on transmit of address Meldung. I2C Verbindung wieder hergestellt und zusätzlich 5,6k Pullups eingesetzt und neu geflasht. Startet bei 1. Nach nochmaliges Flash zählt er allerdings weiter und fängt nicht mehr bei 1 an. Scheint zu funktionieren wie gewünscht.

Starte lesen 0:success 5 gelesen Starte schreiben 0:success 6 geschrieben Starte lesen 0:success 6 gelesen Starte schreiben 0:success 7 geschrieben Starte lesen 0:success 7 gelesen Starte schreiben 0:success 8 geschrieben

combie:
Ackert der EEprom Monitor Sketch nicht auf dem im AVR eingebautem EEProm rum?
Bzw: Ich habe KA, welches Script du meinst…

Hatte die Adresse 0x50 eingestellt zum auslesen und Endaddresse spaßenshalber auf 4095 belassen. Ohne zu murren lass er bis zum Ende 255 aus. Hätte bei 1023 Ende sein müssen.
Er liest auch jetzt noch bis 4095 den Wert 255 aus. ???

Mein Mega2560 hat genau die 4k.
Der 24C08 hat nur 1k.
So langsam werde ich wieder stutzig.

/*
Arduino Mega2560
RTC DS3231 (0x68) mit AT24C32 EEprom (0x57)

EEprom wird komplett ausgelesen und im Terminalfenster dargestellt
AT24C32: 32kbits = 32768 bits = 4kByte  |  Speicherbereich 0 ... 4095
*/

#include <Wire.h>
#define AT24C32  0x50   
#define Startadresse  0
#define Endeadresse   1023

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
  unsigned int adr = 0;
   
  for (unsigned int adr = Startadresse; adr <= Endeadresse; adr++)
    {
      int a;
      // Dezimal
      a = leseEEprom(AT24C32, adr);
      if ( (adr == 0) || (adr % 8 == 0) )
        Serial.print(int2dez(adr, 4) + ": ");  // zeige Speicheradresse
        
      Serial.print(int2dez(a, 3) + " ");       // zeige Daten Byte
      
      if ( (adr + 1) % 8 == 0)
        Serial.println();                     // wenn Zeile mit Byte komplett
      
      /*
      // Hexadezimal
      a = leseEEprom(AT24C32, adr);
      if ( (adr == 0) || (adr % 8 == 0) )
        Serial.print(int2hex(adr, 4) + ": ");  // zeige Speicheradresse
        
      Serial.print(int2hex(a, 3) + " ");       // zeige Daten Byte
      
      if ( (adr + 1) % 8 == 0)
        Serial.println();                      // Zeilenvorschub wenn Zeile mit Byte komplett
      */  
    }  
}

void loop()
{
  
}


// int > dez Konvertierung mit Stellenanzahl
String int2dez(int wert, int stellen)
{
  String temp = String(wert);
  String prae = "";
  int len = temp.length();
  int diff = stellen - len;
  for (int i = 0; i < diff; i++)
    prae = prae + "0";
  return prae + temp;
}  


// int > hex Konvertierung mit Stellenanzahl
String int2hex(int wert, int stellen)
{
  String temp = String(wert, HEX);
  String prae = "";
  int len = temp.length();
  int diff = stellen - len;
  for (int i = 0; i < diff; i++)
    prae = prae + "0";
  return prae + temp;
}  



byte leseEEprom(int I2C_Adresse, unsigned int speicherAdresse)
{
  byte data = 0xFF;
  Wire.beginTransmission(I2C_Adresse);           // Connect
  Wire.write( (byte)(speicherAdresse >> 8)   );  // MSB
  Wire.write( (byte)(speicherAdresse & 0xFF) );  // LSB
  Wire.endTransmission();                        // Disconnect
  Wire.requestFrom(I2C_Adresse, 1);              // Daten vom Slave anfordern
  if (Wire.available()) data = Wire.read();      // Daten vorhanden?
  return data;
}  
  

void schreibeEEprom(int I2C_Adresse, unsigned int speicherAdresse, byte data)
{
  Wire.beginTransmission(I2C_Adresse);          // Connect
  Wire.write( (byte)(speicherAdresse >> 8)   ); // MSB
  Wire.write( (byte)(speicherAdresse & 0xFF) ); // LSB
  Wire.write(data);                             // data Byte zum speichern senden
  Wire.endTransmission();                       // Disconnect
  delay(5);
}

Deine Funktionen nutzen das 2 Byte Adressenverfahren. Das tuts bei einem 24C32, aber nicht bei einem 24C08.

Der 24C08 verteilt seine 256Byte "Blöcke" auf mehrere Geräte Adressen.

Mit einem I2C Scanner solltest du das auch sehen können. Ein 24C32 belegt 1 Adresse, ein 24C08 eine ganze Hand voll.

Mein Mega2560 hat genau die 4k.

Das interne EEProm funktioniert ganz anders, nicht über I2C.

Hallo,

mit dem Bus Scanner bekomme ich 4 Adressen angezeigt.
0x50 … 0x53. Es ist nur der 24C08 am Bus angeschlossen.

Ich verliere langsam den Überblick. Ganz ehrlich.