Для электронщиков и радиолюбителей

Чтение и запись в EEPROM: сохранение настроек между перезапусками

Чтение и запись в EEPROM: сохранение настроек между перезапусками

Одна из особенностей 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();
  • делать распределение записи (чтобы не изнашивалась одна ячейка).