ELECTRONICS

Библиотека EEPROM

встроена в средуArduino, встроенаверсия ядро AVR 1.8.8

Память, которая переживает выключение питания: настройки, счётчики, калибровки. На UNO — 1024 байта.

Обычные переменные обнуляются при каждом включении. EEPROM — отдельная память внутри контроллера, где байты остаются навсегда: у UNO и Nano её килобайт, у Mega четыре. Сюда кладут то, что должно пережить перезагрузку: выбранный режим, счётчик включений, откалиброванный ноль датчика.

Ресурс — около ста тысяч записей на ячейку. Это много для настроек и ничтожно мало для логгера, пишущего каждую секунду: ячейка умрёт за сутки. Запись в цикле loop() без условия — классическая ошибка.

Установка и подключение

Ставить ничего не нужно: библиотека входит в среду Arduino и доступна сразу после установки. Достаточно строки подключения в начале скетча.

#include <EEPROM.h>

Создание объекта — обычно до setup():

// объект EEPROM создан библиотекой, begin() не нужен
EEPROM.write(0, 42);          // байт в ячейку 0
byte v = EEPROM.read(0);

Методы

Только то, что нужно в обычном скетче. Сигнатуры сверены с версией ядро AVR 1.8.8.

read(int address)
Прочитать байт по адресу 0…length()−1.
write(int address, uint8_t value)
Записать байт. Занимает 3,3 мс и тратит ресурс ячейки.
update(int address, uint8_t value)
Записать, только если значение отличается. Предпочтительнее write(): бережёт ресурс.
put(int address, T value)
Записать любой тип целиком — int, float, структуру. Внутри использует update().
get(int address, T& value)
Прочитать любой тип в переменную. Адрес — тот же, что при put().
length()
Размер памяти в байтах: 1024 на UNO, 4096 на Mega.
EEPROM[address]
Доступ как к массиву: EEPROM[5] = 10; работает через update().

Пример

#include <EEPROM.h>

struct Settings {
  int  brightness;
  float offset;
  byte mode;
};

const int ADDR = 0;

void setup() {
  Serial.begin(9600);
  Settings s;
  EEPROM.get(ADDR, s);                     // читаем, что сохранили в прошлый раз
  if (s.mode > 3) {                        // мусор в чистой памяти: 255 везде
    s = { 128, 0.0, 0 };                   // значения по умолчанию
  }
  s.mode = (s.mode + 1) % 4;               // при каждом включении — следующий режим
  EEPROM.put(ADDR, s);                     // put пишет только изменившиеся байты
  Serial.print("Режим: ");
  Serial.println(s.mode);
}

void loop() {}

В свежей памяти все байты равны 255. Всегда проверяйте прочитанное на правдоподобие, иначе первое включение даст мусор.

На чём попадаются

EEPROM «сломалась» через день

Запись в loop() без условия: сотня тысяч циклов набирается за минуты. Пишите по событию (кнопка, изменение) и через update().

Прочитали не то, что писали

Разные адреса в put() и get(), или структура изменилась между прошивками. Держите адреса константами и добавьте в структуру номер версии.

Float не сохраняется через write()

write() пишет один байт. Для чисел длиннее байта — put() и get().

На ESP32 не работает

Там EEPROM эмулируется во флеш-памяти: нужен EEPROM.begin(size) в setup() и EEPROM.commit() после записи.

Что дальше