{"id":102041,"date":"2021-03-02T15:35:28","date_gmt":"2021-03-02T15:35:28","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=102041"},"modified":"2024-12-06T10:27:49","modified_gmt":"2024-12-06T10:27:49","slug":"esp32-save-data-permanently-preferences","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-save-data-permanently-preferences\/","title":{"rendered":"ESP32 Save Data Permanently using Preferences Library"},"content":{"rendered":"\n<p>This guide shows how to save data permanently on the ESP32 flash memory using the <span class=\"rnthl rntliteral\">Preferences.h<\/span> library. The data held in the flash memory persists across resets or power failures. Using the<span class=\"rnthl rntliteral\"> Preferences.h<\/span> library is useful to save data like network credentials, API keys, threshold values, or even the last state of a GPIO. You&#8217;ll learn how to save and read data from flash memory.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Data-Permanently-Preferences-Library.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Save Data Permanently using the Preferences Library\" class=\"wp-image-102117\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Data-Permanently-Preferences-Library.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Data-Permanently-Preferences-Library.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Data-Permanently-Preferences-Library.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Data-Permanently-Preferences-Library.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>In this tutorial, we&#8217;ll cover the following topics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#save-key-value\">Save <em>key:value<\/em> pairs<\/a>;<\/li>\n\n\n\n<li><a href=\"#read-key\">Read a <em>key <\/em>value<\/a>;<\/li>\n\n\n\n<li><a href=\"#example1\">Example 1: Save key:value pairs<\/a>;<\/li>\n\n\n\n<li><a href=\"#example2\">Example 2: ESP32 &#8211; Save\/Read Network Credentials using the Preferences.h Library<\/a>;<\/li>\n\n\n\n<li><a href=\"#example3\">Example 3: ESP32 &#8211; Remember Last GPIO State After RESET<\/a>;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Preferences.h Library<\/h2>\n\n\n\n<p>In a <a href=\"https:\/\/randomnerdtutorials.com\/esp32-flash-memory\/\">previous tutorial<\/a>, we recommended using the EEPROM library to save data on flash memory. However, the EEPROM library is deprecated in favor of the <span class=\"rnthl rntliteral\">Preferences.h<\/span> library. This library is &#8220;installed&#8221; automatically when you install the ESP32 boards in your Arduino IDE.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">Preferences.h<\/span> library is preferably used to store variable values through key:value pairs. Saving data permanently can be important to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>remember the last state of a variable;<\/li>\n\n\n\n<li>save settings;<\/li>\n\n\n\n<li>save how many times an appliance was activated;<\/li>\n\n\n\n<li>or any other data type you need to save permanently.<\/li>\n<\/ul>\n\n\n\n<p>If, instead of variables, you need to save files on the ESP32, we recommend using the filesystem (SPIFFS) instead. To learn how to save files in the ESP32 filesystem, you can read one of the following tutorials:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/install-esp32-filesystem-uploader-arduino-ide\/\">Install ESP32 Filesystem Uploader in Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-vs-code-platformio-spiffs\/\">ESP32 with VS Code and PlatformIO: Upload Files to Filesystem (SPIFFS)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Save Data Using Preferences.h Library<\/h2>\n\n\n\n<p>The data saved using preferences is structured like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>namespace {\n  key:value\n}<\/code><\/pre>\n\n\n\n<p>You can save different keys on the same namespace, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>namespace {\n  key1: value1\n  key2: value2\n}<\/code><\/pre>\n\n\n\n<p>In a practical example, this configuration could be used to save your network credentials:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>credentials {\n  ssid: \"your_ssid\"\n  pass: \"your_pass\"\n}<\/code><\/pre>\n\n\n\n<p>In the preceding example, <span class=\"rnthl rntliteral\">credentials<\/span> is the namespace, and <span class=\"rnthl rntliteral\">ssid<\/span> and <span class=\"rnthl rntliteral\">pass<\/span> are the keys.<\/p>\n\n\n\n<p>You can also have multiple namespaces with the same key (but each key with its value):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>namespace1{\n  key:value1\n}\nnamespace2{\n  key:value2\n}<\/code><\/pre>\n\n\n\n<p>When using the <span class=\"rnthl rntliteral\">Preferences.h<\/span> library, you should define the data type you want to save. Later, if you want to read that data, you must know the saved data type. In other words, the data type of writing and reading should be the same.<\/p>\n\n\n\n<p>You can save the following data types using <span class=\"rnthl rntliteral\">Preferences.h<\/span>: char, Uchar, short, Ushort, int, Uint, long, Ulong, long64, Ulong64, float, double, bool, string and bytes. <\/p>\n\n\n\n<p>For more information, you can access the <a href=\"https:\/\/github.com\/espressif\/arduino-esp32\/blob\/master\/libraries\/Preferences\/src\/Preferences.cpp\" target=\"_blank\" rel=\"noreferrer noopener\">Preferences.cpp file here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Preferences.h Library Useful Functions<\/h2>\n\n\n\n<p>To use the <span class=\"rnthl rntliteral\">Preferences.h<\/span> library to store data, first you need to include it in your sketch:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;Preferences.h&gt;<\/code><\/pre>\n\n\n\n<p>Then, you must initiate an instance of the Preferences library. You can call it <span class=\"rnthl rntliteral\">preferences<\/span>, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Preferences preferences;<\/code><\/pre>\n\n\n\n<p>After this, you can use the following methods to handle data using the <span class=\"rnthl rntliteral\">Preferences.h<\/span> library.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Start Preferences<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">begin()<\/span> method opens a &#8220;storage space&#8221; with a defined namespace. The <span class=\"rnthl rntliteral\">false<\/span> argument means that we&#8217;ll use it in read\/write mode. Use <span class=\"rnthl rntliteral\">true<\/span> to open or create the namespace in read-only mode.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.begin(\"my-app\", false); <\/code><\/pre>\n\n\n\n<p>In this case, the namespace name is <span class=\"rnthl rntliteral\">my-app<\/span>. <strong>Namespace name is limited to 15 characters.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Clear Preferences<\/h3>\n\n\n\n<p>Use <span class=\"rnthl rntliteral\">clear()<\/span> to clear all preferences under the opened namespace (it doesn&#8217;t delete the namespace):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.clear();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Remove Key<\/h3>\n\n\n\n<p>Remove a key from the opened namespace:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.remove(key);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Close Preferences<\/h3>\n\n\n\n<p>Use the <span class=\"rnthl rntliteral\">end()<\/span> method to close the preferences under the opened namespace:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.end();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"save-key-value\">Put a Key Value (Save a value)<\/h3>\n\n\n\n<p>You should use different methods depending on the variable type you want to save.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Char<\/strong><\/td><td><span class=\"rnthl rntliteral\">putChar(const char* key, int8_t value)<\/span><\/td><\/tr><tr><td><strong>Unsigned Char<\/strong><\/td><td><span class=\"rnthl rntliteral\">putUChar(const char* key, int8_t value)<\/span><\/td><\/tr><tr><td><strong>Short<\/strong><\/td><td><span class=\"rnthl rntliteral\">putShort(const char* key, int16_t value)<\/span><\/td><\/tr><tr><td><strong>Unsigned Short<\/strong><\/td><td><span class=\"rnthl rntliteral\">putUShort(const char* key, uint16_t value)<\/span><\/td><\/tr><tr><td><strong>Int<\/strong><\/td><td><span class=\"rnthl rntliteral\">putInt(const char* key, int32_t value)<\/span><\/td><\/tr><tr><td><strong>Unsigned Int<\/strong><\/td><td><span class=\"rnthl rntliteral\">putUInt(const char* key, uint32_t value)<\/span><\/td><\/tr><tr><td><strong>Long<\/strong><\/td><td><span class=\"rnthl rntliteral\">putLong(const char* key, int32_t value)<\/span><\/td><\/tr><tr><td><strong>Unsigned Long<\/strong><\/td><td><span class=\"rnthl rntliteral\">putULong(const char* key, uint32_t value)<\/span><\/td><\/tr><tr><td><strong>Long64<\/strong><\/td><td><span class=\"rnthl rntliteral\">putLong64(const char* key, int64_t value)<\/span><\/td><\/tr><tr><td><strong>Unsigned Long64<\/strong><\/td><td><span class=\"rnthl rntliteral\">putULong64(const char* key, uint64_t value)<\/span><\/td><\/tr><tr><td><strong>Float<\/strong><\/td><td><span class=\"rnthl rntliteral\">putFloat(const char* key, const float_t value)<\/span><\/td><\/tr><tr><td><strong>Double<\/strong><\/td><td><span class=\"rnthl rntliteral\">putDouble(const char* key, const double_t value)<\/span><\/td><\/tr><tr><td><strong>Bool<\/strong><\/td><td><span class=\"rnthl rntliteral\">putBool(const char* key, const bool value)<\/span><\/td><\/tr><tr><td><strong>String<\/strong><\/td><td><span class=\"rnthl rntliteral\">putString(const char* key, const String value)<\/span><\/td><\/tr><tr><td><strong>Bytes<\/strong><\/td><td><span class=\"rnthl rntliteral\">putBytes(const char* key, const void* value, size_t len)<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"read-key\">Get a Key Value (Read Value)<\/h3>\n\n\n\n<p>Similarly, you should use different methods depending on the variable type you want to get.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Char<\/strong><\/td><td><span class=\"rnthl rntliteral\">getChar(const char* key, const int8_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Unsigned Char<\/strong><\/td><td><span class=\"rnthl rntliteral\">getUChar(const char* key, const uint8_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Short<\/strong><\/td><td><span class=\"rnthl rntliteral\">getShort(const char* key, const int16_t defaultValue<\/span><\/td><\/tr><tr><td><strong>Unsigned Short<\/strong><\/td><td><span class=\"rnthl rntliteral\">getUShort(const char* key, const uint16_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Int<\/strong><\/td><td><span class=\"rnthl rntliteral\">getInt(const char* key, const int32_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Unsigned Int<\/strong><\/td><td><span class=\"rnthl rntliteral\">getUInt(const char* key, const uint32_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Long<\/strong><\/td><td><span class=\"rnthl rntliteral\">getLong(const char* key, const int32_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Unsigned Long<\/strong><\/td><td><span class=\"rnthl rntliteral\">getULong(const char* key, const uint32_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Long64<\/strong><\/td><td><span class=\"rnthl rntliteral\">getLong64(const char* key, const int64_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Unsigned Long64<\/strong><\/td><td><span class=\"rnthl rntliteral\">getULong64(const char* key, const uint64_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Float<\/strong><\/td><td><span class=\"rnthl rntliteral\">getFloat(const char* key, const float_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Double<\/strong><\/td><td><span class=\"rnthl rntliteral\">getDouble(const char* key, const double_t defaultValue)<\/span><\/td><\/tr><tr><td><strong>Bool<\/strong><\/td><td><span class=\"rnthl rntliteral\">getBool(const char* key, const bool defaultValue)<\/span><\/td><\/tr><tr><td><strong>String<\/strong><\/td><td><span class=\"rnthl rntliteral\">getString(const char* key, const String defaultValue)<\/span><\/td><\/tr><tr><td><strong>String<\/strong><\/td><td><span class=\"rnthl rntliteral\">getString(const char* key, char* value, const size_t maxLen)<\/span><\/td><\/tr><tr><td><strong>Bytes<\/strong><\/td><td><span class=\"rnthl rntliteral\">getBytes(const char* key, void * buf, size_t maxLen)<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Remove a Namespace<\/h3>\n\n\n\n<p>In the Arduino implementation of Preferences, there is no method of completely removing a namespace. As a result, over the course of several projects, the ESP32 non-volatile storage (nvs) Preferences partition may become full. To completely erase and reformat the NVS memory used by Preferences, create a sketch that contains:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;nvs_flash.h&gt;\n\nvoid setup() {\n  nvs_flash_erase(); \/\/ erase the NVS partition and...\n  nvs_flash_init(); \/\/ initialize the NVS partition.\n  while(true);\n}\n\nvoid loop() {\n\n}<\/code><\/pre>\n\n\n\n<p>You should download a new sketch to your board immediately after running the above, or it will reformat the NVS partition every time it is powered up.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"example1\">Preferences.h &#8211; Save key:value Pairs<\/h2>\n\n\n\n<p>For a simple example on how to save and get data using <span class=\"rnthl rntliteral\">Preferences.h<\/span>, in your Arduino IDE, go to <strong>File <\/strong>&gt; <strong>Examples <\/strong>&gt; <strong>Preferences <\/strong>&gt; <strong>StartCounter<\/strong>.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n ESP32 startup counter example with Preferences library.\n\n This simple example demonstrates using the Preferences library to store how many times the ESP32 module has booted. \n The Preferences library is a wrapper around the Non-volatile storage on ESP32 processor.\n\n created for arduino-esp32 09 Feb 2017 by Martin Sloup (Arcao)\n \n Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-save-data-permanently-preferences\/\n*\/\n\n#include &lt;Preferences.h&gt;\n\nPreferences preferences;\n\nvoid setup() {\n  Serial.begin(115200);\n  Serial.println();\n\n  \/\/ Open Preferences with my-app namespace. Each application module, library, etc\n  \/\/ has to use a namespace name to prevent key name collisions. We will open storage in\n  \/\/ RW-mode (second parameter has to be false).\n  \/\/ Note: Namespace name is limited to 15 chars.\n  preferences.begin(&quot;my-app&quot;, false);\n\n  \/\/ Remove all preferences under the opened namespace\n  \/\/preferences.clear();\n\n  \/\/ Or remove the counter key only\n  \/\/preferences.remove(&quot;counter&quot;);\n\n  \/\/ Get the counter value, if the key does not exist, return a default value of 0\n  \/\/ Note: Key name is limited to 15 chars.\n  unsigned int counter = preferences.getUInt(&quot;counter&quot;, 0);\n\n  \/\/ Increase counter by 1\n  counter++;\n\n  \/\/ Print the counter to Serial Monitor\n  Serial.printf(&quot;Current counter value: %u\\n&quot;, counter);\n\n  \/\/ Store the counter to the Preferences\n  preferences.putUInt(&quot;counter&quot;, counter);\n\n  \/\/ Close the Preferences\n  preferences.end();\n\n  \/\/ Wait 10 seconds\n  Serial.println(&quot;Restarting in 10 seconds...&quot;);\n  delay(10000);\n\n  \/\/ Restart ESP\n  ESP.restart();\n}\n\nvoid loop() {\n\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/Preferences\/ESP32_StartCounter.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>This example increases a variable called <span class=\"rnthl rntliteral\">counter<\/span> between resets. This illustrates that the ESP32 &#8220;remembers&#8221; the value even after a reset.<\/p>\n\n\n\n<p>Upload the previous sketch to your ESP32 board. Open the Serial Monitor at a baud rate of 115200 and press the on-board RST button. You should see the <span class=\"rnthl rntliteral\">counter<\/span> variable increasing between resets.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"952\" height=\"669\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-StartCounter-Example-Serial-Monitor.png?resize=952%2C669&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Preferences StartCounter Example Serial Monitor\" class=\"wp-image-102104\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-StartCounter-Example-Serial-Monitor.png?w=952&amp;quality=100&amp;strip=all&amp;ssl=1 952w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-StartCounter-Example-Serial-Monitor.png?resize=300%2C211&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-StartCounter-Example-Serial-Monitor.png?resize=768%2C540&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 952px) 100vw, 952px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>This example uses the functions we&#8217;ve seen in the previous sections.<\/p>\n\n\n\n<p>First, include the <span class=\"rnthl rntliteral\">Preferences.h<\/span> library.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;Preferences.h&gt;<\/code><\/pre>\n\n\n\n<p>Then, create an instance of the library called <span class=\"rnthl rntliteral\">preferences<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Preferences preferences;<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the Serial Monitor at a baud rate of 115200.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Create a &#8220;storage space&#8221; in the flash memory called <span class=\"rnthl rntliteral\">my-app<\/span> in read\/write mode. You can give it any other name.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.begin(\"my-app\", false);<\/code><\/pre>\n\n\n\n<p>Get the value of the <span class=\"rnthl rntliteral\">counter<\/span> key saved on preferences. If it doesn&#8217;t find any value, it returns <span class=\"rnthl rntliteral\">0<\/span> by default (which happens when this code runs for the first time).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned int counter = preferences.getUInt(\"counter\", 0);<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">counter<\/span> variable is increased one unit every time the ESP runs:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>counter++;<\/code><\/pre>\n\n\n\n<p>Print the value of the <span class=\"rnthl rntliteral\">counter<\/span> variable:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.printf(\"Current counter value: %u\\n\", counter);<\/code><\/pre>\n\n\n\n<p>Store the new value on the <span class=\"rnthl rntliteral\">&#8220;counter&#8221;<\/span> key:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.putUInt(\"counter\", counter);<\/code><\/pre>\n\n\n\n<p>Close the Preferences.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.end();<\/code><\/pre>\n\n\n\n<p>Finally, restart the ESP32 board:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ESP.restart();<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"example2\">ESP32 &#8211; Save\/Read Network Credentials using the Preferences.h Library<\/h2>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">Preferences.h<\/span> library is many times used to save your network credentials permanently on the flash memory. This way, you don&#8217;t have to hard code the credentials in every sketch that involves connecting the ESP32 to the internet. <\/p>\n\n\n\n<p>In this section, we&#8217;ll show you two simple sketches that might be useful in your projects:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#example2-1\">Save Network Credentials using Preferences.h<\/a><\/li>\n\n\n\n<li><a href=\"#example2-2\">Connect to Wi-Fi with Network Credentials Saved on Preferences<\/a><\/li>\n<\/ul>\n\n\n\n<p>To learn more about ESP32 Wi-Fi related functions, read the following article:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-useful-wi-fi-functions-arduino\/\">ESP32 Useful Wi-Fi Library Functions (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"example2-1\">Save Network Credentials using Preferences.h<\/h3>\n\n\n\n<p>The following sketch saves your network credentials permanently on the ESP32 flash memory using <span class=\"rnthl rntliteral\">Preferences.h<\/span>.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n  Rui Santos\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-save-data-permanently-preferences\/\n  \n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files.\n  \n  The above copyright notice and this permission notice shall be included in all\n  copies or substantial portions of the Software.\n*\/\n\n#include &lt;Preferences.h&gt;\n\nPreferences preferences;\n\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\n\nvoid setup() {\n  Serial.begin(115200);\n  Serial.println();\n\n  preferences.begin(&quot;credentials&quot;, false);\n  preferences.putString(&quot;ssid&quot;, ssid); \n  preferences.putString(&quot;password&quot;, password);\n\n  Serial.println(&quot;Network Credentials Saved using Preferences&quot;);\n\n  preferences.end();\n}\n\nvoid loop() {\n\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/Preferences\/ESP32_Save_Credentials.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Don&#8217;t forget to insert your network credentials in the following variables:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ssid = \"REPLACE_WITH_YOUR_SSID\";\nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">How the Code Works<\/h4>\n\n\n\n<p>Let&#8217;s take a quick look at the relevant parts of the code for this example.<\/p>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, create a new storage space on the flash memory with the <span class=\"rnthl rntliteral\">credentials<\/span> namespace.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.begin(\"credentials\", false);<\/code><\/pre>\n\n\n\n<p>Then, create a key called <span class=\"rnthl rntliteral\">ssid<\/span> that saves your SSID value (<span class=\"rnthl rntliteral\">ssid<\/span> variable) &#8211; use the <span class=\"rnthl rntliteral\">putString()<\/span> method.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.putString(\"ssid\", ssid); <\/code><\/pre>\n\n\n\n<p>Add another key called <span class=\"rnthl rntliteral\">password<\/span> to save the password value (<span class=\"rnthl rntliteral\">password<\/span> variable):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.putString(\"password\", password);<\/code><\/pre>\n\n\n\n<p>So, your data is structured in this way:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>credentials{\n  ssid: your_ssid\n  password: your_password\n}<\/code><\/pre>\n\n\n\n<p>Upload the code to your board and this is what you should get on the Serial Monitor:<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"688\" height=\"541\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Network-Credentials-Preferences-Library.png?resize=688%2C541&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Save Network Credentials using Preferences Library\" class=\"wp-image-102109\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Network-Credentials-Preferences-Library.png?w=688&amp;quality=100&amp;strip=all&amp;ssl=1 688w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Network-Credentials-Preferences-Library.png?resize=300%2C236&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/figure><\/div>\n\n\n<p>In the following example, we&#8217;ll show you how to read the network credentials from preferences and use them to connect the ESP32 to your network.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"example2-2\">Connect to Wi-Fi with Network Credentials Saved on Preferences<\/h3>\n\n\n\n<p>The following sketch gets the network credentials&#8217; values and connects to your network using those credentials.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n  Rui Santos\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-save-data-permanently-preferences\/\n  \n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files.\n  \n  The above copyright notice and this permission notice shall be included in all\n  copies or substantial portions of the Software.\n*\/\n\n#include &lt;Preferences.h&gt;\n#include &quot;WiFi.h&quot;\n\nPreferences preferences;\n\nString ssid;\nString password;\n\nvoid setup() {\n  Serial.begin(115200);\n  Serial.println();\n  \n  preferences.begin(&quot;credentials&quot;, false);\n \n  ssid = preferences.getString(&quot;ssid&quot;, &quot;&quot;); \n  password = preferences.getString(&quot;password&quot;, &quot;&quot;);\n\n  if (ssid == &quot;&quot; || password == &quot;&quot;){\n    Serial.println(&quot;No values saved for ssid or password&quot;);\n  }\n  else {\n    \/\/ Connect to Wi-Fi\n    WiFi.mode(WIFI_STA);\n    WiFi.begin(ssid.c_str(), password.c_str());\n    Serial.print(&quot;Connecting to WiFi ..&quot;);\n    while (WiFi.status() != WL_CONNECTED) {\n      Serial.print('.');\n      delay(1000);\n    }\n    Serial.println(WiFi.localIP());  \n  }\n}\n\nvoid loop() {\n  \/\/ put your main code here, to run repeatedly:\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/Preferences\/ESP32_Connect_WiFi_Preferences.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">How the Code Works<\/h4>\n\n\n\n<p>Let&#8217;s take a quick look at the relevant parts of the code for this example.<\/p>\n\n\n\n<p>Open the <span class=\"rnthl rntliteral\">credentials<\/span> namespace:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.begin(\"credentials\", false);<\/code><\/pre>\n\n\n\n<p>Get the SSID and password values using the <span class=\"rnthl rntliteral\">getString()<\/span> method. You need to use the key name that you used to save the variables, in this case, <span class=\"rnthl rntliteral\">ssid<\/span> and <span class=\"rnthl rntliteral\">password<\/span> keys:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ssid = preferences.getString(\"ssid\", \"\"); \npassword = preferences.getString(\"password\", \"\");<\/code><\/pre>\n\n\n\n<p>As a second argument to the <span class=\"rnthl rntliteral\">getString()<\/span> function, we passed an empty String. This is the returned value in case there aren&#8217;t <span class=\"rnthl rntliteral\">ssid<\/span> or <span class=\"rnthl rntliteral\">password<\/span> keys saved on preferences.<\/p>\n\n\n\n<p>If that&#8217;s the case, we print a message indicating that there aren&#8217;t any saved values:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (ssid == \"\" || password == \"\"){\n  Serial.println(\"No values saved for ssid or password\");\n}<\/code><\/pre>\n\n\n\n<p>Otherwise, we connect to Wi-Fi using the SSID and password saved on preferences.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>else {\n  \/\/ Connect to Wi-Fi\n  WiFi.mode(WIFI_STA);\n  WiFi.begin(ssid.c_str(), password.c_str());\n  Serial.print(\"Connecting to WiFi ..\");\n  while (WiFi.status() != WL_CONNECTED) {\n    Serial.print('.');\n    delay(1000);\n  }\n  Serial.println(WiFi.localIP());\n}<\/code><\/pre>\n\n\n\n<p>Upload this code to your board after the previous one (to ensure that you have the credentials saved). If everything goes as expected, this is what you should get on your Serial Monitor.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"688\" height=\"470\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Connect-Network-Credentials-Saved-in-Preferences.png?resize=688%2C470&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Connect to Network with Credentials Saved on Preferences\" class=\"wp-image-102110\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Connect-Network-Credentials-Saved-in-Preferences.png?w=688&amp;quality=100&amp;strip=all&amp;ssl=1 688w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Connect-Network-Credentials-Saved-in-Preferences.png?resize=300%2C205&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/figure><\/div>\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"example3\">Remember Last GPIO State After RESET<\/h2>\n\n\n\n<p>Another application of the <span class=\"rnthl rntliteral\">Preferences.h<\/span> library is to save the last state of an output. For example, imagine the following scenario:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>You\u2019re controlling an output with the ESP32;<\/li>\n\n\n\n<li>You set your output to turn on;<\/li>\n\n\n\n<li>The ESP32 suddenly loses power;<\/li>\n\n\n\n<li>When the power comes back on, the output stays off \u2013 because it didn&#8217;t keep its last state.<\/li>\n<\/ol>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"228\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-Library-Remember-Last-GPIO-State-1.png?resize=750%2C228&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Preferences Library Remember Last GPIO State (without preferences)\" class=\"wp-image-102154\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-Library-Remember-Last-GPIO-State-1.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-Library-Remember-Last-GPIO-State-1.png?resize=300%2C91&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>You don\u2019t want this to happen. You want the ESP32 to remember what was happening before losing power and return to the last state.<\/p>\n\n\n\n<p>To solve this problem, you can save the output&#8217;s state in the flash memory. Then, you need to add a condition at the beginning of your sketch to check the last output state and turn it on or off accordingly.<\/p>\n\n\n\n<p>The following figure shows what we\u2019re going to do:<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"216\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-Library-Remember-Last-GPIO-State-2.png?resize=750%2C216&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Preferences Library Remember Last GPIO State\" class=\"wp-image-102155\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-Library-Remember-Last-GPIO-State-2.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Preferences-Library-Remember-Last-GPIO-State-2.png?resize=300%2C86&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>We&#8217;ll show you an example using an LED and a pushbutton. The pushbutton controls the LED state. The LED keeps its state between resets. This means that if the LED is lit when you remove power, it will be lit when it gets powered again.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Schematic Diagram<\/h3>\n\n\n\n<p>Wire a pushbutton and an LED to the ESP32 as shown in the following schematic diagram.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1065\" height=\"707\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/led_button_esp32_bb.png?resize=1065%2C707&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Schematics diagram circuit LED output pushbutton input\" class=\"wp-image-84226\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/led_button_esp32_bb.png?w=1065&amp;quality=100&amp;strip=all&amp;ssl=1 1065w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/led_button_esp32_bb.png?resize=300%2C199&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/led_button_esp32_bb.png?resize=768%2C510&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/led_button_esp32_bb.png?resize=1024%2C680&amp;quality=100&amp;strip=all&amp;ssl=1 1024w\" sizes=\"(max-width: 1065px) 100vw, 1065px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\">Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pinout-reference-gpios\/\">ESP32 Pinout Reference: Which GPIO pins should you use?<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Code<\/h2>\n\n\n\n<p>This is a debounce code that changes the LED state every time you press the pushbutton. But there\u2019s something special about this code \u2013 it remembers the last LED state, even after resetting or removing power from the ESP32. This is possible because we save the led state on Preferences whenever it changes.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n  Rui Santos\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-save-data-permanently-preferences\/\n  \n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files.\n  \n  The above copyright notice and this permission notice shall be included in all\n  copies or substantial portions of the Software.\n*\/\n\n#include &lt;Preferences.h&gt;\n\nPreferences preferences;\n\nconst int buttonPin = 4;    \nconst int ledPin = 5;      \n\nbool ledState;         \nbool buttonState;             \nint lastButtonState = LOW;\n\nunsigned long lastDebounceTime = 0;  \/\/ the last time the output pin was toggled\nunsigned long debounceDelay = 50;    \/\/ the debounce time; increase if the output flickers\n\nvoid setup() { \n  Serial.begin(115200);\n\n  \/\/Create a namespace called &quot;gpio&quot;\n  preferences.begin(&quot;gpio&quot;, false);\n\n  pinMode(buttonPin, INPUT);\n  pinMode(ledPin, OUTPUT);\n\n  \/\/ read the last LED state from flash memory\n  ledState = preferences.getBool(&quot;state&quot;, false); \n  Serial.printf(&quot;LED state before reset: %d \\n&quot;, ledState);\n  \/\/ set the LED to the last stored state\n  digitalWrite(ledPin, ledState);\n}\n\nvoid loop() {\n  int reading = digitalRead(buttonPin);\n\n  if (reading != lastButtonState) {\n    lastDebounceTime = millis();\n  }\n  if ((millis() - lastDebounceTime) &gt; debounceDelay) {\n    if (reading != buttonState) {\n      buttonState = reading;\n      if (buttonState == HIGH) {\n        ledState = !ledState;\n      }\n    }\n  }\n  lastButtonState = reading;\n  if (digitalRead(ledPin)!= ledState) {  \n    Serial.println(&quot;State changed&quot;);\n    \/\/ change the LED state\n    digitalWrite(ledPin, ledState);\n    \n    \/\/ save the LED state in flash memory\n    preferences.putBool(&quot;state&quot;, ledState);\n    \n    Serial.printf(&quot;State saved: %d \\n&quot;, ledState);\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/Preferences\/ESP32_Remember_Last_State.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>Let\u2019s take a quick look at the relevant parts of code for this example.<\/p>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, start by creating a section in the flash memory to save the GPIO state. In this example, we&#8217;ve called it <span class=\"rnthl rntliteral\">gpio<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>preferences.begin(\"gpio\", false);<\/code><\/pre>\n\n\n\n<p>Get the GPIO state saved on Preferences on the <span class=\"rnthl rntliteral\">state<\/span> key. It is a boolean variable, so use the <span class=\"rnthl rntliteral\">getBool()<\/span> function. If there isn&#8217;t any <span class=\"rnthl rntliteral\">state<\/span> key yet (which happens when the ESP32 first runs), return <span class=\"rnthl rntliteral\">false<\/span> (the LED will be off).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ledState = preferences.getBool(\"state\", false); <\/code><\/pre>\n\n\n\n<p>Print the state and set the LED to the right state:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.printf(\"LED state before reset: %d \\n\", ledState);\n\/\/ set the LED to the last stored state\ndigitalWrite(ledPin, ledState);<\/code><\/pre>\n\n\n\n<p>Finally, in the <span class=\"rnthl rntliteral\">loop()<\/span> update the <span class=\"rnthl rntliteral\">state<\/span> key on Preferences whenever there&#8217;s a change.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ save the LED state in flash memory\npreferences.putBool(\"state\", ledState);\n\nSerial.printf(\"State saved: %d \\n\", ledState);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>Upload the code to your board and wire the circuit. Open the Serial Monitor at a baud rate of 115200 and press the on-board RST button. <\/p>\n\n\n\n<p>Press the pushbutton to change the LED state and then remove power or press the RST button.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"414\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/micropython-esp32-esp8266-inputs-outputs.jpg?resize=750%2C414&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Schematics diagram circuit LED output pushbutton input demonstration testing\" class=\"wp-image-84230\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/micropython-esp32-esp8266-inputs-outputs.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/04\/micropython-esp32-esp8266-inputs-outputs.jpg?resize=300%2C166&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>When the ESP32 restarts, it will read the last state saved on Preferences and set the LED to that state. It also prints a message on the Serial Monitor whenever there&#8217;s a change on the GPIO state.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"688\" height=\"512\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Remember-Last-LED-State-Preferences.png?resize=688%2C512&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Remember Last LED State Preferences\" class=\"wp-image-102113\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Remember-Last-LED-State-Preferences.png?w=688&amp;quality=100&amp;strip=all&amp;ssl=1 688w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Remember-Last-LED-State-Preferences.png?resize=300%2C223&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you&#8217;ve learned how to save data permanently on the ESP32 flash memory using the Preferences.h library. This library is handy to save key:value pairs. Data held on the flash memory remains there even after resetting the ESP32 or removing power. <\/p>\n\n\n\n<p>If you need to store bigger amounts of data or files, you should use the ESP32 filesystem (SPIFFS) or a microSD card instead:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/install-esp32-filesystem-uploader-arduino-ide\/\">Install ESP32 Filesystem Uploader in Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-vs-code-platformio-spiffs\/\">ESP32 with VS Code and PlatformIO: Upload Files to Filesystem (SPIFFS)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-data-logging-temperature-to-microsd-card\/\">ESP32 Data Logging Temperature to MicroSD Card<\/a><\/li>\n<\/ul>\n\n\n\n<p>We hope you\u2019ve found this tutorial useful.<\/p>\n\n\n\n<p>Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build Web Servers with ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">More ESP32 Projects and Tutorials\u2026<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This guide shows how to save data permanently on the ESP32 flash memory using the Preferences.h library. The data held in the flash memory persists across resets or power failures. &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 Save Data Permanently using Preferences Library\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-save-data-permanently-preferences\/#more-102041\" aria-label=\"Read more about ESP32 Save Data Permanently using Preferences Library\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":102117,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-102041","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/02\/ESP32-Save-Data-Permanently-Preferences-Library.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/102041","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=102041"}],"version-history":[{"count":2,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/102041\/revisions"}],"predecessor-version":[{"id":164423,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/102041\/revisions\/164423"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/102117"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=102041"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=102041"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=102041"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}