Load and save your Settings to the EEPROM

A sketch that demonstrates how to load settings for your code from the EEPROM (if there are any) and how to store them.

The constant CONFIG_VERSION provides a way to determine if you ever wrote settings to the EEPROM and if it was this piece of code that did it (otherwise the code will use the default values).

When using this algorithm, please remember the following to ensure data integrity and some reliability:

  • CONFIG_VERSION must be unique between different sketches;
  • Also change it if you do any changes to the "StoreStruct" struct, or you will be in trouble!


2012-03-05, footswitch
Consider the following approach to increase reliability:

  • Move char version[4] to the end of the struct;
  • Adapt the functions loadConfig() and saveConfig() to this change (example provided further below);
  • (Optional) verify the data when it's being written to EEPROM.


2012-07-30, Thijs Elenbaas
Also Consider the implementation using the EEPROMex library, see below.


/* LoadAndSaveSettings
 * Joghurt 2010
 * Demonstrates how to load and save settings to the EEPROM
 */

// Contains EEPROM.read() and EEPROM.write()
#include <EEPROM.h>

// ID of the settings block
#define CONFIG_VERSION "ls1"

// Tell it where to store your config data in EEPROM
#define CONFIG_START 32

// Example settings structure
struct StoreStruct {
  // This is for mere detection if they are your settings
  char version[4];
  // The variables of your settings
  int a, b;
  char c;
  long d;
  float e[6];
} storage = {
  CONFIG_VERSION,
  // The default values
  220, 1884,
  'c',
  10000,
  {4.5, 5.5, 7, 8.5, 10, 12}
};

void loadConfig() {
  // To make sure there are settings, and they are YOURS!
  // If nothing is found it will use the default settings.
  if (EEPROM.read(CONFIG_START + 0) == CONFIG_VERSION[0] &&
      EEPROM.read(CONFIG_START + 1) == CONFIG_VERSION[1] &&
      EEPROM.read(CONFIG_START + 2) == CONFIG_VERSION[2])
    for (unsigned int t=0; t<sizeof(storage); t++)
      *((char*)&storage + t) = EEPROM.read(CONFIG_START + t);
}

void saveConfig() {
  for (unsigned int t=0; t<sizeof(storage); t++)
    EEPROM.write(CONFIG_START + t, *((char*)&storage + t));
}

void setup() {
  loadConfig();
}

void loop() {
  // [...]
  int i = storage.c - 'a';
  // [...]

  // [...]
  storage.c = 'a';
  if (ok)
    saveConfig();
  // [...]
}





2012-03-05, footswitch
If you want to try a different approach that may be more reliable, here's an adaptation of the code:

/* LoadAndSaveSettings
 * footswitch 2012-03-05, original code by Joghurt (2010)
 * Demonstrates how to load and save settings to the EEPROM
 * Tested on Arduino Uno R2 with Arduino 0023
 */

// Contains EEPROM.read() and EEPROM.write()
#include <EEPROM.h>

// ID of the settings block
#define CONFIG_VERSION "ls1"

// Tell it where to store your config data in EEPROM
#define CONFIG_START 32

// Example settings structure
struct StoreStruct {
  // The variables of your settings
  int a, b;
  char c;
  long d;
  float e[6];
  // This is for mere detection if they are your settings
  char version_of_program[4]; // it is the last variable of the struct
  // so when settings are saved, they will only be validated if
  // they are stored completely.
} settings = {
  // The default values
  220, 1884,
  'c',
  10000,
  {4.5, 5.5, 7, 8.5, 10, 12},
  CONFIG_VERSION
};

void loadConfig() {
  // To make sure there are settings, and they are YOURS!
  // If nothing is found it will use the default settings.
  if (//EEPROM.read(CONFIG_START + sizeof(settings) - 1) == settings.version_of_program[3] // this is '\0'
      EEPROM.read(CONFIG_START + sizeof(settings) - 2) == settings.version_of_program[2] &&
      EEPROM.read(CONFIG_START + sizeof(settings) - 3) == settings.version_of_program[1] &&
      EEPROM.read(CONFIG_START + sizeof(settings) - 4) == settings.version_of_program[0])
  { // reads settings from EEPROM
    for (unsigned int t=0; t<sizeof(settings); t++)
      *((char*)&settings + t) = EEPROM.read(CONFIG_START + t);
  } else {
    // settings aren't valid! will overwrite with default settings
    saveConfig();
  }
}

void saveConfig() {
  for (unsigned int t=0; t<sizeof(settings); t++)
  { // writes to EEPROM
    EEPROM.write(CONFIG_START + t, *((char*)&settings + t));
    // and verifies the data
    if (EEPROM.read(CONFIG_START + t) != *((char*)&settings + t))
    {
      // error writing to EEPROM
    }
  }
}


void setup() {
  loadConfig();
}

void loop() {
  // [...]
  int i = settings.c - 'a';
  // [...]

  // [...]
  settings.c = 'a';
  if (some_condition)
    saveConfig();
  // [...]
}




2012-07-30, Thijs Elenbaas
Using the EEPROMex library, the code would simplify to the following:

#include <EEPROMex.h>

// ID of the settings block
#define CONFIG_VERSION "ls1"

// Tell it where to store your config data in EEPROM
#define memoryBase 32

bool ok  = true;
int configAdress=0;

// Example settings structure
struct StoreStruct {
    char version[4];   // This is for mere detection if they are your settings
    int a, b;          // The variables of your settings
    char c;
    long d;
    float e[6];
} storage = {
    CONFIG_VERSION,
    220, 1884,
    'c',
    10000,
    {4.5, 5.5, 7, 8.5, 10, 12}
};

void setup() {
  EEPROM.setMemPool(memoryBase, EEPROMSizeUno); //Set memorypool base to 32, assume Arduino Uno board
  configAdress  = EEPROM.getAddress(sizeof(StoreStruct)); // Size of config object
  ok = loadConfig();
}

void loop() {
  // [...]
  int i = storage.c - 'a';
  // [...]
  storage.c = 'a';
  if (ok)
    saveConfig();
  // [...]
}

bool loadConfig() {
  EEPROM.readBlock(configAdress, storage);
  return (storage.version == CONFIG_VERSION);
}

void saveConfig() {
   EEPROM.writeBlock(configAdress, storage);
}

It would also limit the number of writes in the loop statement to stop burning out the EEPROM.

Share