In this article, we will take a look at the EEPROM memory on the Arduino. EEPROM memory is a type of external memory that the Arduino can write to. You can use it to store files and logs of sensor data. To demonstrate how to use EEPROM memory on Arduino, we will create a project that reads the temperature from a thermistor and writes sensor data to external EEPROM memory.
ROM to EEPROM
ROM (Read Only Memory) stands for Read-Only Memory and was used in early microcontrollers to routinely store a computer’s operating system.
In fact, what was used was a PROM (read-only programmable memory) and was programmed or “burned” externally in a dedicated high voltage programmer. Once programmed, it becomes unchanged and you have to start all over again.
Next came EPROM (Erasable Programmable Read-Only Memory – Erasable programmable read-only memory). It has a small glass window and can be erased under strong UV light.
Then he can use the programmer again and repeat the so-called “burn and crash” (English – “burn and crash”). Then came EEPROM, or electrically erasable programmable memory, read-only.
EEPROM capacity
With the creation of EEPROM, ROM (ROM) is no longer a read-only device, but something that you can write to again, like RAM (Random Access Memory, literally random access memory).
EEPROM is significantly slower than RAM and has a write limit (usually 1 million). But this shouldn’t be a problem since there are 2 versions of the EEPROM.
The first version is a version in which you can write data in parallel in byte format, and the second is sequential using I2C, in which writing is done sequentially. The guaranteed data storage period is usually limited to 10 years.
Then came flash memory, capable of storing much more data in the same volume. While EEPROM can be written byte by byte or byte byte, Flash is written in blocks or large chunks, typically 512 bytes at a time. Note that the number of times you can burn is usually 100,000, so you have to deal with that.
The size of EEPROM memory can be confusing as it is usually specified in bits, not bytes. A 256K EEPROM can hold 256K bits of data or 32K bytes in total, about 16 pages of plain text. In addition, it works as non-volatile memory, which means that it can retain its memory even after power-on again (as opposed to volatile memory, which loses its contents after power-off).
What’s inside the chip?
Typically, each bit of memory consists of two field-effect transistors or FETs. One is the FET memory, which has a floating shutter that can be charged or discharged. The second FET is a gate that allows the first bit to be written and read.
Why add an external EEPROM and not just use an SD card? EEPROM is much faster to read and write than SD card. It has more space (32KB compared to 1KB in UNO) and is more stable than an SD card, which can fall out of the holder due to vibration.
In addition, the I2C protocol is easier to use compared to the SPI used on SD cards. The 24LC256 comes in different variations. The above figure shows a DIP IC package, a breakout board that includes pull-up resistors, and another unusual one with built-in address selectors.
EEPROM project
Now let’s create a project that will write the temperature data from the thermistor to the EEPROM. A thermistor is a resistor that changes resistance with temperature.
You can read more about thermistors on Wikipedia.
Components
To create our project we will use:
- Arduino Uno
- Thermistor 10 kΩ
- 24LC256 EEPROM chip
- Resistors
- Jumpers
- Layout
Do not forget that we must have the Arduino development environment installed – the Arduino IDE.
Connection diagram
We connect the components according to the diagram below:
Address setting
If you are going to connect more than one 24LC256 EEPROM to the microcontroller, you will need to change the addresses of each of them, making pins 1 through 3 high or low.
Since there are three (3) address lines, there can be 8 EEPROM devices (23 = 8). But each must have a unique address. If you only use one, ground all 3 pins and you will get an address of 0x50.
Write-Protect pin 7 is usually HIGH, but keep it LOW.
Connect the connection of the thermistor and 10K resistor to A0. Note that the parameters of the Steinhart equation depend on the specific type of thermistor used. If you have a different type, the results may vary, but you can calculate the parameters on this page.
Sketch
Now, using the Arduino IDE, you can upload the following code to Arduino Uno:
#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;
}
After reading the temperature T we save it to EEPROM and then read it back. Around line 50, we are converting a floating point value T to a c-type character string dtostr()
and add it to our line chrFloat
…
Then we write and read it back from the EEPROM. This is done using the “engine” of the program writeEEPROM()
and readEEPROM()
where the string is written and read byte by byte.
This way you can use functions to read / write individual bytes or characters, either through a loop or a long string.
Note that you should not use strings longer than 32 bytes. For your convenience, I also included in the sketch (commented out) how to read / write integers at the end setup
… An integer takes 2 bytes, so you need to split it by 2 bytes to store and then when read, concatenate again with word()
…
Serial window output
The sequential window should look something like this:
That’s all. Good and working projects for you.