Терморегулятор инкубатора я собрал за вечер: DHT22 на пине 2, реле на нагреватель, целевая температура на экране. Первую неделю всё шло отлично — тридцать восемь и ноль с точностью до десятой. Потом ночью в сарае сверкнула гроза, свет мигнул, и плата стартовала заново. Целевую температуру она забыла и выставила заводской дефолт. К обеду инкубатор грел до двадцати восьми, а яйца лежали в холоде шесть часов, пока я не заглянул. Плату я тогда винил зря: она не сломалась — ей просто негде было хранить настройку.
Переменная с целевой температурой жила в оперативной памяти. Оперативная память работает, только пока на неё подано питание: свет мигнул — содержимое ушло, и скетч стартовал с нулями и дефолтами. Это не дефект конкретной платы, а устройство любого компьютера, от ардуинки до ноутбука: выключил питание — оперативка пуста.
Но внутри того же чипа ATmega328P есть отдельный отсек, которому питание не нужно: EEPROM — энергонезависимая память объёмом 1024 байта. Она помнит данные годами при полностью вынутом проводе, а скетч может читать и писать её двумя-тремя командами. Правда, у отсека свои правила: запись медленная, ресурс каждой ячейки ограничен, а пустая ячейка читается неожиданным числом 255.
В этом уроке — карта всех трёх памятей платы, физика того, почему EEPROM живёт без розетки, и честные числа: сколько лет хранится записанное и на сколько циклов записи хватает ячейки. Симулятор поддерживает EEPROM.read, EEPROM.write, EEPROM.update и EEPROM.length(), причём значения переживают перезапуск — так что эксперимент «выключил — включил — всё на месте» можно проделать прямо на этой странице.
Три памяти на одной плате
В Arduino Uno три вида памяти, и путать их дорого. Flash, 32 КБ, хранит сам скетч: он остаётся в чипе десятилетиями, но писать в него из работающей программы не принято — так можно повредить загрузчик и окирпичить плату. SRAM, 2 КБ, — рабочая память: переменные, стек, буферы Serial. Быстрая и удобная, но она существует, только пока есть питание: пропал вольтаж — и содержимое исчезло за мгновение.
EEPROM, 1 КБ, — третий мир: 1024 байта внутри того же чипа, доступные программе и не зависящие от питания. Один адрес — один байт, числа от 0 до 255; адреса идут от 0 до 1023. Больше байта в ячейку не влезет физически, а числа крупнее приходится раскладывать по соседним адресам — приём мы разобрали в уроке про счётчик включений, а типы и их потолки раскладывали ещё в уроке про переменные и типы.
Размер зависит от платы, и это стоит знать до переноса проекта: у Uno и Nano — 1024 байта, у Mega — 4096, у Leonardo — 1024. Чтобы код не приходилось править руками при переезде, спрашивайте у платы: EEPROM.length() вернёт точное число ячеек конкретного чипа.
Практическая карта такая: во Flash лежит программа, в SRAM живут переменные текущей работы, в EEPROM — то, что должно пережить розетку: настройки пользователя, калибровки, счётчики. Отсюда и правило выбора: настройку — в EEPROM, измерение текущей секунды — в SRAM, а если измерений слишком много для 1024 байтов — им место на SD-карте, о чём есть отдельный урок про логирование.
| Память | Объём на Uno | Без питания | Запись из скетча | Что там живёт |
|---|---|---|---|---|
| Flash | 32 КБ | Годы | Практически недоступна | Скетч, константы |
| SRAM | 2 КБ | Теряется мгновенно | Свободная, мгновенная | Переменные, стек, буферы |
| EEPROM | 1024 байта | Около 100 лет при 25 °C | Да, ~3,3 мс, изнашивает ячейку | Настройки, калибровки, счётчики |
Почему EEPROM помнит без питания, а SRAM — нет, объясняется физикой ячейки. В EEPROM каждый бит — транзистор с плавающим затвором: крошечный карман изолятора, в который при записи перекачивается заряд. Вокруг кармана — диэлектрик, и заряд заперт в нём без всякой подпитки: столько, сколько нужно, хоть сотню лет. SRAM устроена иначе: бит там держит пара транзисторов, которая обязана питаться каждую микросекунду, — питание кончилось, пара распалась, ноль.
Обратная сторона запертого заряда — цена доставки. Чтобы записать байт, заряд приходится прокачивать сквозь тонкий оксидный слой, и каждый проход понемногу этот слой старит. Производитель гарантирует около 100000 циклов записи на ячейку. Чтение заряда не трогает вовсе: читайте хоть миллион раз в секунду — ячейке всё равно. Изнашивает только запись.
Два числа из даташита Atmel стоит выучить и не путать. Удержание данных: около 100 лет при 25 °C, около 20 лет при 85 °C — столько хранится однажды записанное. Ресурс перезаписи: гарантированные 100000 циклов на ячейку. Заметьте: это гарантия производителя, то есть нижняя граница. Реальные ячейки в любительских тестах переживают заметно больше, но проектировать надо по паспорту: экономия на одном байте не оправдывает скетч, который однажды молча потеряет настройки.
Адреса 0–1023 и что туда класть
Железный список «да» для EEPROM: настройки, которые меняет человек — целевая температура, яркость, громкость; калибровки — сдвиг нуля датчика, коэффициент весов; счётчики тихих событий — включения платы, циклы фильтра; и контрольный байт, по которому скетч понимает, что память уже настроена. Всё это меняется редко, и ячейки при такой жизни живут годами.
Список «нет» такой же железный. Потоковые логи и показания раз в секунду — их место на SD-карте: EEPROM такого темпа не выдержит и объёмом не вытянет. Большие массивы — 1024 байта это примерно полторы страницы текста, а не архив. Пароли — EEPROM читается программатором за минуту, это не сейф. И всё, что требует записи чаще раза в минуту.
В этом разделе мы уже сохраняли яркость ночника и собирали счётчик включений — теперь понятно, почему оба проекта вообще работают: яркость и счётчик лежали в том самом отсеке на 1024 байта. Ниже — минимальный скетч, который знакомится с памятью платы: спрашивает её размер, проверяет контрольный байт и печатает содержимое первых ячеек.
#include <EEPROM.h> const int addrMagic = 100; // контрольная ячейка void setup() { Serial.begin(9600); Serial.print("dlina="); Serial.println(EEPROM.length()); int magic = EEPROM.read(addrMagic); if (magic != 170) { EEPROM.write(addrMagic, 170); Serial.println("pervyj_zapus: pishu_kontrolnyj_bajt"); } for (int i = 0; i < 5; i++) { Serial.print("cell"); Serial.print(i); Serial.print("="); Serial.println(EEPROM.read(i)); } Serial.print("magic="); Serial.println(EEPROM.read(addrMagic));} void loop() { delay(500);}EEPROM.length() на Uno вернёт 1024, на Mega тот же скетч напечатает 4096 — код подстроился сам. Строка dlina=1024 — та самая пара имя=значение из первого урока про монитор порта, на которой построена вся читаемость Serial в этом самоучителе. EEPROM.read(100) до первой настройки вернёт 255, и ветвление из урока про if/else это ловит: пишет контрольное число 170. Цикл for печатает ячейки 0–4: на свежей плате все покажут 255 — пустая EEPROM состоит из одних единичных битов.
Число 170 выбрано не для красоты: в двоичном виде это 10101010, чередование нулей и единиц видно даже в дампе памяти. После записи при перезапуске строка о первом запуске не появится: контрольный байт найден, память инициализирована. На этом приёме держится вся работа с настройками: по magic-байту скетч отличает новую плату от уже сконфигурированной.
Обратите внимание, чего в скетче нет: записи в loop(). Память тронули один раз — при старте, по необходимости. Это не перестраховка, а прямое следствие ограниченного ресурса, к которому мы сейчас и перейдём.
Итоговые две цифры урока и как ими пользоваться. Удержание: записанное переживёт розетку примерно на 100 лет при комнатной температуре — заботиться о выживании не нужно, оно и так есть. Ресурс: каждая ячейка выдерживает гарантированные 100000 записей, и тратит их только запись — значит, весь вопрос бережливости сводится к тому, как часто вы пишете.
Отдельный нюанс для честных экспериментов на реальной плате: нажатие Reset выживание памяти не проверяет — скетч просто перезапускается, питание не пропадало. Выдёргивайте питание целиком: USB, затем снова. В симуляторе та же процедура выглядит как Стоп и повторный запуск — EEPROM между запусками сохраняется.
Про плату в сарае при минус тридцати тоже спокойно: холод удержанию не вредит, из даташитных условий страшна жара — уже при 85 °C срок падает с сотни лет до двадцати. Для бытовой электроники это академично, но знать границу полезно: автомобильный салон летом ближе к верхней цифре, чем кажется.
Проверяем вживую
- Перенесите контрольную ячейку с адреса 100 на 200 и запустите дважды: в первый запуск magic ещё исходный (в симуляторе — 0, на свежей плате — 255) и есть строка о записи, во второй — magic=170 без строки. Контрольный байт работает.
- Добавьте EEPROM.write(3, 700) и прочитайте ячейку 3: вернётся 44 — байт хранит остаток от деления на 256. Подумайте, как уложить 700 честно.
- Напечатайте EEPROM.length() и посчитайте: сколько настроек по одному байту помещается в память вашей платы, если тратить по одному адресу на настройку.
- Запишите в ячейку 10 число 128, нажмите Стоп и запустите снова: байт вернулся. На реальной плате повторите то же через полное отключение питания, а не через Reset.
- 1. Сколько EEPROM у Arduino Mega?
- 2. Что живёт в SRAM и что с ней происходит при выключении питания?
- 3. Сколько лет записанные данные держатся в EEPROM при 25 °C по даташиту?
- 4. Тратится ли ресурс ячейки EEPROM при чтении?
- 5. Что вернёт чтение ячейки на совершенно новой, никогда не писаной EEPROM?
- На Uno три памяти: Flash 32 КБ (скетч), SRAM 2 КБ (переменные, теряется при выключении), EEPROM 1024 байта (настройки, живёт без питания)
- Адреса EEPROM — 0–1023, ячейка хранит байт 0–255; размер любой платы возвращает EEPROM.length()
- Удержание: около 100 лет при 25 °C, около 20 при 85 °C; ресурс: гарантированные ~100000 записей на ячейку
- Чтение ресурса не тратит — изнашивает только запись
- Пустая ячейка читается как 255; контрольный байт 170 (10101010) отличает неинициализированную память от случайных 255
- В EEPROM живут настройки, калибровки и счётчики; потоки измерений — на SD-карте, секреты — вообще не здесь
Частые вопросы по теме урока
- Сколько EEPROM у Arduino Mega?
- У Mega — 4096 байт, у Uno, Nano и Leonardo — 1024. Точный размер конкретной платы вернёт EEPROM.length(). 4096 байт
- Что живёт в SRAM и что с ней происходит при выключении питания?
- SRAM — оперативная память: переменные, стек, буферы. Без питания содержимое пропадает. Скетч лежит во Flash, настройки — в EEPROM. Переменные и стек, содержимое теряется
- Сколько лет записанные данные держатся в EEPROM при 25 °C по даташиту?
- Удержание данных — около 100 лет при 25 °C и около 20 лет при 85 °C. Это про хранение без питания, а не про ресурс перезаписи. Около 100 лет
- Тратится ли ресурс ячейки EEPROM при чтении?
- Ресурс тратит физический процесс записи заряда. Чтение заряд не трогает — читать можно хоть миллион раз в секунду. Нет, изнашивает только запись
- Что вернёт чтение ячейки на совершенно новой, никогда не писаной EEPROM?
- Пустые ячейки состоят из единичных битов, то есть 255. По этому признаку ловят первый запуск, а подтверждают контрольным байтом. 255