EEPROM енергонезалежна память яка може зберігати записані в неї дані десятки років після вимкнення живлення. Деякі виробники гаранатують 100 років зберігання інформації без механічних пошкоджень. Кількість разів перезапису EEPROM пам’яті обмежена, та може складати від десяти тисяч (10 000) до одного мільйона (1 000 000) циклів. Кількість циклів читання теоретично необмежений. Операція запуси одного байта виконується за 3 ~ 4 мікросекунди, а читання 0.5 мікросекунд.
В платах Arduino об’єм EEPROM памяті наступний:
- ATmega168 Arduino Nano – 512 байт
- ATmega328 Arduino Uno, Arduino Nano – 1Kбайт
- ATmega1280, ATmega2560 Arduino Mega – 4 Кбайт
У Arduino проектах EEPROM пам’ять часто використовується для зберігання налаштувань програми. також для різного роду лічильників. Основне завдання писати не дуже часто, щоб не вичерпати ресурс пам’яті.
При 100 000 циклів запису та частотою запису один раз на хвилину, пам’яті вистачить на ~ 69 днів.
100 000 / 60 = 1666 годин роботи пам’яті до вичерпання ресурсу
1666 / 24 = 69 днів
69 днів це умови запису в одну і туж адресу.
Якщо записувати циклічно по усьому об’єму, ресурсу вистачить на довше. До прикладу у ATmega328 1Кбайт EEPROM памяті, це 1024байта. Змінна для запису INT яка займає 2 байта, отримаєм при записі один раз на хвилину 69 * (1024 / 2) = 35328 днів, або ~ 96 років. Приклад циклічного перезапису.
Бібліотека EEPROM в Arduino
В фреймфоркові Arduino бібліотека для роботи з EEPROM інтегрована за умовчанням.
Вона складається всього з дев’яти функцій.
EEPROM.begin() | Початок роботи з памяють, оголошується один раз при старті |
EEPROM.end() | Повертає EEPROM.length() |
EEPROM.length() | Повертає розмір пам’яті |
EEPROM.read(address) | Повертає прочитаний байт за адресою |
EEPROM.write(address, value) | Записати байт за вказаною адресою |
EEPROM.update(address, value) | Записує значення якщо воно відрізняється |
EEPROM.get(address, data) | Отримати значення будьякого типу з адреси |
EEPROM.put(address, data) | Записати значення будьякого типу за вказаною адресою |
EEPROM[address] | Базовий оператор запису читання одного байта |
Приклади коду
Функція EEPROM.end() повертає останню доступну адресу в памяті, фактично це розмір самої EEPROM пам’яті. Тобто функції EEPROM.end() та EEPROM.length() ідентичні.
#include <Arduino.h>
#include <EEPROM.h>
void setup()
{
EEPROM.begin();
Serial.begin(9600);
Serial.println(EEPROM.end());
Serial.println(EEPROM.length());
}
void loop()
{
}
Лічильник перезавтажень
#include <Arduino.h>
#include <EEPROM.h>
int zero_addres = 0;
void setup()
{
// First run save zero value
// EEPROM.put(zero_addres, 0);
EEPROM.begin();
Serial.begin(9600);
int reboot_count;
EEPROM.get(zero_addres, reboot_count);
Serial.println(reboot_count);
EEPROM.put(zero_addres, reboot_count + 1);
}
void loop()
{
}
Форматування всієї EEPROM пам’яті, запис нулями
#include <Arduino.h>
#include <EEPROM.h>
int zero_addres = 0;
void setup()
{
EEPROM.begin();
int eeprom_size = EEPROM.length();
for (int i = 0; i <= eeprom_size; i++)
{
EEPROM.update(i, 0);
}
}
void loop()
{
}
Запис та читання різних типів
#include <Arduino.h>
#include <EEPROM.h>
int zero_addres = 0;
int int_val_addres = 1;
int float_val_addres = 3;
int cahr_val_addres = 10;
void setup()
{
EEPROM.begin();
Serial.begin(9600);
// byte
EEPROM.write(zero_addres, 124);
// or
EEPROM.update(zero_addres, 124); // write only if the value differs
Serial.println(EEPROM.read(zero_addres));
// int
int new_int_val = 4856;
EEPROM.put(int_val_addres, new_int_val); // write only if the value differs
int read_int_val;
EEPROM.get(int_val_addres, read_int_val);
Serial.println(read_int_val);
// float
float new_float_val = 38.63;
EEPROM.put(float_val_addres, new_float_val); // write only if the value differs
float read_float_val;
EEPROM.get(float_val_addres, read_float_val);
Serial.println(read_float_val);
// char
char new_char_val[18] = "Hello world, char";
EEPROM.put(cahr_val_addres, new_char_val); // write only if the value differs
char read_char_val[18];
EEPROM.get(cahr_val_addres, read_char_val);
Serial.println(read_char_val);
// base operator byte
int addr = 100;
unsigned char val = 129;
EEPROM[addr] = val;
unsigned char _val = EEPROM[addr];
Serial.println(_val);
}
void loop()
{
}
Циклічний запис
#include <Arduino.h>
#include <EEPROM.h>
int addres = 0;
void setup()
{
EEPROM.begin();
}
int my_value()
{
return rand();
}
void loop()
{
static unsigned long timer = 0;
if ((millis() - timer) > 60000)
{
if (addres > EEPROM.length())
{
addres = 0;
}
EEPROM.put(addres, my_value());
addres += 2; // sizeof(int) = 2
timer = millis();
}
}
Даний приклад один раз на хвилину записує випадкове число у EEPROM, по порядку у весь об’єм пам’яті. При досягні кінця переходить знову на початок.