EEPROM

In vielen Fällen besteht das Problem mit dem Arduin darin, dass die Daten nicht standardmäßig persistieren werden können. Persistenz bedeutet, dass Daten auch nach einem Neustart nicht gelöscht werden, in einem komplexeren Fall ein redundanter Switch. Der RAM des Arduino wird in diesem Fall vollständig gelöscht. Die einfachste Lösung besteht darin, solche Daten im Speicherbereich des Arduino EEPROM zu speichern. Wir können einen externen Speicher für die Datenspeicherung verwenden, der eine SD-Karte sein kann, aber es ist einfacher, ein externes EEPROM zu installieren. Unter den Lösungen hilft es natürlich, Ihnen zu zeigen, wie viel wir Arduinos eigenes EEPROM laden möchten und wie viele Daten wir beibehalten möchten.

Verschiedene Arduino-Boards haben EEPROMs unterschiedlicher Größe:

  • ATmega328P: 1024 Bytes
  • ATmega168: 512 Bytes
  • ATmega8: 512 Bytes
  • ATmega1280: 4096 Bytes
  • ATmega2560: 4096 Bytes

Um auf das EEPROM zuzugreifen, sollten Sie die Funktionen der EEPROM-Bibliothek verwenden: https://www.arduino.cc/en/Reference/EEPROM

Beim Schreiben eines internen EEPROM muss darauf geachtet werden, dass es auf maximal ca. 100.000 Schreibzyklen angewendet wird. Dies mag viel erscheinen, aber wenn wir versuchen, dort in jedem Zyklus Daten zu speichern, können wir schnell das Ende ihrer Lebensdauer erreichen. Offensichtlich lohnt es sich, Ihre Schriften an Ereignisse zu binden, die nicht sehr oft vorkommen, oder an einen Zeitauslöser.

Beispielprogramm für Arduino EEPROM

/*
 * EEPROM Write
 *
 * Stores values read from analog input 0 into the EEPROM.
 * These values will stay in the EEPROM when the board is
 * turned off and may be retrieved later by another sketch.
 */
 
#include <EEPROM.h>
 
/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
int addr = 0;
 
void setup() {
  /** Empty setup. **/
}
 
void loop() {
  /***
    Need to divide by 4 because analog inputs range from
    0 to 1023 and each byte of the EEPROM can only hold a
    value from 0 to 255.
  ***/
 
  int val = analogRead(0) / 4;
 
  /***
    Write the value to the appropriate byte of the EEPROM.
    these values will remain there when the board is
    turned off.
  ***/
 
  EEPROM.write(addr, val);
 
  /***
    Advance to the next address, when at the end restart at the beginning.
 
    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduno Duemilanove: 512b EEPROM storage.
    - Arduino Uno:        1kb EEPROM storage.
    - Arduino Mega:       4kb EEPROM storage.
 
    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/
  addr = addr + 1;
  if (addr == EEPROM.length()) {
    addr = 0;
  }
 
  /***
    As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
    EEPROM address is also doable by a bitwise and of the length - 1.
 
    ++addr &= EEPROM.length() - 1;
  ***/
 
 
  delay(100);
}

AT24C256 I²C EEPROM Modul

In diesem Fall kann über I²C auf die EEPROM-Funktion zugegriffen werden. Da die Wahrscheinlichkeit groß ist, dass wir ohnehin einige andere Arduino I²C-Kommunikationseinheiten verwenden, nimmt die Speicherverwaltung keine zusätzlichen wertvollen Pins mehr in Anspruch. Es gibt zwei Versionen dieses ICs, den AT24C128 mit 128 kBit bis 16 kByte, während der AT24C256 mit 256 kBit bis 32 kByte einen adressierbaren, löschbaren, aber dauerhaften Datenbereich enthält. Das Schreiben / Lesen kann in Bytes oder Seiten (64 Bytes) erfolgen.

AT24C256 Spezifikationen

  • Netzteil:
    • (Niederspannungsmodus): 1,8..3,6 V.
    • (normaler Spannungsmodus): 2,7..5,5 V.
  • Kommunikation: I²C
  • Überlagerungsmodus: 64 Bytes
  • I²C-Frequenzkompatibilität: 1 MHz (5 V), 400 kHz (2,7..2,5 V), 100 kHz (1,8 V)
  • Maximale Anzahl von Schreibzyklen: 1 Million
  • Betriebstemperatur: -55..125 ° C.
  • Spannungstoleranz der Beine gegenüber GND: -1..7 V.
  • Maximale Versorgungsspannung: 6,25 V.
  • Ausgangsstrom: 5,0 mA

AT24C256 IC-Pinbelegung

AT24C256 IC-Pinbelegung

A0, A1: I²C-Adresse
SDA: I²C-Datenport
SCL: I²C-Clock-Port
WP: Schreibschutz auf IC
NC: nicht verbunden

AT24C256 Adresszuweisung

Die EEPROM-Adresse wird unter Verwendung der Pins A0, A1 (oder Jumper im Fall eines Moduls) wie folgt gebildet:

AT24C256 Adresszuweisung

AT24C256 Telegrammstruktur

AT24C256 Telegrammstruktur

Verdrahtung (modul)

AT24C256 I²C EEPROM Modul Verdrahtung

Softver

Ein Anwendungsprogramm für das Modul kann auch von Github heruntergeladen werden: https://github.com/cyberp/AT24Cx

/*
  *  Use the I2C bus with EEPROM 24LC64
  *  Sketch:    eeprom.ino
  *
  *  Author: hkhijhe
  *  Date: 01/10/2010
  *
  *
  */
 
#include <Wire.h>
 
 
 
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.write(rdata);
    Wire.endTransmission();
}
 
// 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.write((int)(eeaddresspage >> 8)); // MSB
    Wire.write((int)(eeaddresspage & 0xFF)); // LSB
    byte c;
    for ( c = 0; c < length; c++)
        Wire.write(data[c]);
    Wire.endTransmission();
}
 
byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
    byte rdata = 0xFF;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,1);
    if (Wire.available()) rdata = Wire.read();
    return rdata;
}
 
// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,length);
    int c = 0;
    for ( c = 0; c < length; c++ )
        if (Wire.available()) buffer[c] = Wire.read();
}
 
 
 
 
void setup()
{
    char somedata[] = "this is data from the eeprom"; // data to write
    Wire.begin(); // initialise the connection
    Serial.begin(9600);
    i2c_eeprom_write_page(0x50, 0, (byte *)somedata, sizeof(somedata)); // write to EEPROM
 
    delay(100); //add a small delay
 
    Serial.println("Memory written");
}
 
void loop()
{
    int addr=0; //first address
    byte b = i2c_eeprom_read_byte(0x50, 0); // access the first address from the memory
 
    while (b!=0)
    {
        Serial.print((char)b); //print content to serial port
        addr++; //increase address
        b = i2c_eeprom_read_byte(0x50, addr); //access an address from the memory
    }
    Serial.println(" ");
    delay(2000);
}