ESP8266 writing to EEPROM, some data stored other data not so much

I came across an EEPROM exampel to read and write WiFi details to the "EEPROM" on the ESP8266 (ESP-01)

It works with out a hitch, until I add my own code to store a few more integers as well as values from an integer array.

This was pulled from How To Save Values On Arduino With EEPROM - The Robotics Back-End

Working Code

EEPROM.begin(512);

//Reads a string out of memory
String read_string(uint8_t l, uint8_t p){
  String temp;
  for (uint8_t n = p; n < l+p; ++n)
    {
      Serial.print("readmem - ");
      Serial.println(n);
     if(char(EEPROM.read(n))!=';'){
        if(isWhitespace(char(EEPROM.read(n)))){
          //do nothing
        }else temp += String(char(EEPROM.read(n)));
      
     }else n=l+p;
     
    }
  return temp;
}

void readEEProm()
{
    String string_Ssid="";
    String string_Password="";
    string_Ssid= read_string(30,0); 
    string_Password= read_string(30,60); 
    Serial.println("ssid: "+string_Ssid);
    Serial.println("Password: "+string_Password);
    string_Password.toCharArray(passwordc,30);
    Serial.println("FOUND");
    WiFiSSID = string_Ssid;
    WiFiPassw = string_Password;
    }
}


void write_to_Memory(String s, String p) {
  s += ";";
  write_EEPROM(s, 0);
  p += ";";
  write_EEPROM(p, 60);
  EEPROM.commit();
  flashGreen();
}
//write to memory
void write_EEPROM(String x, uint16_t pos) {
  for (uint16_t n = pos; n < x.length() + pos; n++) {
    EEPROM.write(n, x[n - pos]);
  }
}

All the above works, I can store a SSIDname and password and read it.

I serial.print the output and I can verify it works, the readmem is just the memory location being read from

readmem - 0
readmem - 1
readmem - 2
readmem - 3
readmem - 4
readmem - 5
readmem - 6
readmem - 7
readmem - 8
readmem - 9
readmem - 10
readmem - 11
readmem - 60
readmem - 61
readmem - 62
readmem - 63
readmem - 64
readmem - 65
readmem - 66
readmem - 67
readmem - 68
readmem - 69
readmem - 70
readmem - 71
ssid: abcdefghijk
Password: abcdefghijk

BUT When I add my own code to store integer values to the ESP and read them back at boot. Nothing works, upon read every value is set to 255, and the first and third characters in the SSID name value are overwritten.

uint8_t readArray[15]

void write_settings_Memory()
{
  uint16_t mempos = 120;
  EEPROM.write(mempos, UPDATES_PER_SECOND);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(UPDATES_PER_SECOND);
  mempos = mempos +2;
  EEPROM.write(mempos, BRIGHTNESS);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(BRIGHTNESS);
  mempos = mempos +2;
  EEPROM.write(mempos, SPARKING);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(SPARKING);
  mempos = mempos +2;
  EEPROM.write(mempos, COOLING);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(COOLING);
  mempos = mempos +2;
  for(uint8_t i = 0; i < 15; i++)
  {
    EEPROM.write(readArray[i], mempos);
    mempos = mempos +2;
    Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(readArray[i]);
  }
  Serial.println("Writing Settings");
  EEPROM.commit();
   
}


void read_Settings()
{
  uint16_t mempos = 120;
  UPDATES_PER_SECOND = EEPROM.read(mempos);
  Serial.print(mempos);
  Serial.print(" - ");
  Serial.println(UPDATES_PER_SECOND);  
  mempos = mempos +2;
  BRIGHTNESS = EEPROM.read(mempos);
  Serial.print(mempos);
  Serial.print(" - ");
  Serial.println(BRIGHTNESS);
  mempos = mempos +2;
  SPARKING = EEPROM.read(mempos);
  Serial.print(mempos);
  Serial.print(" - ");
  Serial.println(SPARKING);
  mempos = mempos +2;
  COOLING = EEPROM.read(mempos);
  Serial.print(mempos);
  Serial.print(" - ");
  Serial.println(COOLING);
  mempos = mempos +2;
  for(uint8_t i = 0; i < 15; i++)
  {
    readArray[i] = EEPROM.read(mempos);
    mempos = mempos +2;
    Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(readArray[i]);
  }
  Serial.println("Reading Settings");
}

For writing my own settings...
As shown, I start at address 120 to being writing these values, and this is the output from console while writing the settings. I'm only changing the values for location 130 and 132 as shown.

120 - 255
122 - 255
124 - 255
126 - 255
130 - 2
132 - 0
134 - 255
136 - 255
138 - 255
140 - 255
142 - 255
144 - 255
146 - 255
148 - 255
150 - 255
152 - 255
154 - 255
156 - 255
158 - 255

Now, when I reboot my device, it will read the WiFi details as well as the other values I've tried to store. (locations 0-11 are the SSID and 60-71 are the Password)

readmem - 0
readmem - 1
readmem - 2
readmem - 3
readmem - 4
readmem - 5
readmem - 6
readmem - 7
readmem - 8
readmem - 9
readmem - 10
readmem - 11
readmem - 60
readmem - 61
readmem - 62
readmem - 63
readmem - 64
readmem - 65
readmem - 66
readmem - 67
readmem - 68
readmem - 69
readmem - 70
readmem - 71
ssid: ⸮b⸮defghijk
Password: abcdefghijk

Here you can see the ssid has an invalid first and third character, appears its getting overwritten. This only occurs when I try and write my integers to the EEPROM. if I only write the ssid and password, it never corrupts.

After those values are read, it then starts at address 120 and begins to read what should be my adjusted values (specifically 130 and 132. they should be 2 and 0, not 255)

120 - 255
122 - 255
124 - 255
126 - 255
130 - 255
132 - 255
134 - 255
136 - 255
138 - 255
140 - 255
142 - 255
144 - 255
146 - 255
148 - 255
150 - 255
152 - 255
154 - 255
156 - 255
158 - 255

If I am understanding what I am trying to do.

Starting at memory location 0-59 it stores the SSID
Memory location 60-119 stores the Password
then starting at memory location 120 it begins to store the uint8_t (single byte integer) values. I increments +2 each time as I've read an integer takes up 2 bytes
So integer 1 goes into 120-121
Integer 2 goes into 122-123 and so on.

I'm new too working with the EEPROM, even more so working with an ESP. What am I doing wrong?

Side note, I'm going to change most of the EEPROM.write to EEPROM.update to avoid crushing the EEPROM with writes, and being its an ESP, I do perform the EEPROM.commit after storing values.

I believe you did not do: EEPROM.commit(); after writing the code. Be sure you are not going over 512 bytes. If you are less you can change the EEPROM.begin(512); to a lesser value but remember it must be divisible by 4.

Yeah there is an EEPROM.commit right after it prints "Writing settings" to the serial console.
I'll try bumping up the byte count from 512 up.

One thing I am noticing

If I write to the first address of 200, it saves the value. It's not till I start going through the for loop for the values in the array it appears does not work.

I also bumped my location pointer from 200 to 300, when I save to location 300 and 301 everything is OK. it's not till I start going through the array values that things just don't work.
But even then, it still corrupts the first set of values stored for the SSID, in the first memory address 0-11 in this example.

readmem - 0
readmem - 1
readmem - 2
readmem - 3
readmem - 4
readmem - 5
readmem - 6
readmem - 7
readmem - 8
readmem - 9
readmem - 10
readmem - 11
readmem - 60
readmem - 61
readmem - 62
readmem - 63
readmem - 64
readmem - 65
readmem - 66
readmem - 67
readmem - 68
readmem - 69
readmem - 70
readmem - 71
ssid: abcde0ghijk
Password: abcdefghijk

Notice the 0 in place of f in the ssid field

300 - 66
301 - 100
302 - 255
303 - 255
305 - 255
306 - 255
307 - 255
308 - 255
309 - 255
310 - 255
311 - 255
312 - 255
313 - 255
314 - 255
315 - 255
316 - 255
317 - 255
318 - 255
319 - 255
Reading Settings

But it reads the 66 and 100 in location 300 and 301

I thought EEPROM.write only wrote 1 byte at a time, but you seem to be trying to write 2 bytes then moving the EEPROM pointer 2 further along. The original code to me looks as though it writes 1 at a time.

I've been trying different memory start locations.

Are from the original code (linked in my first post) the ssid takes up 0-59 and the password is 60-119

I've tried starting at 120, 200 and 300 to being writing my integer values.

No matter what address I start it, when I write the additional values to the EEPROM it overwrites data in either the ssid section or password section.

BUT, storing values in the first 4 locations it alteast saves those. i.e. starting off at position 120

120 - 66
121 - 255
122 - 0
123 - 12

it saves 66 to 120, 255 to 121, 0 to 122 and 12 to 123. But again corrupts values stored in locations 0-59 and 60-119 i.e. the "}" in ssid is position 0 and should be "a"

ssid: }bcd|f||ijk
Password: abcdef}hijk

I feel like my issue is 2 fold, 1, I'm overwriting memory 0-119 and 2, nothing at all is written when I tick through the array

void write_settings_Memory()
{
  uint16_t mempos = 120;
  EEPROM.write(mempos, UPDATES_PER_SECOND);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(UPDATES_PER_SECOND);
  mempos = mempos +1;
  EEPROM.write(mempos, BRIGHTNESS);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(BRIGHTNESS);
  mempos = mempos +1;
  EEPROM.write(mempos, SPARKING);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(SPARKING);
  mempos = mempos +1;
  EEPROM.write(mempos, COOLING);
  Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(COOLING);
  mempos = mempos +1;
  for(uint8_t i = 0; i < 15; i++)
  {
    EEPROM.write(readArray[i], mempos);
    mempos = mempos +1;
    Serial.print(mempos);
    Serial.print(" - ");
    Serial.println(readArray[i]);
  }
  Serial.println("Writing Settings");
  EEPROM.commit();
   
}

The array uint8_t readArry[15];

countrypaul:
I thought EEPROM.write only wrote 1 byte at a time, but you seem to be trying to write 2 bytes then moving the EEPROM pointer 2 further along. The original code to me looks as though it writes 1 at a time.

I ended up changing the increment to +1, since I'm writing uint8_t values, those should be 1 byte correct?
My values are 0-255 and most never go above 10 in real world use, though I'm testing with values between 0 and 255

To clean things up abit.

This is the code that is working to store the SSID and Password into EEPROM, it works flawless

I am calling EEPROM.begin(512); at the start

void write_to_Memory(String s, String p) {
  s += ";";
  write_EEPROM(s, 0);
  p += ";";
  write_EEPROM(p, 60);
  EEPROM.commit();
  flashGreen();
}
//write to memory
void write_EEPROM(String x, uint16_t pos) {
  for (uint16_t n = pos; n < x.length() + pos; n++) {
    EEPROM.write(n, x[n - pos]);
  }
}

This is the code where I try and write my own values. All values are of the type uint8_t so they should only be 1 byte from as far as I know.

void write_settings_Memory()
{
  uint16_t mempos = 120;
  EEPROM.write(mempos, UPDATES_PER_SECOND);
  mempos = mempos +1;

  EEPROM.write(mempos, BRIGHTNESS);
  mempos = mempos +1;

  EEPROM.write(mempos, SPARKING);
  mempos = mempos +1;

  EEPROM.write(mempos, COOLING);
  mempos = mempos +1;

  for(uint8_t i = 0; i < 15; i++)
  {
    EEPROM.write(readArray[i], mempos);
    mempos = mempos +1;
  }

  EEPROM.commit();
   
}

The first 4 values are written to the EEPROM and I can read them back correctly. But the SSID and Password values stored at the start get corrupted with random characters when I run this second storage code.

The next 15 values, from the array, are never read back and are always 255

Below is the read code for just this portion

void read_Settings()
{
  uint16_t mempos = 120;
  UPDATES_PER_SECOND = EEPROM.read(mempos);
  mempos = mempos +1;

  BRIGHTNESS = EEPROM.read(mempos);
  mempos = mempos +1;

  SPARKING = EEPROM.read(mempos);
  mempos = mempos +1;

  COOLING = EEPROM.read(mempos);
  mempos = mempos +1;

  for(uint8_t i = 0; i < 15; i++)
  {
    readArray[i] = EEPROM.read(mempos);
    mempos = mempos +1;
  }
}

Something else to note, I just commented out the for loop in my write_settings_Memory function. This is the loop that writes the readArray[] values to the EEPROM. Again the array is length of 15 with a type of uint8_t.

If I skip writing these values, and only write my first 4 values of UPDATES_PER_SECOND, Brightness and the like. It writes them, doesn't corrupt the SSID or Password stored and reads them fine.
(these values are also uint8_t)

It's not till the for loop that reads through all 15 values of the array and writes them to the EEPROM, that things start to go haywire. Corrupting data in the SSID and Password fields and giving values of 255.

(EDIT)
Even just trying to store 1 value to the EEPROM from the readArray corrupts the SSID and Password data

i.e. EEPROM.write(readArray[0]);
I'm trying to focus on this now as it appears to be the root of the problem. again the array is created with uint8_t readArray[15];
Using the array works fine in my code, until I try and write its values to the EEPROM

Can you post the whole sketch rather than just parts, I have a suspicion that we are missing something in the wider picture.

Edit:

I've trimed down the code to just the HTTP portion that grabs a string, parses it into integers and builds the array.
As well as the read and write EEPROM functions. The end result is still the same, nothing from the array gets stored in the EEPROM, and if I execute that portion it overwrites either the ssid or password data.
I can change the settings position to anything even 200 (the setpos byte in code below) and it will save my first 4 values, but not after.
I did try storing readArray[0] into the first position 120 (or even 200) and that works, it writes and reads.

Test.ino (10.1 KB)

I have used emulated EPPROM on ESP for couple of times,

faced same issue at the beginning,

and what I realized is that, you are better off writing into it on one-go

you need to put all the stuffs into one long string like this

char buff[200];
sprintf(buff, "%s/%s/%s/%d",
ssid.c_str(),   // this is String
pass.c_str(),   // this is String
httpString,
brightness      // this is integer/byte
);

see all the things go into buff array, delimited by character '/' and gets saved as

 eeprom_write(buff);

where

void eeprom_write(String xx) {
  int end_ = xx.length();
  EEPROM.write(2, end_);  // store string length
  for (int x = 4; x < end_ + 4; x++ ) {
    byte mm = xx.charAt(x - 4);
    if ( EEPROM.read(x) != mm ) { // prevents writing same thing into a memory cell
      EEPROM.write(x, mm);
    }
    EEPROM.commit();
  }
}

you can clearly see line

 EEPROM.write(2, end_);

stores the string length to be retrieved back when ESP reboots

upon reboot I read the whole string just like this

String eepromString = eeprom_read();

where

String eeprom_read() {
  String xx = "";
  int end_ = EEPROM.read(2);  // get string length
  if ( end_ == 255 ) {  // new here
    return "none";
  }
  for (int x = 4; x < end_ + 4; x++ ) {
    if ( EEPROM.read(x) > 250 ) {  // skip this bastard
      continue;
    }
    xx += char(EEPROM.read(x));
  }
  return xx;
}

you might want to check for '/' presence in eepromString

then you need to parse thet obtained String back to individual variables like this

String myData[100];
 int counter = 0 ;
  char delimiter = '/';

  for ( int i = 0 ; i < eepromString.length() ; i ++ ) {
    if ( eepromString.charAt(i) == delimiter ) {
      counter++;
    }
    else {
      myData[counter] +=  eepromString.charAt(i) ;
    }
  }

  ssid = myData[0];
  pass = myData[1];
 randomString = myData[2];
  brightness = myData[3].toInt();

Hope that Might help

That seems to have done the trick!

I still kept the SSID and Password read/writes in different routines from my light settings portion.
I just set the memory position to 120 and start from there.
I also added some error checking to see if the integer value being read and written to my array is < 256, since I'm using 1 byte integers in my array.

It also no longer corrupts the SSID or Password data stored in the EEPROM.

All seems to be working, now to clean up my code abit.

Thank you very much!