Introduction
EEPROM is a permanent memory. It will remain even after the Arduino is restarted. It can be reprogrammed around 100,000 times, so it is substantially less resilient than the flash storage or a hard drive. It is also kind of slow (3ms per byte). The Ardiono Uno has 1KB of EEPROM.
The compiled program is uploaded to flash storage (not EEPROM), which is faster and larger. So, if you can, it is better to write keep as much as possible in the C++ file.
Sometimes it can be convenient or more reliable to use the EEPROM. You could log sensor readings to EEPROM so that the data will still be there even if it loses power. Alternatively, you could use an SD shield and get more, more reliable, and more portable storage.
If you have multiple Arduinos for a project that do the same tasks, but want a way to differentiate them despite having identical programming, you could flash an ID number to the EEPROM.
Simple Usage
Reader
This reader is used after the writer to get the value from the EEPROM:
#include <EEPROM.h>
int address = 0;
void setup() {
Serial.begin(9600);
int value = EEPROM.read(address);
Serial.print("Read: ");
Serial.println( value );
}
void loop() {
}
Writer
Here is a simple writer that just writes an int of 123 to the first byte in the EEPROM:
#include <EEPROM.h>
int address = 0;
void setup() {
Serial.begin(9600);
int value = 123;
EEPROM.write(address, value);
Serial.println("Done writing");
}
void loop() {
}
Structured and Organized Storage
A cool trick in C++ is to sort of overlay a structure onto an area of memory - taking advantage of data structure alignment. This organization method is used heavily in file manipulation, for example: reading a bitmap.
The cool thing about this is that you can mix datatypes and not have to worry about reading things in the right order. As long as the struct remains the same when you read it after you write it.
You might see this struct example and want to use it as a seperate class in a seperate header, but I didn't do that primarily because it depends so heavily on the struct you make. It is actually possible to make an encapsulated version of this by using templates. A template is a way to pick a data type for some elements in a class. Some good examples of ways they are useful are vectors and linked lists.
This class should only be used once in a project without any modification. By simply adding a fixed offset to the EEPROM.read and EEPROM.write methods, multiples could be used.
#include <EEPROM.h>
typedef struct /**** EEPROM STORAGE STRUCTURE ****/
{
//stuff in here gets stored to the EEPROM
unsigned short count; /* A count of values stored */
long sum; /* A running total of values */
char str[10]; /* A string label */
int values[100]; /* Array of values collected */
boolean complete; /* a flag for whether gathering is finished */
} EEPROMSTORAGE;
// a class to manage the struct
class Permanent {
private:
// the actual eeprom gets stored here
// the struct is overlayed onto this storage
byte buffer[ sizeof(EEPROMSTORAGE) ];
public:
Permanent(); //constructor - reads the eeprom
void write(); //a function to write to the eeprom
//this pointer makes the buffer's contents easily accessed
EEPROMSTORAGE * store;
};
//read the eeprom into the buffer
Permanent::Permanent() {
for( int i = 0; i < sizeof(EEPROMSTORAGE); ++i ) {
buffer[i] = EEPROM.read(i);
}
//overlay the pointer to the storage onto the buffer
store = (EEPROMSTORAGE *) buffer;
}
//write the buffer into the eeprom
//be careful writting too often to the eeprom. It only has 100,000 writes
void Permanent::write() {
for( int i = 0; i < sizeof(EEPROMSTORAGE); ++i ) {
EEPROM.write(i, buffer[i]);
}
}
//make an instance of the managing class called eeprom (in lower case!)
Permanent eeprom;
//this is just a demo of how you would access and write the data
void setup() {
Serial.begin(9600);
//check to see what was already in the eeprom. serial print it.
Serial.println( eeprom.store->str );
//fill the buffer's store with some data
eeprom.store->count = 0;
strcpy( eeprom.store->str, "Hello!");
for(int i = 0; i < 50; ++i ) {
int sensorVal = i*3+2;
eeprom.store->values[i] = sensorVal;
eeprom.store->sum += sensorVal;
eeprom.store->count++;
}
eeprom.store->complete = true;
//write the buffered data to the eeprom
eeprom.write();
}
void loop() {}