Как читать и записывать 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. Как это можно сделать?

, 👍22

Обсуждение

Посмотрите примеры скетчей EEPROM, которые устанавливаются при добавлении поддержки ESP8266 в arduino ide., @Jaromanda X

возник вопрос, есть ли какие-либо зависимости от флэш-памяти с использованием EEPROM. Могу ли я прошить с 1 МБ (без SPIFFS) и иметь доступ к EEPROM? Спасибо Т, @riker1


5 ответов


0

Используйте #include <EEPROM.h>

EEPROM.begin(size); //Размер может быть от 4 до 4096 байт.
EEPROM.write(0, RedValue);   // Для сохранения в 0-м месте
EEPROM.commit();
,

10

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


36

Несмотря на то, что 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


0

В своем коде на ESP8266 я использую две отдельные функции: одну с EEPROM.put(), другую с EEPROM.get().

У меня был EEPROM.begin(sizeof...); только в функции EEPROM.put() и работал put. Но мне потребовалось довольно много времени, пока я не узнал, что его нужно использовать и перед EEPROM.get().

,

2

Метод с использованием количества букв.

#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;
}
,