EEPROM libraries

The sample pages have been removed ???

I was looking for confirmation that the .write method effectively used the .update method, as I'm sure I read it somewhere....

Then again, I'm using .get and .put, because all of my EEPROM data is in one structure.

Furthermore, I read the docs on Robust_EEPROM, and it did not mention how .writes are performed either.

Having said all of that, on this project I'm using an ESP8266 (Wemos Mini), and could possibly migrate it to ESP8266_EEPROM, although the effort to do that is not minor. A simple EEPROM.commit after a EEPROM.put is no deal-breaker.

Someone in the know needs to do a comprehensive article on the different EEPROM libraries available across as many platforms as possible (or perhaps one exists and I've just not found it)

Seems something you could explore and report on! Learning opportunity :wink:

The esp8266 does not have built in eeprom, so it’s simulated with flash storage. The library I with examples is

I suspect that they are now part of the reference. https://docs.arduino.cc/learn/built-in-libraries/eeprom.

write does not use update under the hood, put does. From EEPROM.h:

    void write( int idx, uint8_t val )   { (EERef( idx )) = val; }
    void update( int idx, uint8_t val )  { EERef( idx ).update( val ); }

    ...
    ...

    template< typename T > const T &put( int idx, const T &t ){
        EEPtr e = idx;
        const uint8_t *ptr = (const uint8_t*) &t;
        for( int count = sizeof(T) ; count ; --count, ++e )  (*e).update( *ptr++ );
        return t;
    }

That’s on AVR. OP said

On an ESP8266 the library works from a buffer that is committed to flash when you say so. The write() method does check if the byte is different to set the dirty flag (that would trigger an actual flash sector erase and dump upon commit)

Just make an array, fill it with whatever needs be saved, and put the whole thing in one pass, when you get it later extract from array, and you neednt worry about where to place what, might be a tad slower depending of how much data you want to save then adressing individually but way easier.

If the parts of the array change then only those parts should wear eeprom since other data remains the same, not entirely sure about that tho

And you can reed eeprom at the start, and use the array for reference later without reading eeprom

OP’s approach is way more flexible as it supports different types

On AVR only the bytes that need changing would be actually written. For the ESP and thus flash, it’s a sector transaction so one dirty bit requires a full sector write. (That’s why you commit the buffer and not a single variable)

would be good to know what he wants to save... I used eeprom to save some pid tunings and frequencies, so array was perfect on uno, if its alot of different data, you re right

If you have different conceptual values being stored, a struct leads to more readable code than a 2D array and you get to choose the best type for each value

struct __attribute__((packed)) t_preferences {
  double P;
  double I;
  double D;
  uint16_t frequencies[50];
} preferences ;

Then you can use the named fields in the code which is more readable

But may be I did not get the way you were storing info or your needs.

interesting...
i had this XD

 noInterrupts();                                   
        arrayEEPROM[0]=Kp;                        
        arrayEEPROM[1]=Ki;
        arrayEEPROM[2]=Kd;
        arrayEEPROM[3]=InverterFrequency;
        arrayEEPROM[4]=InverterSwitchingFrequency;
      
        EEPROM.put(0,arrayEEPROM);      
        interrupts();    

they were double and int, so array was double... worked like a charm for the little bit of data, struct seems even better
I had a few interrupts so I wanted to avoid coruption when saving

Ok i would have used

struct __attribute__((packed)) t_preferences {
  double Kp;
  double Ki;
  double Kd;
  uint16_t InverterFrequency;
  uint16_t InverterSwitchingFrequency;
} preferences ;

So that updating or reading fields would be very clear and it does not change the way you save it

EEPROM.put(0,preferences); 

Also in order to know if eeprom has already been initialized I usually add a sentinel at the start of the struct that I initialize to a known value

struct __attribute__((packed)) t_preferences {
  uint32_t sentinel;
  double Kp;
  double Ki;
  double Kd;
  uint16_t InverterFrequency;
  uint16_t InverterSwitchingFrequency;
} preferences ;

So when you fetch the data in memory in the setup to fill the struct, if the sentinel
Is not the known keyword (0xDEADBEEF or similar hexspeak values are usually found there) then you know it’s the first time the eeprom was being used and you can initialize it with defaults values

Also I would not disable interrupts to write to eeprom, I would make sure to use a copy of the data (simpler to assign a struct to another one or call a function and pass by value versus making an explicit copy of an array ) so that if the values are being used in an interrupt they would not be affected by the eeprom operation

1 Like

+1 for my programming skill right there :smile:
structured variables, very nice indeed, also genious sentinel
I needed to rewrite after saving the first time XD

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.