5

I need to know how I can write integer values in EEPROM and retain the value on power on.

char *Red = strstr(myTestUrl, "/R");
if (Red) {
  int RedValue  = atoi(Red + 2);
  analogWrite(12, RedValue);
  Serial.println("Red :");
  Serial.println(RedValue);
}

I want to write RedValue in EEPROM. How can it be done?

  • Have a look in the EEPROM sample sketches that are installed when you add ESP8266 support to the arduino ide – Jaromanda X Jul 3 '16 at 2:47
13

While EEPROM.read and EEPROM.write are valid methods, it's like mopping the floor with a toothbrush. Use EEPROM.put and EEPROM.get instead.

For example:

#include <EEPROM.h>

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

  uint addr = 0;

  // fake data
  struct { 
    uint val = 0;
    char str[20] = "";
  } data;

  // commit 512 bytes of ESP8266 flash (for "EEPROM" emulation)
  // this step actually loads the content (512 bytes) of flash into 
  // a 512-byte-array cache in RAM
  EEPROM.begin(512);

  // read bytes (i.e. sizeof(data) from "EEPROM"),
  // in reality, reads from byte-array cache
  // cast bytes into structure called data
  EEPROM.get(addr,data);
  Serial.println("Old values are: "+String(data.val)+","+String(data.str));

  // fiddle with the data "read" from EEPROM
  data.val += 5;
  if ( strcmp(data.str,"hello") == 0 )
      strncpy(data.str, "jerry",20);
  else 
      strncpy(data.str, "hello",20);

  // replace values in byte-array cache with modified data
  // no changes made to flash, all in local byte-array cache
  EEPROM.put(addr,data);

  // actually write the content of byte-array cache to
  // hardware flash.  flash write occurs if and only if one or more byte
  // in byte-array cache has been changed, but if so, ALL 512 bytes are 
  // written to flash
  EEPROM.commit();  

  // clear 'data' structure
  data.val = 0; 
  strncpy(data.str,"",20);

  // reload data for EEPROM, see the change
  //   OOPS, not actually reading flash, but reading byte-array cache (in RAM), 
  //   power cycle ESP8266 to really see the flash/"EEPROM" updated
  EEPROM.get(addr,data);
  Serial.println("New values are: "+String(data.val)+","+String(data.str));
}

void loop()
{
  delay(1000);
}

UPDATE: If you want to understand how the "EEPROM" is emulated in the ESP8266, you might want to reference https://github.com/esp8266/Arduino/tree/master/libraries/EEPROM, specifically, EEPROM.h.

Also, EEPROM.end is not needed, it simply clears the local byte-array cache of the flash/EEPROM from RAM. It serves on other function.

  • you have saved my day, I was searching for more than five hours for a solution and you have gave it ! – nonozor May 9 '18 at 15:12
  • The actual Arduino documentation is really lacking here and the sources do not really help either. Is EEPROM.end() still needed? Why is begin(512) needed? Plus a get()/put() combination or using update() would help to prevent EEPROM wear. Maybe you could update the answer. – Bim Jul 13 '18 at 10:00
  • I did a copy/paste of this exact code for a NodeMCU v3 and it's not retrieving the written value after a power cycle (I commented out the "write portion for the second run"). – WhiskerBiscuit Oct 27 '18 at 18:15
  • @WhiskerBiscuit, are you seeing ANY output in serial console? are you sure baud rate is set correctly? i don't have v3, just v0.9, so can't help if this is a forwards compatibility problem. – codechimp Oct 29 '18 at 0:17
  • 1
    from reference "EEPROM.write does not write to flash immediately, instead you must call EEPROM.commit() whenever you wish to save changes to flash. EEPROM.end() will also commit, and will release the RAM copy of EEPROM contents." – Juraj Oct 29 '18 at 8:15
4

EEPROM.write(pos, val) writes one byte (val) at the address giving by pos. An "int" in ESP8266 takes 4 bytes, so it's a little more complicated, because EEPROM works in bytes, not ints.

Here is a code for writing one int val at some position pos in the EEPROM:

void eeWriteInt(int pos, int val) {
    byte* p = (byte*) &val;
    EEPROM.write(pos, *p);
    EEPROM.write(pos + 1, *(p + 1));
    EEPROM.write(pos + 2, *(p + 2));
    EEPROM.write(pos + 3, *(p + 3));
    EEPROM.commit();
}

and, of course, you need to read it back:

int eeGetInt(int pos) {
  int val;
  byte* p = (byte*) &val;
  *p        = EEPROM.read(pos);
  *(p + 1)  = EEPROM.read(pos + 1);
  *(p + 2)  = EEPROM.read(pos + 2);
  *(p + 3)  = EEPROM.read(pos + 3);
  return val;
}

In Arduino you call EEPROM.begin(), but in ESP8266 you have to call EEPROM.begin(n), where n is the total number of bytes you will need.

And remember that EEPROM have a short life span (by number of writes). You must minimize the number of writes!

EEPROM is permanent; you don't need to do nothing.

  • I did some searching and it seems EEPROMs can handle many more write cycles than flash storage but then flash storage also has a controller to stop using bad sections and keep working with the remaining working ones. – Qwertie Jul 4 '17 at 2:01
1

Method using the number of letters.

#include <ESP8266WiFi.h>

const char* SSID = "R360"; //MAX 32
const char* PASSWORD = "HFDYUK64323246"; //MAX 32

#include <EEPROM.h>

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

  EEPROM_ESP8266_GRABAR(SSID, 0); //Primero de 0 al 32, del 32 al 64, etc
  EEPROM_ESP8266_GRABAR(PASSWORD, 32); //SAVE

  Serial.println();
  Serial.println(EEPROM_ESP8266_LEER(0, 32));//Primero de 0 al 32, del 32 al 64, etc
  Serial.println(EEPROM_ESP8266_LEER(32, 64));

  WiFi.begin(EEPROM_ESP8266_LEER(0,32).c_str(), EEPROM_ESP8266_LEER(32,64).c_str());

}
//
void loop() {}
//
void EEPROM_ESP8266_GRABAR(String buffer, int N) {
  EEPROM.begin(512); delay(10);
  for (int L = 0; L < 32; ++L) {
    EEPROM.write(N + L, buffer[L]);
  }
  EEPROM.commit();
}
//
String EEPROM_ESP8266_LEER(int min, int max) {
  EEPROM.begin(512); delay(10); String buffer;
  for (int L = min; L < max; ++L)
    if (isAlphaNumeric(EEPROM.read(L)))
      buffer += char(EEPROM.read(L));
  return buffer;
}
0

Use #include <EEPROM.h>

EEPROM.write(0, RedValue);   // To store in 0th Location
EEPROM.commit();
  • 1
    You forgot EEPROM.begin() – per1234 May 4 '17 at 2:07
0

I use 2 separate functions in my code on ESP8266 - one with EEPROM.put(), one with EEPROM.get().

I had EEPROM.begin(sizeof...); only in EEPROM.put() function and put worked. But it took me quite a while, until I found out, that it must be used before EEPROM.get() as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.