Arduino EEPROM – запоминаем последнее состояние светодиода

В этом руководстве объясняется, что такое EEPROM в Arduino и для чего он нужен. Мы также покажем, как записывать данные в EEPROM и считывать их, а также построим проект-пример, чтобы закрепить изученные концепции на практике.

Arduino EEPROM -- запоминаем последнее состояние светодиода

У нас есть аналогичное руководство для ESP32: ESP32 Flash Memory – хранение постоянных данных (запись и чтение)

Введение

Когда вы определяете и используете переменную, данные, сгенерированные в скетче, существуют только до тех пор, пока Arduino включён. Если вы сбросите или выключите Arduino, сохранённые данные исчезнут.

Если вы хотите сохранить данные для дальнейшего использования, вам нужно использовать Arduino EEPROM. Он сохраняет данные переменных даже при сбросе Arduino или отключении питания.

Что такое EEPROM?

Микроконтроллер на плате Arduino (ATMEGA328 в случае Arduino UNO, показан на рисунке ниже) имеет EEPROM (электрически стираемое программируемое постоянное запоминающее устройство). Это небольшая область памяти, в которой можно хранить байтовые переменные.

Переменные, сохранённые в EEPROM, остаются там даже при сбросе или отключении питания Arduino. Проще говоря, EEPROM – это постоянное хранилище, аналогичное жёсткому диску в компьютерах.

Микроконтроллер ATmega328

EEPROM можно считывать, стирать и перезаписывать электронным способом. В Arduino вы можете легко читать и записывать данные в EEPROM с помощью библиотеки EEPROM.

Сколько байт можно хранить?

Каждая позиция EEPROM может сохранить один байт, что означает, что вы можете хранить только 8-битные числа, включая целочисленные значения от 0 до 255.

Количество байтов, которые можно хранить в EEPROM, зависит от микроконтроллера на плате Arduino. Посмотрите таблицу ниже:

Микроконтроллер

EEPROM

ATmega328 (Arduino Uno, Nano, Mini)

1024 байт

ATmega168 (Arduino Nano)

512 байт

ATmega2560 (Arduino Mega)

4096 байт

Однако, если вам нужно хранить больше данных, вы можете использовать внешнюю микросхему EEPROM.

Ограниченный ресурс EEPROM

EEPROM имеет ограниченный ресурс. В Arduino EEPROM рассчитан на 100 000 циклов записи/стирания для каждой позиции. Однако количество чтений не ограничено. Это означает, что вы можете считывать данные из EEPROM сколько угодно раз, не сокращая его срок службы.

Применение в проектах Arduino – запоминание последнего состояния

EEPROM полезен в проектах Arduino, которым необходимо сохранять данные даже после сброса Arduino или при отключении питания.

Он особенно полезен для запоминания последнего состояния переменной или для подсчёта количества включений устройства.

Например, представьте следующий сценарий:

  • Вы управляете лампой с помощью Arduino, и лампа включена;

  • Arduino внезапно теряет питание;

  • Когда питание восстанавливается, лампа остаётся выключенной – она не сохраняет своё последнее состояние.

Вы не хотите, чтобы это происходило. Вы хотите, чтобы Arduino запоминал, что происходило до потери питания, и возвращался к последнему состоянию.

Состояние светодиода без EEPROM

Чтобы решить эту проблему, вы можете сохранить состояние лампы в EEPROM и добавить в скетч условие для начальной проверки: соответствует ли состояние лампы состоянию, ранее сохранённому в EEPROM.

Мы проиллюстрируем это примером далее в этой статье в разделе Пример: Arduino EEPROM – запоминание сохранённого состояния светодиода.

Чтение и запись

Вы можете легко читать и записывать данные в EEPROM с помощью библиотеки EEPROM.

Для подключения библиотеки EEPROM:

#include <EEPROM.h>

Запись (Write)

Для записи данных в EEPROM используется функция EEPROM.write(), которая принимает два аргумента. Первый – это адрес (позиция) в EEPROM, куда вы хотите сохранить данные, а второй – значение, которое мы хотим сохранить:

EEPROM.write(address, value);

Например, чтобы записать значение 9 по адресу 0, вы напишете:

EEPROM.write(0, 9);

Чтение (Read)

Для чтения байта из EEPROM используется функция EEPROM.read(). Эта функция принимает адрес байта в качестве аргумента.

EEPROM.read(address);

Например, чтобы прочитать байт, ранее сохранённый по адресу 0:

EEPROM.read(0);

Это вернёт 9 – значение, сохранённое в этой позиции.

Обновление значения (Update)

Функция EEPROM.update() особенно полезна. Она записывает данные в EEPROM только в том случае, если записываемое значение отличается от уже сохранённого.

Поскольку EEPROM имеет ограниченный срок службы из-за ограниченного количества циклов записи/стирания, использование функции EEPROM.update() вместо EEPROM.write() позволяет сэкономить циклы.

Функция EEPROM.update() используется следующим образом:

EEPROM.update(address, value);

На данный момент у нас сохранено значение 9 по адресу 0. Поэтому, если мы вызовем:

EEPROM.update(0, 9);

Запись в EEPROM не произойдёт повторно, так как текущее сохранённое значение совпадает с тем, которое мы хотим записать.

Пример: Arduino EEPROM – запоминание сохранённого состояния светодиода

В этом примере мы покажем, как заставить Arduino запоминать сохранённое состояние светодиода, даже когда мы сбрасываем Arduino или отключаем питание.

На следующем рисунке показано, что мы будем демонстрировать:

Состояние светодиода с EEPROM

Необходимые компоненты

Вот список компонентов, необходимых для этого проекта (нажмите на ссылки ниже, чтобы найти лучшую цену на Maker Advisor):

Вы можете использовать ссылки выше или перейти напрямую на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!

Схема подключения

Вот схема подключения для этого проекта. Это просто кнопка, которая будет включать и выключать светодиод.

Схема подключения EEPROM с кнопкой и светодиодом

Код

Скопируйте следующий код в Arduino IDE и загрузите его на вашу плату Arduino. Убедитесь, что выбрана правильная плата и COM-порт.

/*
 * Rui Santos
 * Complete Project Details https://randomnerdtutorials.com
 */

#include <EEPROM.h>

const int buttonPin = 8;    // пин кнопки
const int ledPin = 4;       // пин светодиода

int ledState;                // переменная для хранения состояния светодиода
int buttonState;             // текущее состояние кнопки
int lastButtonState = LOW;   // предыдущее состояние кнопки

// следующие переменные имеют тип long, потому что время, измеряемое
// в миллисекундах, быстро превысит размер int
long lastDebounceTime = 0;  // последнее время переключения выхода
long debounceDelay = 50;    // время антидребезга; увеличьте, если выход мерцает

void setup() {
  // настройка входа и выхода
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

  // установка начального состояния светодиода
  digitalWrite(ledPin, ledState);

  // инициализация Serial Monitor
  Serial.begin (9600);

  // проверка сохранённого состояния светодиода в EEPROM
  // с помощью функции, определённой в конце кода
  checkLedState();
}

void loop() {
  // считываем состояние кнопки в локальную переменную
  int reading = digitalRead(buttonPin);

  if(reading != lastButtonState) {
    // сброс таймера антидребезга
    lastDebounceTime = millis();
  }

  if((millis() - lastDebounceTime) > debounceDelay) {
    // какое бы значение ни было считано, оно держится дольше,
    // чем задержка антидребезга, поэтому принимаем его
    // как текущее состояние:

    // если состояние кнопки изменилось:
    if(reading != buttonState) {
      buttonState = reading;

      // переключаем светодиод только если новое состояние кнопки HIGH
      if(buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }

  // устанавливаем состояние светодиода
  digitalWrite(ledPin, ledState);
  // сохраняем текущее состояние светодиода в EEPROM
  EEPROM.update(0, ledState);
  // сохраняем считанное значение. В следующем проходе loop()
  // оно станет lastButtonState
  lastButtonState = reading;
}

// Выводит и обновляет состояние светодиода
// при перезапуске или включении Arduino
void checkLedState() {
   Serial.println("LED status after restart: ");
   ledState = EEPROM.read(0);
   if(ledState == 1) {
    Serial.println ("ON");
    digitalWrite(ledPin, HIGH);
   }
   if(ledState == 0) {
    Serial.println ("OFF");
    digitalWrite(ledPin, LOW);
   }
}

Посмотреть исходный код

Это код с антидребезгом, который меняет состояние светодиода при каждом нажатии кнопки. Но в этом коде есть кое-что особенное – он запоминает сохранённое состояние светодиода, даже после сброса или отключения питания Arduino.

По сути, мы сохраняем текущее состояние светодиода в переменной ledState и записываем его в EEPROM следующей строкой:

EEPROM.update(0,ledState);

В начале кода, в функции setup(), мы проверяем значение ledState, сохранённое в EEPROM, и включаем или выключаем светодиод в соответствии с этим состоянием при перезапуске программы. Мы делаем это с помощью функции, которую создали в конце кода, – checkLedState():

void checkLedState() {
    Serial.println("LED status after restart: ");
    ledState = EEPROM.read(0);
     if (ledState == 1) {
       Serial.println ("ON");
       digitalWrite(ledPin, HIGH);
     }
     if (ledState == 0) {
       Serial.println ("OFF");
       digitalWrite(ledPin, LOW);
     }
}

Демонстрация

Для демонстрации этого примера посмотрите видео ниже.

Заключение

В этой статье вы узнали о EEPROM в Arduino и о том, для чего он нужен. Вы создали скетч для Arduino, который запоминает последнее состояние светодиода даже после сброса Arduino.

Это лишь простой пример, чтобы вы поняли, как использовать EEPROM. Идея в том, чтобы вы применили концепции, изученные в этом руководстве, в своих собственных проектах.

Если вам интересен Arduino, мы рекомендуем ознакомиться с нашими ресурсами по Arduino:

Надеемся, эта статья была вам полезна.

Спасибо за чтение.