Библиотека EEPROM
Память, которая переживает выключение питания: настройки, счётчики, калибровки. На 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() после записи.