Рейтинг@Mail.ru
EEPROM в Arduino
EEPROM в Arduino

Как хранить данные в Arduino

Be the first to comment! Arduino
Print Friendly, PDF & Email

У плат семейства плат Arduino есть несколько видов памяти. Во-первых, это статическое ОЗУ, которая используется для хранения переменных в процессе выполнения программы. Во-вторых, это флеш-память, в которой хранятся написанные вами скетчи. И в-третьих, это EEPROM, которую можно использовать для постоянного хранения информации.

Виды памяти Arduino:

  • Статическое ОЗУ (оперативное запоминающее устройство) – энергозависимая память, которая используется для хранения переменных в процессе выполнения программы. После перезагрузки Arduino теряет информацию.
  • Флеш-память – энергоНЕзависимая память, в ней хранятся написанные скетчи.
  • EEPROM – дословно переводится как «электрически стираемая программируемая память» – энергоНЕзависимая память, которую можно использовать для постоянного хранения пользовательской информации. В неё можно записывать информацию во время работы Arduino и читать по мере необходимости. Эту память мы и рассмотрим сейчас.

Инструкция по использованию EEPROM в Arduino

1Описание памяти EEPROM

EEPROM означает Electrically Erasable Programmable Read-Only Memory, т.е. электрически стираемое перепрограммируемое постоянное запоминающее устройство. Данные в этой памяти могут храниться десятки лет после отключения питания. Количество циклов перезаписи – порядка нескольких миллионов раз.

Количество EEPROM памяти в Arduino довольно ограниченно:

  • для плат, основанных на микроконтроллере ATmega328 (например, Arduino UNO и Nano), количество памяти составляет 1 кБ,
  • для плат на ATmega168 и ATmega8 – 512 байт,
  • на ATmega2560 и ATmega1280 – 4 кБ.

2Библиотека EEPROM

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

ФункцияНазначение
read(address)считывает 1 байт из EEPROM; address – адрес, откуда считываются данные (ячейка, начиная с 0);
write(address, value)записывает в память значение value (1 байт, число от 0 до 255) по адресу address;
update(address, value)заменяет значение value по адресу address, если её старое содержимое отличается от нового;
get(address, data)считывает данные data указанного типа из памяти по адресу address;
put(address, data)записывает данные data указанного типа в память по адресу address;
EEPROM[address]позволяет использовать идентификатор "EEPROM" как массив, чтобы записывать данные в память и считывать их из памяти.

Чтобы задействовать библиотеку в скетче, подключаем её директивой #include EEPROM.h.

3Запись целых чисел в EEPROM

Давайте запишем в память EEPROM два целых числа, а затем прочитаем их из EEPROM и выведем в последовательный порт. С числами от 0 до 255 проблем нет, они занимают как раз 1 байт памяти и с помощью функции EEPROM.write() записываются в нужную ячейку.

Если число больше, чем 255, то с помощью операторов highByte() и lowByte() его нужно делить на байты и записывать каждый байт в свою ячейку. Максимальное число при этом – 65536 (или 216).

#include <EEPROM.h> // подключаем библиотеку EEPROM

void setup() {
  int smallNum = 123; // целое число от 0 до 255
  EEPROM.write(0, smallNum); // запись числа в ячейку 0
    
  int bigNum = 789; // число > 255 разбиваем на 2 байта (макс. 65536)
  byte hi = highByte(bigNum); // старший байт
  byte low = lowByte(bigNum); // младший байт
  EEPROM.write(1, hi);  // записываем в ячейку 1 старший байт
  EEPROM.write(2, low); // записываем в ячейку 2 младший байт
 
  Serial.begin(9600); // инициализация послед. порта
}

void loop() {
  for (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (для Arduino UNO 1024)
    byte val = EEPROM.read(addr); // считываем 1 байт по адресу ячейки
    Serial.print(addr); // выводим адрес в послед. порт 
    Serial.print("\t"); // табуляция
    Serial.println(val); // выводим значение в послед. порт
  }

  delay(60000); // задержка 1 мин
}

Смотрите, монитор последовательного порта в ячейку 0 просто выводит число, меньшее, чем 255. В ячейках 1 и 2 хранится большое число 789. При этом ячейка 1 хранит множитель переполнения 3, а ячейка 2 – недостающее число 21 (т.е. 789 = 3×256 + 21).

Запись целых чисел в EEPROM Arduino
Запись целых чисел в EEPROM Arduino

Чтобы заново «собрать» большое число, разобранное на байты, есть функция word(): int val = word(hi, low), где "hi" и "low" – это значения старшего и младшего байтов числа "val".

Во всех остальных ячейках, которые не были нами ни разу записаны, хранятся числа 255.

4Запись чисел с плавающей запятой и строк в EEPROM

Для записи чисел с плавающей запятой и строк нужно использовать метод EEPROM.put(), а для чтения – EEPROM.get().

#include <EEPROM.h> // подключаем библиотеку

void setup() {
  int addr = 0; // адрес 
  float f = 3.1415926f; // число с плавающей точкой (типа float)
  EEPROM.put(addr, f); // записали число f по адресу addr
  
  addr += sizeof(float); // вычисляем следующую свободную ячейку памяти
  char name[20] = "Hello, SolTau.ru!"; // создаём массив символов
  EEPROM.put(addr, name); // записываем массив в EEPROM 
  Serial.begin(9600); // инициализация послед. порта
}

void loop() {
  for (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (1024Б=1кБ)
    Serial.print(addr); // выводим адрес в послед. порт 
    Serial.print("\t"); // табуляция
    float f; // переменная для хранения значений типа float
    EEPROM.get(addr, f); // получаем значение типа float по адресу addr    
    Serial.print(f, 5); // выводим с точностью 5 знаков после запятой
    Serial.print("\t"); // табуляция

    char c[20]; // переменная для хранения массива из 20 символов
    EEPROM.get(addr, c); // считываем массив символов по адресу addr
    Serial.println(c); // выводим массив в порт
  }

  delay(60000); // ждём 1 минуту
}

В процедуре setup() сначала запишем число с плавающей запятой "f". Затем сдвинемся на количество ячеек памяти, которое занимает тип "float", и запишем строку символов "char" ёмкостью 20 ячеек.

В процедуре loop() будем считывать все ячейки памяти и пытаться расшифровать их сначала как тип "float", а затем как тип "char", и выводить результат в последовательный порт.

Запись чисел с плавающей запятой в EEPROM Arduino
Запись чисел с плавающей запятой в EEPROM Arduino

Видно, что значение в ячейках с 0 по 3 правильно определилось как число с плавающей точкой, а начиная с 4-ой – как строка.

Появляющиеся значения ovf (переполнение) и nan (не число) говорят о том, что значение в ячейке памяти по этому адресу не может быть корректно преобразовано в число с плавающей точкой. Если вы точно знаете, какого типа данные какие ячейки памяти занимают, то у вас не будет возникать проблем.

5Работа с EEPROM как с массивом

Очень удобная возможность – обращение к ячейкам памяти как к элементам массива EEPROM. В данном скетче в процедуре setup() мы сначала запишем данные в 4 первых байта, а в процедуре loop() ежеминутно будем считывать данные из всех ячеек и выводить их в последовательный порт.

#include <EEPROM.h>

void setup() {
  EEPROM[0] = 11;  // записываем 1-ю ячейку
  EEPROM[1] = 121; // записываем 2-ю ячейку
  EEPROM[2] = 141; // записываем 3-ю ячейку
  EEPROM[3] = 236; // записываем 4-ю ячейку
  Serial.begin(9600);
}

void loop() {
  for (int addr=0; addr<1024; addr++) { 
    Serial.print(addr);
    Serial.print("\t");
    int n = EEPROM[addr]; // считываем ячейку по адресу addr
    Serial.println(n);    // выводим в порт
  }
  
  delay(60000);
}
Работа с ячейками памяти EEPROM Arduino как с элементами массива
Работа с ячейками памяти EEPROM Arduino как с элементами массива
Last modified onСреда, 10 Январь 2024 19:12 Read 96681 times
Ключевые слова: :

Поблагодарить автора:

Поделиться

Print Friendly, PDF & Email

Leave a comment