Arduino – 5 – Storing Data in Arduino EEPROM Memory

Electrically Erasable Programmable Read-Only Memory (EEPROM) is a type of memory that retains its values even when a microcontroller is turned off. The amount of EEPROM on an Arduino board is dependent on the microcontroller at its core.
Table 5.1 lists the amount of EEPROM memory available on the microcontrollers used on different Arduino boards.

Table 5.1 EEPROM memory on microcontrollers used on Arduino boards

Microcontroller EEPROM memory (bytes)
ATMega8 and ATMega168 512
ATMega328 1024
ATMega1280 and ATMega2560 4096

NOTE: The Arduino Uno is based on an ATMega328; it has 1,024 bytes of EEPROM memory. Arduino Mega board is based on an ATMega2560; it has 4,096 bytes of EEPROM memory.

The EEPROM library gives sketches access to the Arduino’s EEPROM and provides two functions, read and write, as shown in table 5.2.

Table 5.2: The functions available in the EEPROM library

Function Description
read( ) Reads the value of a byte stored at a location in EEPROM
write( ) Writes a value to a location in EEPROM

NOTE: Any data written to the EEPROM remains there even when the Arduino boards is switched off.

A good use of the EEPROM library would be to store settings in between Arduino restarts—for example, constants that might be used by an LCD interface, data in a counting application, or the highest score in a game. If you want to store more data than this, it might be time to think about using SD cards.

Use the EEPROM library to read and write values in EEPROM memory

This sketch blinks an LED using values read from EEPROM and allows the values to be changed using the Serial Monitor:

Listing 5-1: Blink LED with rate value store in Arduino Build-in EEPROM

/*==========================================================================
//  Author      : Handson Technology
//  Project     : Arduino Uno
//  Description : Blink LED with rate store in Arduino Build-in EEPROM
//  LiquidCrystal Library
//==========================================================================
*/

#include <EEPROM.h>

// these values are saved in EEPROM
const byte EEPROM_ID = 0x99;   // used to identify if valid data in EEPROM
byte ledPin =  13;             // the number of the LED pin
int interval = 1000;           // interval at which to blink (milliseconds)

// variables that do not need to be saved
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

//constants used to identify EEPROM addresses
const int ID_ADDR = 0;       // the EEPROM address used to store the ID
const int PIN_ADDR = 1;      // the EEPROM address used to store the pin
const int INTERVAL_ADDR = 2; // the EEPROM address used to store the interval

void setup()
{
  Serial.begin(9600);
  byte id = EEPROM.read(ID_ADDR); // read the first byte from the EEPROM
  if( id == EEPROM_ID)
  {
    // here if the id value read matches the value saved when writing eeprom
    Serial.println("Using data from EEPROM");
    ledPin = EEPROM.read(PIN_ADDR);
    byte hiByte =  EEPROM.read(INTERVAL_ADDR);
    byte lowByte =  EEPROM.read(INTERVAL_ADDR+1);
    interval =  word(hiByte, lowByte); // see word function in Recipe 3.15
  }
  else
  {
    // here if the ID is not found, so write the default data
    Serial.println("Writing default data to EEPROM");
    EEPROM.write(ID_ADDR,EEPROM_ID); // write the ID to indicate valid data
    EEPROM.write(PIN_ADDR, ledPin); // save the pin in eeprom
    byte hiByte = highByte(interval);
    byte loByte = lowByte(interval);
    EEPROM.write(INTERVAL_ADDR, hiByte);
    EEPROM.write(INTERVAL_ADDR+1, loByte);

  }
  Serial.print("Setting pin to ");
  Serial.println(ledPin,DEC);
  Serial.print("Setting interval to ");
  Serial.println(interval);

  pinMode(ledPin, OUTPUT);
}

void loop()
{
  // this is the same code as the BlinkWithoutDelay example sketch
  if (millis() - previousMillis > interval)
  {
    previousMillis = millis();     // save the last time you blinked the LED
    // if the LED is off turn it on and vice versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    digitalWrite(ledPin, ledState);   // set LED using value of ledState
  }
  processSerial();
}

// function to get duration or pin values from Serial Monitor
// value followed by  i is interval, p is pin number
int value = 0;

void processSerial()
{
   if( Serial.available())
  {
    char ch = Serial.read();
    if(ch >= '0' && ch <= '9')   // is this an ascii digit between 0 and 9?
    {
       value = (value * 10) + (ch - '0'); // yes, accumulate the value
    }
    else if (ch == 'i')  // is this the interval
    {
       interval = value;
       Serial.print("Setting interval to ");
       Serial.println(interval);
       byte hiByte = highByte(interval);
       byte loByte = lowByte(interval);
       EEPROM.write(INTERVAL_ADDR, hiByte);
       EEPROM.write(INTERVAL_ADDR+1, loByte);
       value = 0; // reset to 0 ready for the next sequence of digits
    }
    else if (ch == 'p')  // is this the pin number
    {
       ledPin = value;
       Serial.print("Setting pin to ");
       Serial.println(ledPin,DEC);
       pinMode(ledPin, OUTPUT);
       EEPROM.write(PIN_ADDR, ledPin); // save the pin in eeprom
       value = 0; // reset  to 0 ready for the next sequence of digits
    }
  }
}
      

Open the Serial Monitor. As the sketch starts, it tells you whether it is using values previously saved to EEPROM or defaults, if this is the first time the sketch is started. You can change values by typing a number followed by a letter to indicate the action. A number followed by the letter i changes the blink interval; a number followed by a p changes the pin number for the LED.

Listing 5-1 Source Code: eeprom_blinking.rar