EEPROM (Electrically Erasable Programmable Read-Only Memory) – это небольшая, но важная часть микроконтроллера Arduino, которая играет ключевую роль в сохранении данных после отключения питания. Именно благодаря EEPROM мы можем хранить информацию на длительный срок, сохраняя настройки, параметры и другие важные данные. В этой статье мы погрузимся в мир EEPROM, узнаем, как использовать ее на платформе Arduino и какие возможности она предоставляет для создания надежных и гибких проектов.
EEPROM представляет собой тип памяти, которая сохраняет данные, даже когда устройство отключено от питания. Она отличается от оперативной памяти (RAM), которая теряет данные при отключении энергии. EEPROM на платформе Arduino используется для долговременного хранения информации, такой как настройки, параметры и другие данные, которые должны сохраняться между сеансами работы.
Количество EEPROM на различных контроллерах Arduino может варьироваться. Вот примерные размеры EEPROM для пяти популярных плат:
- Arduino Uno: 1024 байта EEPROM.
- Arduino Nano: 1024 байта EEPROM.
- Arduino Mega 2560: 4096 байт EEPROM.
- Arduino Leonardo: 1024 байта EEPROM.
Принцип работы EEPROM основан на возможности программного обеспечения контроллера записывать и считывать данные из памяти. Для записи данных в EEPROM используется специальный процесс, который электрически стирает и программирует ячейки памяти. В результате этого процесса данные сохраняются даже при выключении питания. Устройство EEPROM состоит из множества ячеек памяти, каждая из которых может хранить один байт информации. Обратите внимание, что если данным требуется больше 1 байта (например, число больше 255), то они разбиваются на несколько ячеек. Это важно учитывать при работе с EEPROM.
Работа с EEPROM в Arduino IDE
Для работы с EEPROM в Arduino IDE предусмотрена стандартная библиотека EEPROM.h. Она предоставляет удобные функции для чтения, записи и управления данными во встроенной EEPROM микроконтроллера.
Основные функции библиотеки EEPROM.h включают:
EEPROM.read(address)
: Чтение одного байта данных из указанного адреса EEPROM.EEPROM.write(address, value)
: Запись одного байта данных по указанному адресу EEPROM.EEPROM.update(address, value)
: Работает по аналогии с функциейwrite()
, но запись происходить только в том случае, если новые данные отличаются от уже имеющихся данных по указанному адресу EEPROM.EEPROM.put(address, value)
: Запись любого типа данных (в том числе структур) по указанному адресу EEPROM. При этом адрес указывает на начало данных в памяти, а количество байт, необходимое для хранения данных, вычисляется автоматически.EEPROM.get(address, value)
: Чтение любого типа данных по указанному адресу EEPROM.EEPROM[address]
: В дополнение к основным функциям, библиотека позволяет обращаться к EEPROM как к обычному массиву данных. Это означает, что можно работать с EEPROM напрямую, аналогично обычному массиву: записывать данные в ячейки памяти по конкретным адресам и читать данные из них. Такой подход позволяет управлять EEPROM более гибко и эффективно, обеспечивая возможность прямого доступа к отдельным ячейкам памяти и оперировать данными как с элементами массива.
Пример кода в Arduino IDE
Рассмотрим использование EEPROM на примере сохранения и загрузки настроек Arduino. Мы создадим структуру данных, которая будет содержать в себе настройки устройства Arduino, например, параметры для подключения к Wi-F.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
#include <EEPROM.h> #define DATA_FLAG 0xAA // Маркер, указывающий наличие сохраненных данных в EEPROM // Структура для хранения настроек struct Settings { char ssid[30]; // Имя Wi-Fi сети char password[30]; // Пароль для подключения }; // Функция сохранения настроек в EEPROM void saveSettings(const Settings &settings) { EEPROM.write(0x0, DATA_FLAG); // Записываем маркер, указывающий наличие данных EEPROM.put(0x1, settings); // Сохраняем данные в EEPROM, начиная с адреса 0x1 } // Функция загрузки дефолтных настроек void loadDefaults(Settings &settings) { // Устанавливаем дефолтные значения strcpy(settings.ssid, "DefaultSSID"); strcpy(settings.password, "DefaultPassword"); // Сохраняем дефолтные значения в EEPROM saveSettings(settings); } // Функция загрузки настроек из EEPROM void loadSettings(Settings &settings) { if (EEPROM.read(0x0) == DATA_FLAG) { // Проверяем наличие маркера EEPROM.get(0x1, settings); // Если маркер есть, загружаем настройки из EEPROM } else { loadDefaults(settings); // Если маркера нет, загружаем дефолтные настройки } } // Создаем переменную для хранения настроек Settings deviceSettings; void setup() { // Загружаем настройки из EEPROM или устанавливаем дефолтные loadSettings(deviceSettings); // Выводим настройки в монитор порта Serial.begin(9600); Serial.print("Загружено имя сети: "); Serial.println(deviceSettings.ssid); Serial.print("Загружен пароль: "); Serial.println(deviceSettings.password); Serial.println(); } void loop() { // Проверяем наличие данных в Serial порте if (Serial.available() > 0) { String input = Serial.readStringUntil('\n'); // Считываем строку до символа новой строки // Проверяем, содержит ли строка "set_password=" if (input.startsWith("set_password=")) { String newPassword = input.substring(13); // Извлекаем новый пароль из строки strcpy(deviceSettings.password, newPassword.c_str()); // Записываем новый пароль saveSettings(deviceSettings); // Сохраняем измененные настройки в EEPROM Serial.print("Пароль изменён, новый пароль: "); Serial.println(deviceSettings.password); } // Проверяем, содержит ли строка "set_ssid=" if (input.startsWith("set_ssid=")) { String newSSID = input.substring(9); // Извлекаем новое имя сети из строки strcpy(deviceSettings.ssid, newSSID.c_str()); // Записываем новое имя сети saveSettings(deviceSettings); // Сохраняем измененные настройки в EEPROM Serial.print("Имя сети изменено, новое имя сети: "); Serial.println(deviceSettings.ssid); } // Выводим текущий пароль в монитор порта при запросе "password" if (input.equals("password")) { Serial.print("Текущий пароль: "); Serial.println(deviceSettings.password); } // Выводим текущее имя сети в монитор порта при запросе "ssid" if (input.equals("ssid")) { Serial.print("Текущее имя сети: "); Serial.println(deviceSettings.ssid); } } delay(100); } |
Этот код создает структуру Settings
для хранения настроек Wi-Fi и пароля. Функции saveSettings
и loadSettings
используют EEPROM для сохранения и загрузки настроек. Маркер DATA_FLAG
(0xAA) указывает наличие сохраненных данных в EEPROM. Если данные уже сохранены, функция loadSettings
загружает их, иначе используются дефолтные настройки, которые сохраняются в EEPROM.
В функции loop()
проверяется, есть ли данные в Serial порте. Если получает строки вида “set_password=<новый пароль>” или “set_ssid=<новое имя сети>”, он изменяет соответствующие настройки в EEPROM и сохраняет их. При получении строк “password” или “ssid” в монитор порта выводится текущий пароль или имя сети соответственно.