We’ll learn how to use the Arduino IDE to store and read values from the ESP32 flash memory in this article. Even if the ESP32 is reset or power is disconnected, the data saved in the flash memory persists. We’ll teach you how to store the last GPIO state as an example.

PARTS REQUIRED

  • ESP32 DOIT DEVKIT V1 Board  – read ESP32 Development Boards Review and Comparison
  • 5mm LED
  • 330 Ohm resistor
  • Pushbutton
  • 10k Ohm resistor
  • Breadboard
  • Jumper wires

ABOUT FLASH MEMORY

The flash memory works in a similar way to the EEPROM memory found in most microcontrollers. It’s a non-volatile memory, which means the data is retained even if the ESP is reset or the power is cycled. This is beneficial in apps when you need to save device settings, remember the last state of a variable, or save vital runtime data for later use, among other things. For example,supposing a piece of equipment controlled by the ESP32 was ON when power was disconnected; in most situations, the equipment will remain OFF when power is restored, depending on the specified settings, but the system can be designed to return to the last state using Flash memory.

ABOUT EEPROM LIBRARY

The EEPROM library will be used to store and read data from the ESP32 flash memory using the Arduino IDE. Using the ESP32 library is fairly similar to using the Arduino library. You can use up to 512 bytes of flash memory with the ESP32 and the EEPROM library. This implies you can save a value between 0 and 255 in each address location, and you have 512 different addresses.

Write

To write data to the flash memory, you use the EEPROM.write() function that accepts as arguments the location or address where you want to save the data, and the value (a byte variable) you want to save:

EEPROM.write(address, value);

For example, to write 9 on address 0, you’ll have:

EEPROM.write(0, 9);

Followed by

EEPROM.commit();

For the changes to be saved.

Read

To read a byte from the flash memory, you use the EEPROM.read() function. This function takes the address of the byte you want to read as an argument.

EEPROM.read(address);

For example, to read the byte stored previously in address 0, use:

EEPROM.read(0);

This would return 9, which is the value we stored in address 0.

SCHEMATIC

Wire a pushbutton and an LED to the ESP32 as shown in the following schematic diagram.

CODE

// include library to read and write from flash memory
#include <EEPROM.h>

// define the number of bytes you want to access
#define EEPROM_SIZE 1

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 4;    // the number of the pushbutton pin
const int ledPin = 16;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() { 
  Serial.begin(115200);
  
  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);

  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

  // read the last LED state from flash memory
  ledState = EEPROM.read(0);
  // set the LED to the last stored state
  digitalWrite(ledPin, ledState);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }
  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;
  
  // if the ledState variable is different from the current LED state
  if (digitalRead(ledPin)!= ledState) {  
    Serial.println("State changed");
    // change the LED state
    digitalWrite(ledPin, ledState);
    // save the LED state in flash memory
    EEPROM.write(0, ledState);
    EEPROM.commit();
    Serial.println("State saved in flash memory");
  }
}

HOW CODE WORKS

This is a debounce code that changes the state of the LED every time the pushbutton is pressed. But there’s something unique about this code: it remembers the last LED state even after the ESP32 is reset or turned off. Let’s look at how to get the ESP32 to remember the last state of a GPIO.

You must first include the EEPROM library.

#include <EEPROM.h>

The EEPROM size is then determined. This is the number of bytes in the flash memory that you want to access. We’ll only save the LED status in this scenario, therefore the EEPROM size is set to 1.

#define EEPROM_SIZE 1

We also define other variables that are required to make this sketch work.

// constants won’t change. They’re used here to set pin numbers: 

const int buttonPin = 4; // the number of the pushbutton pin 

const int ledPin = 16; // the number of the LED pin 

// Variables will change: 

int ledState = HIGH; 

// the current state of the output pin 

int buttonState; // the current reading from the input pin 

int lastButtonState = LOW; // the previous reading from the input pin 

// the following variables are unsigned longs because the time, measured in 

// milliseconds, will quickly become a bigger number than can be stored in an int. unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers

setup()

In the setup() you initialize the EEPROM with the predefined size.

EEPROM.begin(EEPROM_SIZE);

To make sure your code initializes with the latest LED state, in the setup(), you should read the last LED state from the flash memory. It is stored on address zero.

ledState = EEPROM.read(0);

Then, you just need to turn the LED ON or OFF accordingly to the value read from the flash memory.

digitalWrite (ledPin, ledState);

loop()

The following part of the loop() checks if the pushbutton was pressed and changes the ledState variable every time we press the pushbutton. To make sure we don’t get false positives we use a timer. This snippet of code is based on the pushbutton debounce sketch example from the Arduino IDE.

// read the state of the switch into a local variable:

int reading = digitalRead(buttonPin);

// check to see if you just pressed the button

// (i.e. the input went from LOW to HIGH), and you’ve waited long enough

// since the last press to ignore any noise:

// If the switch changed, due to noise or pressing:

if (reading != lastButtonState) {

  // reset the debouncing timer

  lastDebounceTime = millis();

}

if ((millis() – lastDebounceTime) > debounceDelay) {

  // whatever the reading is at, it’s been there for longer than the debounce

  // delay, so take it as the actual current state:

  // if the button state has changed:

  if (reading != buttonState) {

    buttonState = reading;

  // only toggle the LED if the new button state is HIGH

    if (buttonState == HIGH) {

      ledState = !ledState;

    }

  }

}

// save the reading. Next time through the loop, it’ll be the lastButtonState:

lastButtonState = reading;

You simply need to save the LED state in the flash memory every time the LED state changes.

We check if the state of the GPIO is different from the ledState variable.

if (digitalRead(ledPin)!= ledState) {

If it is, we’ll change the LED state using the digitalWrite() function.

digitalWrite(ledPin, ledState);

The current state is then saved in flash memory. For that, we use EEPROM.write(), and pass as arguments the address position, in this case 0, and the value to be saved, in this case the ledState variable.

EEPROM.write(0, ledState);

Finally, we use the EEPROM.commit() for the changes to take effect.

EEPROM.commit();

DEMONSTRATION

After uploading the code to your ESP32, press the pushbutton to turn the LED on and off. The ESP32 should keep the last LED state after resetting or removing power.

CONCLUSION

In this article, we learned how to use the EEPROM library to save data in the ESP32 flash memory. Even after resetting the ESP32 or turning off the power, data recorded on the flash memory persists.

Author

Write A Comment