Store and retrieve data to / from your ESP8266

If you are working with an ESP8266 microcontroller, you may need to use an EEPROM to store data that needs to be retained even when the power is turned off. Fortunately, the ESP8266 comes with a built-in EEPROM library that makes it easy to read and write data to the EEPROM memory. In this blog post, we will explore the usage of the EEPROM.h library with the ESP8266 microcontroller.

First, let’s start by understanding what EEPROM is. EEPROM stands for Electrically Erasable Programmable Read-Only Memory. It is a type of non-volatile memory that can be written to and read from multiple times. EEPROM memory is used in microcontrollers to store data that needs to be retained even when the power is turned off. This can include data such as user preferences, configuration settings, and calibration data.

To be precise, due to the lack of genuine EEPROM memory on the ESP8266 family of microcontrollers, a common approach is to emulate EEPROM functionality by reserving a portion of flash memory. Anyway, this is something we shouldn’t be much concern of, think about EEPROM.h as a library which lets you read and write ESP8266 storage.

Another sweet thing is that you don’t need to add any external library for this.

The code

Here’s the code for basic read / write operations using EEPROM.h:

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);

  // Init EEPROM
  EEPROM.begin(512);

  // Write data to the EEPROM
  int addr = 0;
  int value = 28;
  EEPROM.put(addr, value);
  EEPROM.commit();

  // Read data from the EEPROM
  int readValue;
  EEPROM.get(addr, readValue);
  Serial.println(readValue);
}

void loop() {
  // Do nothing
}

Let’s break it down

First, we include the EEPROM.h library with #include <EEPROM.h>:

#include <EEPROM.h>

Then, in the setup() function, we initialize the serial communication with Serial.begin(9600):

Serial.begin(9600);

Next, we write data to the EEPROM memory using the EEPROM.put() function. In this example, we write the value 28 to the address 0 in the EEPROM memory. We also need to call EEPROM.begin() before writing to the EEPROM to allocate space for the EEPROM:

EEPROM.begin(512);

int addr = 0;
int value = 28;
EEPROM.put(addr, value);

After writing to the EEPROM, we need to commit the changes with EEPROM.commit(). This function saves the changes made to the EEPROM:

EEPROM.commit();

Finally, we read data from the EEPROM using the EEPROM.get() function. In this example, we read the value at address 0 and store it in the read_value variable. We then print the value to the serial monitor with Serial.println(readValue):

int readValue;
EEPROM.get(addr, readValue);
Serial.println(readValue);

It’s important to note that the EEPROM memory has a limited number of write cycles. The ESP8266 EEPROM library allows you to write to the EEPROM up to 100,000 times before the memory becomes unreliable. To prolong the life of the EEPROM memory, it’s recommended to only write to the EEPROM when necessary and to use other types of memory such as flash memory or SPIFFS for data that doesn’t need to be retained after power is turned off.

Store and retrieve arbitrary objects

In the following code, we’ll store and retrieve structs. To make it more realistic, we’ll store wifi configuration and some sensor data:

#include <EEPROM.h>

struct wifi_config {
  char ssid[20];
  char password[20];
};

struct sensor_data {
  float temperature;
  int humidity;
};

void setup() {
  Serial.begin(9600);

  // Initialize EEPROM
  EEPROM.begin(sizeof(wifi_config) + sizeof(sensor_data));

  // Store data to EEPROM
  wifi_config wifi;
  strcpy(wifi.ssid, "my_wifi_ssid");
  strcpy(wifi.password, "my_wifi_password");

  EEPROM.put(0, wifi);

  sensor_data data;
  data.temperature = 23.5;
  data.humidity = 60;

  EEPROM.put(sizeof(wifi_config), data);

  EEPROM.commit();

  // Read data from EEPROM
  wifi_config read_wifi;
  EEPROM.get(0, read_wifi);

  Serial.println("SSID: " + String(read_wifi.ssid));
  Serial.println("Password: " + String(read_wifi.password));

  sensor_data readData;
  EEPROM.get(sizeof(wifi_config), read_data);

  Serial.println("Temperature: " + String(read_data.temperature, 2));
  Serial.println("Humidity: " + String(read_data.humidity));
}

void loop() {
  // Do nothing
}

we define two different structs: wifi_config and sensor_data. wifi_config contains two character arrays for the SSID and password of the WiFi network, while sensor_data contains a floating-point number for the temperature and an integer for the humidity:

struct wifi_config {
  char ssid[20];
  char password[20];
};

struct sensor_data {
  float temperature;
  int humidity;
};

This time we initialize the EEPROM memory (by calling EEPROM.begin()) with the sum of the sizes of wifi_config and sensor_data:

EEPROM.begin(sizeof(wifi_config) + sizeof(sensor_data));

Next, we create an instance of the wifi_config struct called “wifi” and populate its values with dummy data. We use EEPROM.put() to store wifi to the EEPROM memory starting at address 0. We then create an instance of the sensor_data struct called “data”, populate its values with dummy data, and use EEPROM.put() to store data to the EEPROM memory starting at the size of wifi_config. We call EEPROM.commit() to save the changes made to the EEPROM memory:

wifi_config wifi;
strcpy(wifi.ssid, "my_wifi_ssid");
strcpy(wifi.password, "my_wifi_password");

EEPROM.put(0, wifi);

sensor_data data;
data.temperature = 23.5;
data.humidity = 60;

EEPROM.put(sizeof(wifi_config), data);

EEPROM.commit();

Finally, we read the data back from the EEPROM memory. We create an instance of the wifi_config struct called “read_wifi” and use EEPROM.get() to retrieve the data starting at address 0. We then print the values to the serial monitor using Serial.println(). We repeat the same process for the sensor_data struct, but starting at the size of wifi_config:

wifi_config read_wifi;
EEPROM.get(0, read_wifi);

Serial.println("SSID: " + String(read_wifi.ssid));
Serial.println("Password: " + String(read_wifi.password));

sensor_data readData;
EEPROM.get(sizeof(wifi_config), read_data);

Serial.println("Temperature: " + String(read_data.temperature, 2));
Serial.println("Humidity: " + String(read_data.humidity));

It’s always worth reminding that the total size of the structs used for EEPROM storage should match the size of the reserved EEPROM memory. In this example, we reserve the EEPROM memory with the size of sizeof(wifi_config) + sizeof(sensor_data) which is the sum of the sizes of both structs.

As an exercise, try implementing a WebServer handling GET requests to read from the EEPROM and POST requests to write to the EEPROM. Then, test the code with Curl or Postman.

Wrappin’ up

We’ll cover more complex examples involving WebServer and EEPROM soon, so check this website from time to time.

Have fun!


Made with ❤️ by Mikepicker