ESP32 Flash-память – сохранение данных (запись и чтение)
В этой статье мы покажем вам, как сохранять и считывать значения из flash-памяти ESP32 с помощью Arduino IDE. Данные, сохраненные в flash-памяти, остаются там даже при сбросе ESP32 или при отключении питания. В качестве примера мы покажем, как сохранить последнее состояние GPIO.
Это руководство устарело. Следуйте новому руководству: [НОВОЕ] ESP32 Сохранение данных с помощью библиотеки Preferences
Прежде чем приступить к этому руководству, у вас должно быть установлено дополнение ESP32 в вашей Arduino IDE. Следуйте одному из следующих руководств для установки ESP32 в Arduino IDE, если вы еще этого не сделали.
Установка платы ESP32 в Arduino IDE (инструкции для Windows)
Установка платы ESP32 в Arduino IDE (инструкции для Mac и Linux)
Мы также рекомендуем ознакомиться со следующими ресурсами:
Смотреть видеоурок
Это руководство доступно в видеоформате (смотрите ниже) и в текстовом формате (продолжайте чтение).
Необходимые компоненты
Для выполнения этого руководства вам понадобятся следующие компоненты:
Вы можете использовать приведенные выше ссылки или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!
Flash-память
Данные, сохраненные в flash-памяти, остаются там даже при сбросе ESP32 или при отключении питания. Flash-память очень похожа на EEPROM. Обе являются энергонезависимыми типами памяти.
Сохранение данных в flash-памяти особенно полезно для:
запоминания последнего состояния переменной;
сохранения настроек;
сохранения количества включений устройства;
или любого другого типа данных, которые необходимо хранить постоянно.
Одним из ограничений flash-памяти является количество циклов записи. Данные можно считывать из flash-памяти сколько угодно раз, но большинство устройств рассчитаны примерно на 100 000 – 1 000 000 операций записи.
Библиотека EEPROM
Для чтения и записи из flash-памяти ESP32 с помощью Arduino IDE мы будем использовать библиотеку EEPROM. Использование этой библиотеки с ESP32 очень похоже на использование с Arduino. Поэтому, если вы ранее использовали EEPROM на Arduino, здесь все практически так же.
Мы также рекомендуем ознакомиться с нашей статьей об Arduino EEPROM.
С ESP32 и библиотекой EEPROM вы можете использовать до 512 байт flash-памяти. Это означает, что у вас есть 512 различных адресов, и в каждый адрес можно сохранить значение от 0 до 255.
Запись (Write)
Для записи данных в flash-память используется функция EEPROM.write(), которая принимает в качестве аргументов адрес (позицию), куда вы хотите сохранить данные, и значение (переменная типа byte), которое вы хотите сохранить:
EEPROM.write(address, value);
Например, чтобы записать 9 по адресу 0, нужно написать:
EEPROM.write(0, 9);
Затем необходимо вызвать:
EEPROM.commit();
Чтобы изменения были сохранены.
Чтение (Read)
Для чтения байта из flash-памяти используется функция EEPROM.read(). Эта функция принимает в качестве аргумента адрес байта, который вы хотите прочитать.
EEPROM.read(address);
Например, чтобы прочитать байт, ранее сохраненный по адресу 0, используйте:
EEPROM.read(0);
Это вернет 9, то есть значение, которое мы сохранили по адресу 0.
Запоминание последнего состояния GPIO
Чтобы показать вам, как сохранять данные в flash-памяти ESP32, мы сохраним последнее состояние выхода, в данном случае светодиода. Например, представьте следующий сценарий:
Вы управляете лампой с помощью ESP32
Вы включаете лампу
ESP32 внезапно теряет питание
Когда питание восстанавливается, лампа остается выключенной – потому что она не сохраняет свое последнее состояние
Вы не хотите, чтобы так происходило. Вы хотите, чтобы ESP32 запоминал, что происходило до потери питания, и возвращался к последнему состоянию.
Для решения этой проблемы вы можете сохранить состояние лампы в flash-памяти. Затем вам просто нужно добавить условие в начале вашего скетча для проверки последнего состояния лампы и включить или выключить лампу соответственно.
На следующем рисунке показано, что мы собираемся сделать:
Схема подключения
Подключите кнопку и светодиод к ESP32, как показано на следующей принципиальной схеме.
Код
Скопируйте следующий код в Arduino IDE и загрузите его на ESP32. Убедитесь, что выбраны правильная плата и COM-порт.
/*********
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");
}
}
Как работает код
Давайте быстро рассмотрим код.
Это код с подавлением дребезга (debounce), который меняет состояние светодиода каждый раз при нажатии кнопки. Но в этом коде есть кое-что особенное – он запоминает последнее состояние светодиода даже после сброса или отключения питания ESP32. Давайте посмотрим, что нужно сделать, чтобы ESP32 запоминал последнее состояние GPIO.
Сначала необходимо подключить библиотеку EEPROM.
#include <EEPROM.h>
Затем вы определяете размер EEPROM. Это количество байтов, к которым вы хотите получить доступ в flash-памяти. В данном случае мы сохраняем только состояние светодиода, поэтому размер EEPROM установлен в 1.
#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
setup()
В функции setup() вы инициализируете EEPROM с заданным размером.
EEPROM.begin(EEPROM_SIZE);
Чтобы убедиться, что ваш код инициализируется с последним состоянием светодиода, в setup() вы должны прочитать последнее состояние светодиода из flash-памяти. Оно хранится по адресу ноль.
ledState = EEPROM.read(0);
Затем вам просто нужно включить или выключить светодиод в соответствии со значением, прочитанным из flash-памяти.
digitalWrite (ledPin, ledState);
loop()
Следующая часть loop() проверяет, была ли нажата кнопка, и меняет переменную ledState каждый раз при нажатии кнопки. Чтобы исключить ложные срабатывания, мы используем таймер. Этот фрагмент кода основан на примере скетча подавления дребезга кнопки из 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;
Вам просто нужно сохранять состояние светодиода в flash-памяти каждый раз, когда состояние светодиода изменяется.
Мы проверяем, отличается ли состояние GPIO от переменной ledState.
if (digitalRead(ledPin)!= ledState) {
Если отличается, мы изменяем состояние светодиода с помощью функции digitalWrite().
digitalWrite(ledPin, ledState);
Затем мы сохраняем текущее состояние в flash-памяти. Для этого мы используем EEPROM.write() и передаем в качестве аргументов позицию адреса, в данном случае 0, и значение для сохранения, в данном случае переменную ledState.
EEPROM.write(0, ledState);
Наконец, мы вызываем EEPROM.commit(), чтобы изменения вступили в силу.
EEPROM.commit();
Демонстрация
После загрузки кода на ESP32 нажмите кнопку, чтобы включить и выключить светодиод. ESP32 должен сохранять последнее состояние светодиода после сброса или отключения питания.
Заключение
Подводя итог, в этом уроке вы узнали, как сохранять данные в flash-памяти ESP32 с помощью библиотеки EEPROM. Данные, сохраненные в flash-памяти, остаются там даже после сброса ESP32 или отключения питания.
У нас есть другие статьи об ESP32, которые могут вам понравиться:
Это отрывок из нашего курса: Learn ESP32 with Arduino IDE. Если вам нравится ESP32 и вы хотите узнать больше, мы рекомендуем записаться на курс Learn ESP32 with Arduino IDE.
Источник: ESP32 Flash Memory – Store Permanent Data (Write and Read)