Одна из особенностей Arduino — наличие энергонезависимой памяти EEPROM (Electrically Erasable Programmable Read-Only Memory). В отличие от оперативной памяти (SRAM), данные в EEPROM сохраняются даже после выключения питания. Это удобно, если нужно хранить настройки, калибровки датчиков, счётчики или последние состояния устройства.
Разберёмся, как работать с EEPROM: от простых примеров до аккуратных практик.
1. Что такое EEPROM на Arduino
- У Arduino Uno, Nano и подобных — 1024 байта EEPROM.
- У Mega — 4096 байт.
- У ESP8266/ESP32 EEPROM нет в «чистом виде», но эмулируется во флеш-памяти.
Каждый байт можно записать и потом считать. Однако есть ограничение:
EEPROM выдерживает около 100 000 циклов записи на одну ячейку. Поэтому нельзя записывать в неё данные «каждый тик цикла».
2. Подключение библиотеки
Для работы используем стандартную библиотеку:
#include <EEPROM.h>
3. Чтение и запись байтов
Простейший способ — записывать и читать по одному байту.
#include <EEPROM.h>
void setup() {
Serial.begin(9600);
// Запишем число 42 в ячейку 0
EEPROM.write(0, 42);
// Считаем число из ячейки 0
int value = EEPROM.read(0);
Serial.print("Прочитано из EEPROM: ");
Serial.println(value);
}
void loop() {}
4. Чтение и запись произвольных типов (put и get)
EEPROM умеет работать не только с байтами, но и с целыми структурами или числами.
#include <EEPROM.h>
struct Config {
int threshold;
float factor;
bool enabled;
};
Config settings;
void setup() {
Serial.begin(9600);
// Запись структуры
settings.threshold = 100;
settings.factor = 2.5;
settings.enabled = true;
EEPROM.put(0, settings);
// Чтение структуры
Config loaded;
EEPROM.get(0, loaded);
Serial.println(loaded.threshold);
Serial.println(loaded.factor);
Serial.println(loaded.enabled ? "ON" : "OFF");
}
void loop() {}
EEPROM.put() и EEPROM.get() автоматически знают размер переменной или структуры и сохраняют её целиком.
5. Экономим ресурс памяти
Чтобы продлить срок службы EEPROM:
- Используйте
EEPROM.update()вместоEEPROM.write()— оно перезапишет байт только если значение изменилось. - Не записывайте данные в каждом цикле — добавьте условие или таймер.
- Для счётчиков и логов распределяйте запись по разным ячейкам (wear leveling).
6. Пример: сохранение состояния между перезапусками
Допустим, у нас есть кнопка, которая переключает режим. При перезапуске Arduino устройство должно «помнить», какой режим был выбран.
#include <EEPROM.h>
int mode; // 0 или 1
const int addr = 0;
const int buttonPin = 2;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
// Читаем режим из EEPROM
EEPROM.get(addr, mode);
Serial.print("Режим при старте: ");
Serial.println(mode);
}
void loop() {
if (digitalRead(buttonPin) == LOW) {
delay(200); // антидребезг
mode = !mode; // переключаем
EEPROM.update(addr, mode); // сохраняем в EEPROM
Serial.print("Новый режим: ");
Serial.println(mode);
}
}
Теперь Arduino будет «помнить», в каком режиме она находилась перед выключением.
7. Итог
EEPROM — мощный инструмент для хранения данных между перезапусками. Использовать её нужно разумно, учитывая ограничение по числу записей.
Для критичных проектов можно:
- хранить настройки в структурах;
- применять
EEPROM.update(); - делать распределение записи (чтобы не изнашивалась одна ячейка).