Official EEPROM library: support and reference.

Rudy216: I really like the implementation of this. :sunglasses: And because it is too easy to ask :blush: , would it be very difficult adapting this to an external I2C eeprom? (like the 24LC256) :sweat_smile:

No, not really, there is only one call to eeprom_read_byte, and one to eeprom_write_byte. You'd simply need to replace these with your own communication routines. However depending on how the address is set up from the arduino, it could be a really expensive operation to resend the address every byte (if the I2c chip supports reading multiple bytes one after the other).

I'll have a look at the datasheet when I'm home.

Hi pYro_65;

I have a problem with writing to and reading from EEPROM in Ardunio and ESP8266. I need to save Username and Password and read them in the next reboot.

In the first cell of EEPROM I write the length of the Username and then, each letter of it in the next cells. Til here I don't have any problem.

when I wanna retrieve the Username, I read the first cell (It gives me 5 for example). In this step, I need to know if the first cell is a digit greater than 0, to be sure that, the value in the first cell is actually written by me. so I used isdigit() function, but it returns zero no matter if the first cell is a digit or a letter.

What should I do to solve this problem?

The ESP8266 has its own 'EEPROM' lib for reading the SPI flash memory (its not really an EEPROM, just has a lib for symmetry between devices).

Or are you using this EEPROM lib for AVR arduinos, with an ESP connected (shouldn't affect the AVR EEPROM)?

If you are using the ESP version, select its board, then its examples should be available in the menus. Otherwise here is a link: https://github.com/esp8266/Arduino/tree/master/libraries/EEPROM/examples

There is also a different lib which you can use called SPIFFS (included with ESP core) however it is a bit more involved. https://github.com/pellepl/spiffs


However, I can only guess what is going on with out seeing some code.

Hi, thanks for this library ? is your Version 2.1 already available within the 1.6.6 or via the library manager ?

I am using IDE 1.6.7 and the sketch "EEPROM_Write" from the EEPROM library page on the Arduino site.

I get these compiler errors:

Arduino: 1.6.7 (Windows 10), Board: "Arduino Uno"

Board Arduino-master:arduino:lilypad doesn't define a 'build.board' preference. Auto-set to: ARDUINO_LILYPAD Board Arduino-master:arduino:mega2560 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_MEGA2560 Board Arduino-master:arduino:micro doesn't define a 'build.board' preference. Auto-set to: ARDUINO_MICRO Board Arduino-master:arduino:mini doesn't define a 'build.board' preference. Auto-set to: ARDUINO_MINI Board Arduino-master:arduino:pro5v328 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_PRO5V328 Board Arduino-master:arduino:pro328 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_PRO328 Board Arduino-master:arduino:leonardo doesn't define a 'build.board' preference. Auto-set to: ARDUINO_LEONARDO Board Arduino-master:arduino:atmega8 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_ATMEGA8 Board Arduino-master:arduino:pro5v doesn't define a 'build.board' preference. Auto-set to: ARDUINO_PRO5V Board Arduino-master:arduino:bt328 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_BT328 Board Arduino-master:arduino:atmega328 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_ATMEGA328 Board Arduino-master:arduino:pro doesn't define a 'build.board' preference. Auto-set to: ARDUINO_PRO Board Arduino-master:arduino:ethernet doesn't define a 'build.board' preference. Auto-set to: ARDUINO_ETHERNET Board Arduino-master:arduino:mini328 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_MINI328 Board Arduino-master:arduino:nano328 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_NANO328 Board Arduino-master:arduino:mega doesn't define a 'build.board' preference. Auto-set to: ARDUINO_MEGA Board Arduino-master:arduino:robotControl doesn't define a 'build.board' preference. Auto-set to: ARDUINO_ROBOTCONTROL Board Arduino-master:arduino:robotMotor doesn't define a 'build.board' preference. Auto-set to: ARDUINO_ROBOTMOTOR Board Arduino-master:arduino:esplora doesn't define a 'build.board' preference. Auto-set to: ARDUINO_ESPLORA Board Arduino-master:arduino:bt doesn't define a 'build.board' preference. Auto-set to: ARDUINO_BT Board Arduino-master:arduino:lilypad328 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_LILYPAD328 Board Arduino-master:arduino:fio doesn't define a 'build.board' preference. Auto-set to: ARDUINO_FIO Board Arduino-master:arduino:atmega168 doesn't define a 'build.board' preference. Auto-set to: ARDUINO_ATMEGA168 Board Arduino-master:arduino:uno doesn't define a 'build.board' preference. Auto-set to: ARDUINO_UNO Board Arduino-master:arduino:nano doesn't define a 'build.board' preference. Auto-set to: ARDUINO_NANO Board Arduino-master:arduino:LilyPadUSB doesn't define a 'build.board' preference. Auto-set to: ARDUINO_LILYPADUSB Board Arduino-master:arduino:diecimila doesn't define a 'build.board' preference. Auto-set to: ARDUINO_DIECIMILA WARNING: Category '' in library EEPROM is not valid. Setting to 'Uncategorized' WARNING: Category '' in library SPI is not valid. Setting to 'Uncategorized' WARNING: Category '' in library SoftwareSerial is not valid. Setting to 'Uncategorized' WARNING: Category '' in library Wire is not valid. Setting to 'Uncategorized' Warning: platform.txt from core 'Arduino AVR Boards' contains deprecated compiler.path={runtime.ide.path}/hardware/tools/avr/bin/, automatically converted to compiler.path={runtime.tools.avr-gcc.path}/bin/. Consider upgrading this core. Warning: platform.txt from core 'Arduino AVR Boards' contains deprecated tools.avrdude.cmd.path={runtime.ide.path}/hardware/tools/avr/bin/avrdude, automatically converted to tools.avrdude.cmd.path={path}/bin/avrdude. Consider upgrading this core. Warning: platform.txt from core 'Arduino AVR Boards' contains deprecated tools.avrdude.config.path={runtime.ide.path}/hardware/tools/avr/etc/avrdude.conf, automatically converted to tools.avrdude.config.path={path}/etc/avrdude.conf. Consider upgrading this core. Warning: platform.txt from core 'Arduino AVR Boards' contains deprecated recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}", automatically converted to recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}". Consider upgrading this core. C:\Users\JMK\Documents\Arduino\sketches\EEPROM_write\EEPROM_write.ino: In function 'void loop()':

EEPROM_write:47: error: 'class EEPROMClass' has no member named 'length'

if (addr == EEPROM.length()) {

^

exit status 1 'class EEPROMClass' has no member named 'length'

This report would have more information with "Show verbose output during compilation" enabled in File > Preferences.

In the EEPROM.h, "length" is defined as uint16_t but I do not see a function called "length".

Also, in the main Library discussion page for EEPROM, it does NOT mention "length" as a function.

I guess I am just a bit confused and wondering what is the problem I am having with this.

Thanks.

Do you have another library named EEPROM in your libraries folder?

The length function is there: https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/libraries/EEPROM/EEPROM.h#L127

Just curious, do you see the get() and put() functions?

Also your errors mention EEPROM not having a category: "WARNING: Category '' in library EEPROM is not valid. Setting to 'Uncategorized"

However it does have this set in the library.properties file. This was set since September 2015, and 1.6.7 will have it in there!

I'll download 1.6.7 and check when I get home, however I always compile my own from the latest source, and the length() function is definitely in there.

Hey pYro_65.
Just want to say thank you for the eewrap. I love it !!!
I don’t have to worry about any addressing. Just create the structure with whatever type you want and your done.

When I try to use the EEPROM library I get the following compiler error.

I do not have any references in my code regarding the EEPROM. I only have the include

include .

When I comment this include The sketch compiles fine but when the include is active I get the below compiler error.

Any ideas as to why this is happening ?

Arduino: 1.6.7 (Windows 7), Board: "Arduino Nano, ATmega328"

C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.cpp:40:9: error: redefinition of 'uint8_t EEPROMClass::read(int)'

 uint8_t EEPROMClass::read(int address)

         ^

In file included from C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.cpp:26:0:

C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.h:120:13: error: 'uint8_t EEPROMClass::read(int)' previously defined here

     uint8_t read( int idx )              { return EERef( idx ); }

             ^

C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.cpp:45:6: error: redefinition of 'void EEPROMClass::write(int, uint8_t)'

 void EEPROMClass::write(int address, uint8_t value)

      ^

In file included from C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.cpp:26:0:

C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.h:121:10: error: 'void EEPROMClass::write(int, uint8_t)' previously defined here

     void write( int idx, uint8_t val )   { (EERef( idx )) = val; }

          ^

C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.cpp:50:13: error: redefinition of 'EEPROMClass EEPROM'

 EEPROMClass EEPROM;

             ^

In file included from C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.cpp:26:0:

C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.h:145:20: error: 'EEPROMClass EEPROM' previously declared here

 static EEPROMClass EEPROM;

                    ^

exit status 1
Error compiling.

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.

tolisn63: C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\EEPROM.cpp:40:9: error: redefinition of 'uint8_t EEPROMClass::read(int)'

How did you get an EEPROM.cpp file in C:\Program Files\Arduino\hardware\arduino\avr\libraries\EEPROM\ with Arduino IDE 1.6.7? The EEPROM library included with 1.6.7 only has EEPROM.h. That file is the cause of your problem. You could probably fix the problem by just removing EEPROM.cpp but since this might indicate your IDE installation is messed up in other ways I guess the best thing would be for you to just reinstall the Arduino IDE.

is it possibkle to just replace the original that is provided with the IDE 1.6.8 with your Version 2.1 ?

I’d LOVE to see this library ported to external EEPROMs, such at the 24xx series i2c EEPROMs and the 93xx series as well.

+1

Question: Will the newest edition of EEPROM work on an Arduino R2? (this doesn't apply to me, I'm asking for a friend!)

thanks,

marco

If it is an AVR with EEPROM using the AVR core, then yes it will :)

If you mean an Arduino Uno R2, then its an AVR (Uno, Mega Leonardo, Micro, Nano,... are all AVR chips with EEPROM).

The concern is the IDE version. This new version is only available in IDE revisions 1.6.2 and above.

This person has EEPROM 2.0 and Arduino IDE 1.6.9. He is an arduino uno (either R1 or R2), and the problem is that values aren't being stored in the EEPROM. It works for me, however. Is this an issue regarding the board, or did he burn his EEPROM already perhaps? and if so, is there a way to check? thanks!

marco

If you are using the ISP to upload, the EEPROM will be overwritten. But this will not be the case with standard USB uploading via IDE.

You could reset the EEPROM by writing 1's to every bit (0xFF bytes). Verify all bytes are set to 0xFF.

Then loop through each byte writing each bit to 0. Read and verify the bits on each write are what you expect.

A write cycle is only complete when the byte is returned to all ones, so do not worry about writing 0 bits individually (each bit can be moved to 0, but writing a 1 from a zero requires the whole byte to be reset, which completes a write cycle).

But, yes a sketch left looping over a region of EEPROM can run through its cycles fairly quickly. Easy to do when debugging (and every now and then going off for a coffee/watching an episode in between brainstorms).

Unless the whole EEPROM was written over and over, only the used cells will be affected. You could try simply offsetting the data half way along the EEPROM.

But I would first verify the device with a simple sketch, then check the indices in use in the code. But if you are sure you are using the same code, then its likely not the problem if you do not experience the same failure (likely is not 'guaranteed' different IDE versions have different compilers and they treat logic errors differently).

Maybe post your code, or a test code which you have both tested.

Code:

#include 
#include 
#include 

int address = 0;
static unsigned long SaveTimer;
static unsigned long SaveDelay = (30 * 1000); 


char CODE[10] = "1234E"; 
char Str[10]; 
char CodeLength = 4;
int Pos = 0;
bool Unlocked;
static unsigned long DisplayTimer; 
static unsigned long DisplayDelay = 200;

LiquidCrystal lcd(12, 11, 9, 8, 7, 6); 


int buttonPin1 = 2;   
int buttonPin2 = 3;
int buttonPin3 = 4;
int buttonPin4 = 5;

int enterbutton = 10; 
int clearlockbutton = 13;

Servo myServo;

void setup() {

  myServo.attach(A1);
  
  int EEPROMCodeOK = true;
  for (Pos = 0; Pos <= (CodeLength); Pos++) {
    Str[Pos] =  EEPROM.read(Pos);
    if (!(strrchr("1123456789", Str[Pos]))) { 
      // not a valid code
      EEPROMCodeOK = false;
    }
  }
  Pos++;
  Str[Pos] =  EEPROM.read(Pos); 
  if (Str[CodeLength + 1] != 'E') EEPROMCodeOK = false; 
  if (EEPROMCodeOK) {
    Str[CodeLength + 2] = '\0';
    strncpy(CODE, Str, CodeLength + 1);
  }
  ClearCode();

  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(buttonPin3, INPUT_PULLUP);
  pinMode(buttonPin4, INPUT_PULLUP);

  pinMode(enterbutton, INPUT_PULLUP);
  pinMode(clearlockbutton, INPUT_PULLUP);

  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Hello.");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Password:");

  DisplayTimer = millis() + 200;
}


void loop() {
  
  Lock();
  
  Pos = constrain(Pos, 0, CodeLength);

  int buttonState1 = digitalRead(buttonPin1);  
  int buttonState2 = digitalRead(buttonPin2);
  int buttonState3 = digitalRead(buttonPin3);
  int buttonState4 = digitalRead(buttonPin4);

  int clButtonState = digitalRead(clearlockbutton);
  int enterButtonState = digitalRead(enterbutton);

  lcd.setCursor(9, 0);

  if (buttonState1 == LOW) {
    Str[Pos] = '1';
    Pos++;
    Str[Pos] = '\0';
    delay(250); 
    while (digitalRead(buttonPin1) == LOW); 

  }

  else if (buttonState2 == LOW) {
    Str[Pos] = '2';
    Pos++;
    Str[Pos] = '\0';
    delay(250); 
    while (digitalRead(buttonPin2) == LOW);

  }

  else if (buttonState3 == LOW) {
    Str[Pos] = '3';
    Pos++;
    Str[Pos] = '\0';
    delay(250); 
    while (digitalRead(buttonPin3) == LOW);
  }

  else if (buttonState4 == LOW) {
    Str[Pos] = '4';
    Pos++;
    Str[Pos] = '\0';
    delay(250); 
    while (digitalRead(buttonPin4) == LOW); 

  }
  else if (enterButtonState == LOW) {
    Str[Pos] = 'E';
    Pos++;
    Str[Pos] = '\0';
    delay(250);
    while (digitalRead(buttonPin1) == LOW); 
     if (strcmp (Str,CODE) == 0) {
      Unlocked = true;
      lcd.setCursor(0, 0);
      lcd.print(" Access Granted");
      delay(2000);
      lcd.clear();
      lcd.print("    Unlocked");
    } 
    else if (SaveTimer > millis() && (Pos + 1) == CodeLength) { 

      strcpy(CODE, Str);
      for (Pos = 0; Pos <= (CodeLength + 1); Pos++) {
        EEPROM.write(Pos, Str[Pos]);
      }
      lcd.setCursor(0, 0);
      lcd.print("Saving Code:");
      lcd.setCursor(0, 1);
      lcd.print(Str);

      Unlocked = true;
    }

    else { 

      lcd.clear();
      lcd.print(" Access Denied.");
      delay(2000);
      lcd.clear();
      lcd.print("Password:");

    }

    while (Unlocked) {
      Unlock();
      if (digitalRead(clearlockbutton) == LOW) {
        delay(200);
        lcd.clear();
        lcd.print("     Locked");
        delay(2000);
        lcd.clear();
        Unlocked = false;
        SaveTimer = millis() + 30000;
      }
    }
    
    ClearCode();

    
  }

  else if (clButtonState == LOW) {
    delay(500);

    while (clearlockbutton == LOW);
    if ((millis() - SaveTimer) > 4500) {
      
    }
    
    ClearCode();
    
  }

  if ( (long)( millis() - DisplayTimer ) >= 0) {
    DisplayTimer += DisplayDelay;
    lcd.setCursor(9, 0); 
    lcd.print(Str);
    lcd.print("     ");

  }
}

void ClearCode() {
  
  Pos = 0;
  Str[Pos] = '\0';
  lcd.setCursor(0, 0);
  lcd.print("Password:");
  lcd.setCursor(0, 1);
  lcd.print("          ");
  
}

void Unlock() {

  myServo.write(150);
  
}

void Lock() {

  myServo.write(50);

}

My Result

His Result

Thanks for the help,

marco

Hi, I was wondering if how large is a cell of EEPROM please in terms of bytes?

wenhuizhang: Hi, I was wondering if how large is a cell of EEPROM please in terms of bytes?

One

According to this post http://www.esp8266.com/viewtopic.php?f=33&t=2418 it is necessary to

EEPROM.begin(len);

before using it, eventually

EEPROM.commit();

to execute EEPROM.get(); read operations and after

EEPROM.end();

to actually apply/write changes.

This is actually missing in the original EEPROM Library Reference at arduino.cc I can remember that this was not the first time digging around for the missing bits until I got the examples and fortunately my projects to work finally.