Im using a LOLIN32 Lite board, and it seems that i lose stuff that's stored in the EEPROM every time i flash a new version of my code onto it. Is this normal?
I had a more complex code going, but wanted to check by using some simple example. Because it worked as long as i did the save before reading.
GET EXAMPLE
#include <EEPROM.h>
#define EEPROM_SIZE 4095
void setup() {
EEPROM.begin(EEPROM_SIZE);
float f = 0.00f; //Variable to store data read from EEPROM.
int eeAddress = 0; //EEPROM address to start reading from
Serial.begin(115200);
delay(1000);
Serial.print("Read float from EEPROM: ");
//Get the float data from the EEPROM at position 'eeAddress'
EEPROM.get(eeAddress, f);
Serial.println(f, 3); //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float.
/***
As get also returns a reference to 'f', you can use it inline.
E.g: Serial.print( EEPROM.get( eeAddress, f ) );
***/
/***
Get can be used with custom structures too.
I have separated this into an extra function.
***/
secondTest(); //Run the next test.
}
struct MyObject {
float field1;
byte field2;
char name[10];
};
void secondTest() {
int eeAddress = sizeof(float); //Move address to the next byte after float 'f'.
MyObject customVar; //Variable to store custom object read from EEPROM.
EEPROM.get(eeAddress, customVar);
Serial.println("Read custom object from EEPROM: ");
Serial.println(customVar.field1);
Serial.println(customVar.field2);
Serial.println(customVar.name);
}
void loop() {
/* Empty loop */
}
PUT EXAMPLE:
#include <EEPROM.h>
#define EEPROM_SIZE 4095
struct MyObject {
float field1;
byte field2;
char name[10];
};
void setup() {
EEPROM.begin(EEPROM_SIZE);
Serial.begin(115200);
delay(1000);
float f = 123.456f; //Variable to store in EEPROM.
int eeAddress = 0; //Location we want the data to be put.
//One simple call, with the address first and the object second.
EEPROM.put(eeAddress, f);
Serial.println("Written float data type!");
/** Put is designed for use with custom structures also. **/
//Data to store.
MyObject customVar = {
3.14f,
65,
"Working!"
};
eeAddress += sizeof(float); //Move address to the next byte after float 'f'.
EEPROM.put(eeAddress, customVar);
Serial.print("Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!");
}
void loop() {
};
Thats an Arduino reference for EEPROM and the ESP32 is not an Arduino.
For full details on how the 'EEPROM' emulation works on an ESP32 there ought to be an Espressif reference somewhere, they produce and support the ESP32 plugin for the Arduino IDE.
Ok, thanks for confirming this! And i do know it does not have an EEPROM. Just thought that the emulation would have been better and used part of the flash that is not wiped when reflashed.
I would assume that this is a quite common issue, and that there would be solutions to this.
But now i know my code was not the problem and can at least proceed.
For simple non volatile storage of a struct like you want, you should also take a look at Preferences.h which is a part of the Arduino core for the esp32. It uses a simple key value pair method for nonvolatile storage. You will find many online examples of how to use Preferences.h. For the struct, the putBytes() function is what you will use, and if you look at the library documentation you will see all the other put/get functions available.
Here's a simple example of the use
#include <Preferences.h>
Preferences prefs;
int dataStore[3] = {12345, 45689, 78901};
int dataRetrieve[3];
void setup() {
Serial.begin(115200);
prefs.begin("IntegerArray"); //namespace
//bytes can be put/get in namespace directly see prefs2struct example
//prefs.putBytes("IntegerArray", (byte*)(&dataStore), sizeof(dataStore));
//SavedIntegers is Key
prefs.putBytes("SavedIntegers", (byte*)(&dataStore), sizeof(dataStore));
prefs.getBytes("SavedIntegers", &dataRetrieve, sizeof(dataRetrieve));
Serial.println(dataRetrieve[0]);
Serial.println(dataRetrieve[1]);
Serial.println(dataRetrieve[2]);
}
void loop() {}
I came across this preferences method while searching for solution, so it will retain its values even after reflashing a new version? That would be great. I just skipped it as i was thinking i had problems in code and did not want to try something new before i got the old code to work.
I need to have a database of structs, that from i can then load one into variables. I was a bit confused about this "namespace" thing. Is that like one set namespace for the whole storage? Or for single stored struct?
So "SavedIntegers" is the name for the stored struct, and it can then always find it by using this name?
Yes, i think i got this. This actually simplifies this a lot, damn.. my last version still had all manual seeking byte per byte and even this get & put system and storing whole structs made my things so much simpler.
It works, thanks! It was way easier than i thought. And with this system, no need to worry about the sizes. I don't need to define fixed sizes.. much easier if i need to change the dataset sizes in the future.
I can really post the code as its way too big project. It was pretty much a single line fix, just replaced all the eeprom stuff with this preferences stuff.
It kinda suspected that there must be a easy way to do this. Its 2022 dang diddly doo dang. Cant be bothered to go through stuff byte by byte.