Как читать и записывать EEPROM в ESP8266
Мне нужно знать, как записать целочисленное значение в EEPROM и сохранить значение при включении питания.
char *Red = strstr(myTestUrl, "/R");
if (Red) {
int RedValue = atoi(Red + 2);
analogWrite(12, RedValue);
Serial.println("Red :");
Serial.println(RedValue);
}
Я хочу записать RedValue
в EEPROM. Как это можно сделать?
@Embedded Geek, 👍22
Обсуждение5 ответов
Используйте #include <EEPROM.h>
EEPROM.begin(size); //Размер может быть от 4 до 4096 байт.
EEPROM.write(0, RedValue); // Для сохранения в 0-м месте
EEPROM.commit();
EEPROM.write(pos, val)
записывает один байт (val
) по адресу, заданному pos
. «Int» в ESP8266 занимает 4 байта, так что это немного сложнее, потому что EEPROM работает с байтами, а не с целыми числами.
Вот код для записи одного целого val
в некоторой позиции pos
в EEPROM:
void eeWriteInt(int pos, int val) {
byte* p = (byte*) &val;
EEPROM.write(pos, *p);
EEPROM.write(pos + 1, *(p + 1));
EEPROM.write(pos + 2, *(p + 2));
EEPROM.write(pos + 3, *(p + 3));
EEPROM.commit();
}
и, конечно же, вам нужно перечитать его:
int eeGetInt(int pos) {
int val;
byte* p = (byte*) &val;
*p = EEPROM.read(pos);
*(p + 1) = EEPROM.read(pos + 1);
*(p + 2) = EEPROM.read(pos + 2);
*(p + 3) = EEPROM.read(pos + 3);
return val;
}
В Arduino вы вызываете EEPROM.begin()
, но в ESP8266 вам нужно вызывать EEPROM.begin(n)
, где n
это общее количество байтов, которые вам понадобятся.
И помните, что EEPROM имеет короткий срок службы (по количеству операций записи). Вы должны свести к минимуму количество операций записи!
EEPROM постоянен; вам не нужно ничего делать.
Я немного поискал, и кажется, что EEPROM может обрабатывать гораздо больше циклов записи, чем флэш-память, но у флэш-памяти также есть контроллер, чтобы перестать использовать плохие разделы и продолжать работать с оставшимися рабочими., @Qwertie
ПОДТВЕРЖДЕНО из-за предупреждения о жизненном цикле. 100 тысяч циклов, говорят некоторые., @tony gil
Несмотря на то, что EEPROM.read
и EEPROM.write
являются допустимыми методами, это все равно, что мыть пол зубной щеткой. Вместо этого используйте EEPROM.put
и EEPROM.get
.
Например:
#include <EEPROM.h>
void setup()
{
Serial.begin(9600);
uint addr = 0;
// поддельные данные
struct {
uint val = 0;
char str[20] = "";
} data;
// фиксируем 512 байт флэш-памяти ESP8266 (для эмуляции "EEPROM")
// этот шаг фактически загружает содержимое (512 байт) флэш-памяти в
// кеш-массив размером 512 байт в ОЗУ
EEPROM.begin(512);
// чтение байтов (т.е. sizeof(data) из "EEPROM"),
// на самом деле читает из кеша массива байтов
// преобразовать байты в структуру, называемую данными
EEPROM.get(addr,data);
Serial.println("Old values are: "+String(data.val)+","+String(data.str));
// возиться с данными, "прочитанными" из EEPROM
data.val += 5;
if ( strcmp(data.str,"hello") == 0 )
strncpy(data.str, "jerry",20);
else
strncpy(data.str, "hello",20);
// заменяем значения в кеше байтового массива измененными данными
// никаких изменений во флеш-памяти, все в локальном кеше байтового массива
EEPROM.put(addr,data);
// на самом деле записываем содержимое кеша байтового массива в
// аппаратная флешка. запись во флэш-память происходит тогда и только тогда, когда один или несколько байт
// в кеше байт-массива изменено, но если да, то ВСЕ 512 байт
// записывается во флеш
EEPROM.commit();
// очистить структуру данных
data.val = 0;
strncpy(data.str,"",20);
// перезагружаем данные для EEPROM, см. изменение
// OOPS, на самом деле не чтение флэш-памяти, а чтение кэша байтового массива (в ОЗУ),
// выключите и снова включите ESP8266, чтобы действительно увидеть обновление flash/"EEPROM"
EEPROM.get(addr,data);
Serial.println("New values are: "+String(data.val)+","+String(data.str));
}
void loop()
{
delay(1000);
}
ОБНОВЛЕНИЕ: если вы хотите понять, как «EEPROM» эмулируется в ESP8266, вы можете сослаться на https://github.com/esp8266/Arduino/tree/master/libraries/EEPROM, в частности, EEPROM.h
.
Кроме того, EEPROM.end
не нужен, он просто очищает локальный кэш байтового массива флэш-памяти/EEPROM из ОЗУ. Он выполняет другую функцию.
вы спасли мой день, я искал решение более пяти часов, и вы его дали!, @nonozor
Фактической документации Arduino здесь действительно не хватает, и исходники тоже не очень помогают. EEPROM.end() все еще нужен? Зачем нужно begin(512)? Кроме того, комбинация get()/put() или использование update() поможет предотвратить износ EEPROM. Возможно, вы могли бы обновить ответ., @Bim
Я скопировал/вставил этот точный код для NodeMCU v3, и он не извлекает записанное значение после выключения и включения питания (я закомментировал «часть записи для второго запуска»)., @WhiskerBiscuit
@WhiskerBiscuit, вы видите ЛЮБОЙ вывод в последовательной консоли? Вы уверены, что скорость передачи установлена правильно? у меня нет v3, только v0.9, так что не могу помочь, если это проблема прямой совместимости., @codechimp
из ссылки «EEPROM.write не записывает во флэш-память немедленно, вместо этого вы должны вызывать EEPROM.commit() всякий раз, когда хотите сохранить изменения во флэш-памяти. EEPROM.end() также зафиксирует и освободит копию содержимого EEPROM в ОЗУ. ", @Juraj
Что я узнал на практике, так это то, что EEPROM.commit() абсолютно необходим, по крайней мере, на esp8266, чтобы данные EEPROM сохранились после перезагрузки., @Ameer
В своем коде на ESP8266 я использую две отдельные функции: одну с EEPROM.put()
, другую с EEPROM.get()
.
У меня был EEPROM.begin(sizeof...);
только в функции EEPROM.put()
и работал put
.
Но мне потребовалось довольно много времени, пока я не узнал, что его нужно использовать и перед EEPROM.get()
.
Метод с использованием количества букв.
#include <ESP8266WiFi.h>
const char* SSID = "R360"; //МАКС. 32
const char* PASSWORD = "HFDYUK64323246"; //МАКС. 32
#include <EEPROM.h>
void setup() {
Serial.begin(9600);
EEPROM_ESP8266_GRABAR(SSID, 0); //Primero de 0 al 32, del 32 al 64 и т. д.
EEPROM_ESP8266_GRABAR(PASSWORD, 32); //СОХРАНЯТЬ
Serial.println();
Serial.println(EEPROM_ESP8266_LEER(0, 32));//Primero от 0 до 32, del 32 до 64 и т. д.
Serial.println(EEPROM_ESP8266_LEER(32, 64));
WiFi.begin(EEPROM_ESP8266_LEER(0,32).c_str(), EEPROM_ESP8266_LEER(32,64).c_str());
}
//
void loop() {}
//
void EEPROM_ESP8266_GRABAR(String buffer, int N) {
EEPROM.begin(512); delay(10);
for (int L = 0; L < 32; ++L) {
EEPROM.write(N + L, buffer[L]);
}
EEPROM.commit();
}
//
String EEPROM_ESP8266_LEER(int min, int max) {
EEPROM.begin(512); delay(10); String buffer;
for (int L = min; L < max; ++L)
if (isAlphaNumeric(EEPROM.read(L)))
buffer += char(EEPROM.read(L));
return buffer;
}
- Значение неинициализированной EEPROM в ESP8266
- Wemos D1 EEProm put/get не получает правильное значение
- Как исправить: Invalid conversion from 'const char*' to 'char*' [-fpermissive]
- ошибка: espcomm_upload_mem failed при загрузке скетча
- Как определить размер Flash?
- Несколько клиентских серверов через Wi-Fi
- Передача функции-члена класса в качестве аргумента
- В ESP-12E NodeMCU, какой выход PIN A0?
Посмотрите примеры скетчей EEPROM, которые устанавливаются при добавлении поддержки ESP8266 в arduino ide., @Jaromanda X
возник вопрос, есть ли какие-либо зависимости от флэш-памяти с использованием EEPROM. Могу ли я прошить с 1 МБ (без SPIFFS) и иметь доступ к EEPROM? Спасибо Т, @riker1