EEPROM.put() using a multi-variable struct

Using the EEPROM class is really easy using structs. Storing a single struct with (for example) location specific data is a treat.

struct UserSpecificData{
  char myName[21] = "New User";
  char zipCode[6] = "10001";
  char city[32] = "New York";
  char stateAbbr[3] = "NY";
  char stateFullName[32] = "New York";
  double longitude = -73.935242;
  double latitude = 40.730610;
  bool usingDST = true;
} userSpecificData;

// and in some function:
if(somethingPersistentHasChanged)
  EEPROM.put(0, userSpecificData);

To give some reference, my actual struct includes a bunch of data; some vars may never change (depends on location's use) and some vars contain state data which may be toggled daily.

The object data is first compared to the data written in the EEPROM to avoid writing values that haven't changed.

Is EEPROM.put() safe to use on a large struct with multiple changing variables? I know that I'm not changing any single variable stored in EEPROM enough to cause a problem, but I am worried about using .put(), will it write the whole struct if even a single byte changes?

1 Like

Hello Bulldog,

I don’t know if you have seen this yet but this doc goes over the EEPROM.put. @mdma are you able to help with this?

Kyle

1 Like

Thanks @KyleG,

I started there but it wasn’t clear to me wether or not put() would write the whole EEPROM object, though the docs seem to imply yes.

Perhaps there will be someone that can answer this question for me.

1 Like

I pinged one of the people that has answered EEPROM questions in the past and should be able to clear things up. I’ll check back to make sure we get a solid answer though.

1 Like

Short answer is you're doing the right thing.

EEPROM.put() only updates changed bytes of the structure. It still takes a bit of time to compare your struct to the contents of the EEPROM so don't do put() on every loop if you know nothing has changed, but go ahead and put the whole thing when you suspect some data may have changed.

In addition to the fields you have, I like to have a version field to be able to migrate the struct on load. If you're changing apps between devices a lot, start the version at different values (1000 for app 1, 2000 for app 2, etc) and reset the whole EEPROM content if the version isn't one of the ones expected for this app.

See this post for an example. Instead of restoring default values if the version doesn't match, you could also migrate if a previous valid version is detected: set new fields to default values and save.

3 Likes

that's clever, thanks for the tip.

I appreciate your assistance, thanks!

1 Like

You can also check this app for an example of handling of strings in EEPROM with myString.getBytes(myEepromStruct.myString, sizeof(myEepromStruct.myString));. In that app I called the version field app and started it at a magic number.

1 Like

@jvanier,

Since put only looks at changed bytes, can you have a bool datatype in a multivariable structure? Or, do we have to use uint8_t and simply assign 0 or 1 to it?

Thanks, Chip

Within a struct, any primitive type (bool, int, float, double, etc.) can be used.

1 Like