Storing Custom Data in Arduino's EEPROM

EEPROM is a powerful tool when creating projects, but setting and retrieving complex values can be daunting, until now.

What Is EEPROM?

EEPROM stands for Electronically Erasable Programmable Read-Only Memory, which in simplified terms, means that it acts as a type of non-volatile storage; when a value is written to the EEPROM, it stays there even when power is removed, unlike RAM which loses all of its values when power is removed. EEPROM is often utilized to store configuration data or other important values that need to be recalled each time the device is turned on. They can also be used to store simple music or even very tiny games.

One additional note: an EEPROM cell can only be written to a certain number of times (around 10,000) before it wears out and can't be overwritten any longer.

Data Structures in C

In the C language, variables are declared by putting a type next to a name. By doing this, the compiler knows how large your variable is, and therefore, how much space to allocate. You are probably familiar with the keyword class, which allows for data and methods to be encapsulated in a structure. In a similar manner, the keyword struct in C lets you aggregate data (not methods) into a container, which can then be treated as a single variable. They're great for passing and modifying multiple values, for example, such as login data which would include a username and password. Here's an example of a struct:

struct Login {
char username[30];
char password[25];
};

which can then have an instance created with:

Login myLoginDetails = {
"myUsername123",
"password123456"
};

Storing Data

Imagine that you have constructed an interface that has an LCD and several buttons that allow a user to choose various options from a menu. Using the builtin EEPROM would be a great way to remember the last choice(s) made. In order to do that, consider the following example:

struct LatestChoices {
uint8_t valid;
uint8_t option1, option2, option3;
char name[20];
};

The struct contains several fields, each of which correspond to a certain option. It is best practice to have a field that denotes if the value is a valid one, and to make it some kind of integer. This is because uninitialized EEPROM defaults each cell to a value of 255, which would cause a boolean to return false. Instead, check if valid is equal to 2 or 3. It's also good to have a default value to fall back on in case the value in EEPROM isn't valid:

LatestChoices choicesDefault = {
0,
5, 10, 212,
"person1"
};

This data can then be stored by first importing EEPROM.h and calling the function EEPROM.put(address, choicesDefault);

The address variable simply refers to the location the first byte should be stored in, so make sure it isn't too close to the end (an Arduino Uno has 1,024 bytes). Keep track of this number, as it will be used to retrieve this value later on. One additional note: You should put the actual value into the struct to store, not a pointer, since you will need to retrieve the values later on, not where they're stored in your MCU's memory.

Retrieving Data

To get the data back, it's first good to check if there is valid data in the first place. First, declare a new instance of your struct, in this case:

LatestChoices choice;

and then check if its valid fields is true by using EEPROM.get(address, choice) and then an if statement. If it is, then the rest of the data can be accessed using the . operator like so:

EEPROM.get(address, choice);
if(choice.valid == 2) {
// data is valid, do whatever with it
uint8_t firstOption = choice.option1;
char *nameRead = choice.name; // Set pointer to char array in structure

} else {
// data isn't valid, use the default one
}

Otherwise, use the default one you created earlier for getting values, and once they've been changed, set it to valid and store it at the same address.

Potential Uses

The applications of EEPROM are nearly limitless, as it is commonly used in many devices for a wide variety of purposes. One thing I do with it is store information such as credentials that have been entered via some kind of stream and aren't stored in program flash.

Arduino “having11” Guy
18 year-old IoT and embedded systems enthusiast. Also an intern at Hackster.io who loves working on projects and sharing knowledge.
Related articles
Sponsored articles
Related articles