How to use core EEPROM functionality with real variables as easy

Maybe this is of interest.

The EEPROM function let you write or read an array which persists power loss or the deep_sleep command. The array is 100 byte wide. You can store real vars like int or float and others too. The trick is to use the C directive UNION to combine two data structure as one. It means two declared data structures share the same space in memory. How it goes?

First declare var data structure

struct structEEPROM {
    int intValue;       // integer var
    float floatValue;   // float var
    char charValue;     // char var
};

Then declare UNION adding a char[array] with the size of structEEPROM and give it a name, here EEPROMData

union {
    structEEPROM eevar;
    char eeArray[sizeof(structEEPROM)];
} EEPROMData;

Only two function are needed to exchange all data

void readEEPROM(void) {
    for (int i=0; i<sizeof(structEEPROM); i++) {
        EEPROMData.eeArray[i] = EEPROM.read(i);
    }    
}

void writeEEPROM(void) {
    for (int i=0; i<sizeof(structEEPROM); i++) {
        EEPROM.write(i, EEPROMData.eeArray[i]);
    }    
}

Read the EEPROM during setup()

void setup() {
    readEEPROM();
    // your other code
}

Save the data to EEPROM whenever you want

loop() {
    // your code
    writeEEPROM();
}

How to handle data in EEPROM?

//write data to vars
EEPROMData.eevar.intValue = 1337;
EEPROMData.eevar.floatValue = 3.14159;
EEPROMData.eevar.charValue = 13; //cr

//read data from vars
int Value1 = EEPROMData.eevar.intValue;
float Value2 = EEPROMData.eevar.floatValue;
char Value3 = EEPROMData.eevar.charValue;
11 Likes

Worked Perfect!

Thank You!

Thanks @digixx for this tutorial! I just wanted to share one thing I discovered while implementing this.

I had assumed that my EEPROM would be empty to start, and that I would read back all zeros. That turned out to be false, so my variables were getting initially populated with junk values from the EEPROM. To resolve, I added another variable to structEEPROM that would be treated as a fixed value. After reading the EEPROM, I would check this variable to see if it was the fixed value I expected. If it didn’t match, I assumed the EEPROM values are junk and initialize them to known good default values.

Hope this helps!

Greg

1 Like

Hello Greg

Good point. I was not aware that the eeprom could contain random data which can mislead the code.

It would be useful to calculate a CRC and store it as first variable inside eeprom to validate other stored variables…

I haven’t read the entire EEPROM module source code, but at a first glance it seems like EEPROM.write() doesn’t check whether the value being written is different than the current one.

I would add a read check before each write, otherwise you are consuming Flash memory space over and over, at each loop(), and you will soon wear it down:

void writeEEPROM(void) {
    for (int i=0; i<sizeof(structEEPROM); i++) {
        if (EEPROM.read(i) != EEPROMData.eeArray[i]) {
            EEPROM.write(i, EEPROMData.eeArray[i]);
        }
    }    
}

Other than that, I really like the union approach. I would have never thought of that!

I used shorter names: EE.var.myVar instead of EEPROMData.eevar.myVar

In the next release there will be EEPROM.put and EEPROM.get for storing arbitrary types to eeprom.

4 Likes