Using EEPROM to save values


#1

I’m planning to use Nextion LCD to change and save 2 float values. If value changes i want to write it to EEPROM so it’s saved after Photon restarts.

Is this code correct usage of EEPROM:

float muutuja1; 
float muutuja2; 
float LCD_saadud_vaartus1; 
float LCD_saadud_vaartus2; 

void setup(){ 
    EEPROM.get(1, muutuja1); //1 is address where to read from. Do i just put unique number for every float value i want to read/write?
       if(muutuja1 == 0xFFFF) { 
            // EEPROM was empty -> initialize value 
            muutuja1 = 25; 
        } 
    
    EEPROM.get(2, muutuja2); //2 is address where to read from. 
        if(muutuja2 == 0xFFFF) { 
            // EEPROM was empty -> initialize value 
            muutuja2 = 25; 
        } 
    LCD_saadud_vaartus1=muutuja1; 
    LCD_saadud_vaartus2=muutuja2; 
} 

void loop(){ 

    //LCD_saadud_vaartus is value from NEXTION LCD, code not shown here.
    if(muutuja1!=LCD_saadud_vaartus1){ 
        EEPROM.put(1, muutuja1); 
        muutuja1=LCD_saadud_vaartus1; 
    } 
    if(muutuja2!=LCD_saadud_vaartus2){ 
        EEPROM.put(1, muutuja2); 
        muutuja1=LCD_saadud_vaartus2; 
    } 
} 

#2

One problem I see is that you are using floats and then compare them to 0xFFFF assuming that a virgin EEPROM area will contain all 0xFF bytes stored.
The assumption is correct, but the equality check will fail for three reasons

  1. 0xFFFF is 65535 decimal but that number is not stored as 0xFFFF in a float variable.
  2. even if the integer representation would apply here, floats are not only two byte long but rather four
  3. due to 2. your base addresses 1 and 2 are wrong as both four-byte variables share three bytes which will always corrupt one variable when storing the other (BTW, in your loop you even only use the same base address for both variables)

But for the rest I can’t see any obvious error :wink:


#3

Tnx for input.
I copy pasted 0xFFFF from tutorial with integer. What value would i need to check with float?
Does one address space represent one byte?
In my case i would need to use addresses like that so that they would not corrupt each other?:
EEPROM.put(1, muutuja1); //float = 4 bytes ->address space 1,2,3,4
EEPROM.put(5, muutuja2); //float = 4 bytes ->address space 5,6,7,8


#4

Of course - just the same as in RAM or flash.

Even when written in a tutorial, 0xFF will only be there on a virgine device which had never had any EEPROM data stored at that location, so I’d strongly advise against assuming this for any other device than a factory new one - and having said that, to be on the safe side, not even for those.

My personal approach is to create a struct that’s home to all my settings including a unique magic-number for each of my projects and check for that magic-number first. If it’s not there, (re)initialise the EEPROM area for that project. Depending on the “severity” of possibly corrupted settings I even add a checksum field to the data and check that too.
The use of a struct also rids you of the need to calculate the individual base addresses for the individual fields - and I would usually start at address 0x00.

BTW, what tutorial did you take that 0xFFFF from? If your integer was an int then this check would fail too, since on Particle devices int is a 32bit integer which would require a check for 0xFFFFFFFF.


#5

I made some changes by your suggestion, how does this look:

float LCD_saadud_vaartus1; 
float LCD_saadud_vaartus2; 

struct MyObject {
  uint8_t magic_number;
  float muutuja1;
  float muutuja2;
};

MyObject myObj;



void setup() {
    EEPROM.get(0, myObj);
        if(myObj.magic_number != 11) {
        // EEPROM was empty -> initialize myObj
        MyObject defaultObj = { 11, 25, 25};
        myObj = defaultObj;
    }
    LCD_saadud_vaartus1=myObj.muutuja1; 
    LCD_saadud_vaartus2=myObj.muutuja2; 
}

void loop() {

    if(myObj.muutuja1!=LCD_saadud_vaartus1 || myObj.muutuja1!=LCD_saadud_vaartus2){ 
        
      EEPROM.put(0, myObj); 
      myObj.muutuja1=LCD_saadud_vaartus1; 
      myObj.muutuja2=LCD_saadud_vaartus2;
    } 

}

#6

You could simplify this

    if(myObj.magic_number != 11) {
        // EEPROM was empty -> initialize myObj
        myObj = { 11, 25, 25};
    }

and in order to actully store the correct values to EEPROM you need to reverse the order of execution like this.

    if(myObj.muutuja1 != LCD_saadud_vaartus1 || myObj.muutuja1 != LCD_saadud_vaartus2) { 
      myObj.muutuja1 = LCD_saadud_vaartus1; 
      myObj.muutuja2 = LCD_saadud_vaartus2;
      EEPROM.put(0, myObj); 
    } 

You first need to place the new values inside the struct and then write the updated values to EEPROM.


#7

English is not my first language and i’m sure you can tell i’m novice when it comes to writing code. Did i understand correctly that this is working code to save values to eeprom:

if(myObj.muutuja1 != LCD_saadud_vaartus1 || myObj.muutuja1 != LCD_saadud_vaartus2) { 
      myObj.muutuja1 = LCD_saadud_vaartus1; 
      myObj.muutuja2 = LCD_saadud_vaartus2;
      EEPROM.put(0, myObj); 
    } 

Or do i need to do smth more?


#8

This should work.
EEPROM.put() does put (store) the myObj struct into EEPROM, but in order to have your desired values written to EEPROM you need to place the values into the struct first via myObj.xxxx = yyyy. Once all your values are stored in the struct myObj putting that struct into EEPROM stores the values held therein.