В этой статье мы рассмотрим память EEPROM на Arduino. Память EEPROM - это тип внешней памяти, в которую Arduino может делать записи. Вы можете использовать ее для хранения файлов и логов данных датчика. Чтобы продемонстрировать, как использовать память EEPROM на Arduino, мы создадим проект, который считывает температуру с термистора, и записывает данные датчика во внешнюю память EEPROM.
От ROM к EEPROM
ROM (ПЗУ, Постоянное запоминающее устройство) расшифровывается как Read-Only Memory (только для чтения) и использовалась в ранних микроконтроллерах для обычного хранения операционной системы компьютера.
Фактически, то, что использовалось, было PROM (программируемая память только для чтения) и программировалась или "прожигалась" внешне в специальном программаторе с высоким напряжением. Однажды запрограммированная, она становится неизменной и нужно начинать всё с самого начала.
Далее появилась EPROM (Erasable Programmable Read-Only Memory - Стираемая программируемая память, доступная только для чтения). Она имеет маленькое стеклянное окошко и может быть стерта под сильным ультрафиолетовым излучением.
Затем может снова воспользоваться программатором и повторить так называемый «прожиг и падение» (англ. - "burn and crash"). Далее появилась EEPROM или электрически стираемая программируемая память, доступная только для чтения.
Емкость EEPROM
С созданием EEPROM, ROM (ПЗУ) больше не является устройством, доступным только для чтения, а является чем-то, на что вы можете записать снова, подобно RAM (Оперативное запоминающее устройство или Random Access Memory, дословно - случайный доступ к памяти).
EEPROM значительно медленнее оперативной памяти и имеет ограничение по количеству записей (обычно 1 миллион). Но это не должно стать проблемой, так как существует 2 версии EEPROM.
Первая версия - это версия, в которой можно параллельно записывать данные в байтовом формате, а вторая - последовательная с использованием I2C, в которой запись выполняется последовательно. Гарантированный срок хранения данных ограничен, как правило, 10 годами.
Далее появилась флеш-память, способная хранить гораздо больше данных в том же объеме. В то время как EEPROM может записываться байт за байтом или побайтово, флеш-память записывается блоками или большими фрагментами, обычно по 512 байт за раз. Обратите внимание, что количество раз, которое вы можете записать, обычно составляет 100 000, так что вам придется с этим справляться.
Размер EEPROM-памяти может ввести в заблуждение, так как обычно она задается в битах, а не в байтах. 256K EEPROM может содержать 256K бит данных или всего 32K байт, около 16 страниц простого текста. Кроме того, она работает как энергонезависимая память, что означает, что она может сохранять свою память даже после повторного включения питания (в отличие от энергозависимой, которая теряет свое содержимое после выключения питания).
Что внутри чипа?
Обычно каждый бит памяти состоит из двух полевых транзисторов или FET (field-effect transistors). Один из них является FET памяти, который имеет плавающий затвор, который может быть заряжен или разряжен. Второй FET - это затвор, позволяющий записывать и считывать первый бит.

Зачем добавлять внешнюю EEPROM, а не просто использовать SD-карту? EEPROM намного быстрее для чтения и записи, чем SD-карта. Она имеет больше места (32 КБ по сравнению с 1 КБ в UNO) и более устойчива, чем SD-карта, которая может выпасть из держателя из-за вибрации.
Кроме того, протокол I2C упрощает использование по сравнению с SPI, используемым на SD-картах. 24LC256 поставляется в разных вариациях. Выше на рисунке показан пакет DIP IC, коммутационная плата, которая включает в себя подтягивающие резисторы, и еще один необычный со встроенными селекторами адресов.
Проект с использованием EEPROM
Теперь создадим проект, который будет записывать температурные данные от термистора в EEPROM. Термистор - это резистор, который изменяет сопротивление с температурой.
Дополнительную информацию о термисторах вы можете прочитать в Википедии.
Компоненты
Для создания нашего проекта мы будем использовать:
- Arduino Uno
- Термистор 10 кОм
- 24LC256 EEPROM чип
- Резисторы
- Перемычки
- Макет
Не забываем, что у нас должна быть установлена среда разработки Ардуино - IDE Arduino.
Схема соединения
Комплектующие соединяем согласно схеме ниже:

Настройка адреса
Если вы собираетесь подключить более одного 24LC256 EEPROM к микроконтроллеру, вам нужно будет изменить адреса каждого из них, сделав контакты с 1 по 3 высокими или низкими.
Поскольку имеется три (3) адресные линии, то может быть 8 устройств EEPROM (23 = 8). Но у каждого должен быть уникальный адрес. Если вы используете только один, заземлите все 3 контакта, и вы получите адрес 0x50.
Вывод Write-Protect, пин 7, обычно высокий (HIGH), но оставьте его низким (LOW).
Подключите соединение термистора и резистора 10 кОм к A0. Обратите внимание, что параметры уравнения Стейнхарта зависят от конкретного типа используемого термистора. Если у вас другой тип, результаты могут отличаться, но вы можете вычислить параметры на этой странице.
Скетч
Теперь, с помощью Arduino IDE вы можете загрузить в Ардуино Уно следующий код:
#include <Wire.h>
#define xAddr 0x50 // defines the base address of the external EEPROM
byte hiByte;
byte loByte;
byte i;
char buffer[10];
char newStr[10];
unsigned int eepromAdd = 0;
int ThermistorPin = A0;
int Vo;
float R1 = 10000;
float logR2, R2, T;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
void setup() {
Serial.begin(9600);
Wire.begin(); //creates a Wire object
/*
//write an integer
int myInt = 5678;
hiByte = highByte(myInt); //breaks up into into 2 bytes
loByte = lowByte(myInt);
writeEEPROM(xAddr, eepromAdd, hiByte); //write a byte
writeEEPROM(xAddr, eepromAdd+1, loByte); //write a byte
//now read it back
hiByte = readEEPROM(xAddr, eepromAdd);
loByte = readEEPROM(xAddr, eepromAdd + 1); //step 1
int newInt = word(hiByte, loByte);
Serial.println(newInt);
*/
}
void loop() {
Vo = analogRead(ThermistorPin);
R2 = R1 * (1023.0 / (float)Vo - 1.0);
logR2 = log(R2);
T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
T = T - 273.15; //in centigrade
//T = (T * 9.0)/ 5.0 + 32.0; // un-comment for Fahrenheit
Serial.print("Temperature measured: ");
Serial.print(T);
Serial.println(" C");
delay(500);
//convert float to string and write it to the EEPROM
char chrFloat[] = "";;
char buffer[10];
dtostrf(T, 6, 4, buffer); //6 is minimum width, 4 is precision; float value is copied onto buff
strcat( chrFloat, buffer); //append the converted (float now string)
//write the string:
for(byte i=0; i<=strlen(chrFloat);i++)
writeEEPROM(xAddr, eepromAdd+i, chrFloat[i]); //write a byte
//read it back:
for(i=0; i<=strlen(chrFloat);i++)
newStr[i] = readEEPROM(xAddr, eepromAdd + i); //read a byte
newStr[i] = 0;
Serial.print("Temperature from EEPROM ");
Serial.println(atof(newStr),2); //convert ASCII to float with 2 decimals
}
//write a byte or single char - less than 256
void writeEEPROM(int devAddr, unsigned int eeAddr, byte data ) {
Wire.beginTransmission(devAddr);
Wire.write((byte)eeAddr >> 8); //writes the most significant byte, move LSB off to right to get rid of it
Wire.write((byte)eeAddr & 0xFF); //writes the least significant byte, mask off LSB with bitwise AND 0
Wire.write(data);
Wire.endTransmission();
delay(5); //need this for sure
}
//read a byte or single char - less than 256
byte readEEPROM(int devAddr, unsigned int eeAddr ) {
byte readByte = 0;
Wire.beginTransmission(devAddr);
Wire.write((byte)eeAddr >> 8); //writes the most significant byte
Wire.write((byte)eeAddr & 0xFF); //writes the least significant byte
Wire.endTransmission();
Wire.requestFrom(devAddr,1);
if (Wire.available())
readByte = Wire.read();
return readByte;
}
После считывания температуры T мы сохраняем ее в EEPROM и затем читаем обратно. В районе строку 50, мы конвертируем значение с плавающей точкой T в символьную строку c-типа dtostr()
и добавляем ее в нашу строку chrFloat
.
Затем мы пишем и читаем ее обратно из EEPROM. Это делается с помощью «движка» программы writeEEPROM()
и readEEPROM()
, где строка записывается и читается побайтово.
Таким образом, вы можете использовать функции для чтения/записи отдельных байтов или символов или через цикл или длинную строку.
Обратите внимание, что вы не должны использовать строки длиннее 32 байт. Для вашего удобства я также включил в скетч (закомментировал), как читать/писать целые числа в конце setup
. Целое число занимает 2 байта, поэтому вам нужно разделить его на 2 байта, чтобы сохранить, а затем при чтении соединить снова с помощью word()
.
Вывод в последовательном окне
Последовательное окно должно выглядеть как-то так:

На этом всё. Хороших и рабочих вам проектов.