In this article we’ll show you how to store and read values from the ESP32 flash memory using Arduino IDE. The data saved in the flash memory remains there even when the ESP32 resets or when power is removed. As an example we’ll show you how to save the last GPIO state.
This tutorial is outdated. Follow the new tutorial instead: [NEW] ESP32 Save Data Permanently using Preferences Library
Before proceeding with this tutorial you should have the ESP32 add-on installed in your Arduino IDE. Follow one of the following tutorials to install the ESP32 on the Arduino IDE, if you haven’t already.
- Installing the ESP32 Board in Arduino IDE (Windows instructions)
- Installing the ESP32 Board in Arduino IDE (Mac and Linux instructions)
We also recommend taking a look at the following resources:
Watch the Video Tutorial
This tutorial is available in video format (watch below) and in written format (continue reading).
Parts Required
To follow this tutorial you need the following components:
- ESP32 DOIT DEVKIT V1 Board – read ESP32 Development Boards Review and Comparison
- 5mm LED
- 330 Ohm resistor
- Pushbutton
- 10k Ohm resistor
- Breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Flash Memory
The data saved in the flash memory remains there even when the ESP32 resets or when power is removed. The flash memory is very similar to the EEPROM. Both are non-volatile memories.
Saving data in the flash memory is specially useful to:
- remember the last state of a variable;
- save settings;
- save how many times an appliance was activated;
- or any other type of data that you need to have saved permanently.
One limitation with flash memory is the number of times you can write data to it. Data can be read from flash as many times as you want, but most devices are designed for about 100,000 to 1,000,000 write operations.
EEPROM Library
To read and write from the ESP32 flash memory using Arduino IDE, we’ll be using the EEPROM library. Using this library with the ESP32 is very similar to using it with the Arduino. So, if you’ve used the Arduino EEPROM before, this is not much different.
So, we also recommend taking a look at our article about Arduino EEPROM.
With the ESP32 and the EEPROM library you can use up to 512 bytes in the flash memory. This means you have 512 different addresses, and you can save a value between 0 and 255 in each address position.
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.
Remember Last GPIO State
To show you how to save data in the ESP32 flash memory, we’ll save the last state of an output, in this case an LED. For example, imagine the following scenario:
- You’re controlling a lamp with the ESP32
- You set your lamp to turn on
- The ESP32 suddenly loses power
- When the power comes back on, the lamp stays off – because it doesn’t keep its last state
You don’t want this to happen. You want the ESP32 to remember what was happening before losing power and return to the last state.
To solve this problem, you can save the lamp’s state in the flash memory. Then, you just need to add a condition at the beginning of your sketch to check the last lamp state, and turn the lamp on or off accordingly.
The following figure shows what we’re going to do:
Schematic
Wire a pushbutton and an LED to the ESP32 as shown in the following schematic diagram.
Code
Copy the following code to the Arduino IDE and upload it to your ESP32. Make sure you have the right board and COM port selected.
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
// 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 the Code Works
Let’s take a quick look at the code.
This is a debounce code that changes the LED state every time you press the pushbutton. But there’s something special about this code – it remembers the last LED state, even after resetting or removing power from the ESP32. Let’s see what you have to do to make the ESP32 remember the last state of a GPIO.
First, you need to include the EEPROM library.
#include <EEPROM.h>
Then, you define the EEPROM size. This is the number of bytes you’ll want to access in the flash memory. In this case, we’ll just save the LED state, so 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);
And then, we save the current state in the 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.
Wrapping Up
In summary, in this unit you’ve learned how to save data in the ESP32 flash memory using the EEPROM library. Data saved on the flash memory remains there even after resetting the ESP32 or removing power.
We have other articles about ESP32 that you may like:
- How to use ESP32 Dual Core with Arduino IDE
- ESP32 PWM with Arduino IDE
- ESP32 Pinout Reference: Which GPIO pins should you use?
- ESP32 Deep Sleep and Wake Up Sources
This is an excerpt from our course: Learn ESP32 with Arduino IDE. If you like ESP32 and you want to learn more, we recommend enrolling in Learn ESP32 with Arduino IDE course.
I’m glad you noted the limitation of the number of writes to the EEPROM. It’s perhaps the most important note. I’ve commented on a similar project that left that out. It would be easy for people to think it’s a great way to store data repeatedly. Thanks
Seems this multiple write concern has been answered by
a) the fact that esp8266 does not write into EEPROM, but into RAM (and checks one does not write the same thing than in EEPROM – if one should write, a “dirty” flag is set-)
b) EEPROM.commit physically writes into EEPROM …. if dirty flag is set…
forum.arduino.cc/index.php?topic=509169.0
Is there an equivalent of “updating” -i.e.one reads at a given adress before writing at the same place -if previous and to write values are different-?
Is this mechanism provided by chip? software? Or should one provide it (soft is not that difficult: adds two lines)
A good article, as always – thank you.
Do you have any observations as to the differences between using EEPROM and SPIFFS – in terms of when it is advisable to use one vs the other?
-Kim
Hello Kim, unfortunately I don’t have any tutorial on that subject. Thanks for the suggestion!
Hi Rui,
I learn a lot from your writings. Thanks.
I’d like to know why EEPROM.writeFloat (address, data) and similar instructions don’t work? The code is running but nothing is stored in the EEPROM.
What can be done, for example, to store float numbers in the EEPROM?
The problem is solved!
(For data longer than bytes, the address of the EEPROM should be increased with the data length!)
EEPROM.put(addr,type) will place any type at the address.
I know there’s an Arduino library called EEPROMex.h which permits managing of floats in EEPROM.
I don’t know if this library Is compatibile in ESP32…
How can we store the DHT11 value in the EEPROM
Hi.
Yes, you can do that.
Regards,
Sara
How to do that..i am trying from last to many day but i am not getting output…so please share any reference aur tutorial. Thank you
Regards,
M A Shaikh
Using Bluetooth of one ESP32 can I communicate and read the EEPROM data of another esp32.
eg.
I have built an automatic blinds controller and, using my android mobile, I can change the any of the values of the EEPROM in the ESP-Vroom-32 . This way I don’t have to take the controller off the wall to modify my programme and change the twilight/daylight values. But I can’t see the updated values.
Is it possible to read the updated values in the EEPROM of the blinds’ ESP 32 using the Bluetooth of another ESP32 or the Bluetooth of my laptop.
Hi Malcom.
I think it is possible to do that, but you need to prepare your ESP32 to write the EEPROM value on a certain BLE characteristic that the other device can read.
Regards,
Sara
How can I write DHT11 values to EsP32 EEPROM ?
A question, dictated by curiosity: ESP32 platform on Arduino includes “Preferences” library.
Could you, please, detail which when is better ?
Thank you in advance,
M.Trifon
Hi.
You should use Preferences library.
EEPROM library is outdated.
Regards,
Sara
This may be a dumb question, but is there a way to delete data stored in EEPROM?
I’m not seeing any obivous EEPROM methods listed when I type
“EEPROM. ”
into PlatformIO IDE.
I’ve done a quick web query, and the only way I’ve seen is to do a loop through the EEPROMs and write 0 to each address. If that’s the case, it’s not worth doing, really.
As long as, say, each address can simply be written over with other data later…
Hi.
You can do that quickly by erasing the flash of your board:
https://rntlab.com/question/how-perform-reset-factory-esp32/
Regards,
Sara
Hi, I have a ccs811 and it give me a value > 400. Is there a way to keep this value when the ESP32 is in deepsleep. Of course, I tried in the EEPROM and it returned a value of 146
Hi.
Did you try using the preferences library?
Here’s a tutorial about that subject: https://randomnerdtutorials.com/esp32-save-data-permanently-preferences/
Regards,
Sara
hi im using an esp 8266
but put and get seems not working 🙁
i use EEPROM.begin(4194304) on setup function
and after each put command i used EEPROM.commit()
but still seeing no result
my board is a NodeMCU and i use NodeMCU1.0(ESP-12E Module) in Arduino 1.8.13
thanks for the all of your good work
another question
can we use whole 4MB of flash memory ?!
Hi
is there any way to define more than 512byte as EEPROM?
Hi,
How do you only save to flash if the value changes?
Hi.
It already does that automatically.
Regards,
Sara
Beware EEPROM.commit() – it takes 30ms and during that time interrupts aren’t handled. They get processed once commit is done.
All except the first interrupt that happen during those 30ms are ignored.
https://github.com/espressif/arduino-esp32/issues/8169
Hi Sara, I’ve been serching for tutorials on how to use external SPI flash memory chips, but have only found some about EEPROM. I would like, if it is possible, to use a flash memory chip as if it was an SD card to write and read strings. I really don’t know if there are any libraries that that allow to do this. I have previously used the internal memory on the ESP32 with the SPIFFS file system, but as far as I understand that it’s not the same as hooking up an external SPI flash memory module. My objective is to store G-code. Perhaps it could be more complicated than I think it is since there’s less information available about this topic.
If I wanted to write a value of more than 255 in a register, what can I do? Is it even possible?
Hi.
Here’s your answer: https://playground.arduino.cc/Code/EEPROMWriteAnything/
Regards,
Sara
Hi
Can use EEPROM and ESP32 like flash memory(micro sd card), and use for example this code:File MyFile = SD.open(dfName, “r”);
thanks
i want store 1500 string in ESP32 EEPROM each String size is 12 byte its possible
Hi.
I think this will help: https://forum.arduino.cc/t/eeprom-storing-numbers-larger-then-256/317188
Regards,
Sara