Almost all Arduino compatible microcontrollers contain several different types of memory with each their own characteristics.

Flash Memory

The flash memory is where the program you upload is stored. This segment is quite large but writing it requires programming the microcontroller. It can be used for constant read only data as well such as debug strings or large arrays using the PROGMEM and F macros. You can learn more about those here. Atmel specs the Arduino UNO’s flash memory to around 10,000 write cycles before it wears out so it is not suitable for fast changing data.

SRAM

The Static Random Access Memory is used to store data during execution and is generally very fast. It is volatile so the contents are erased when the board is without power.

EEPROM

Electrically Erasable Programmable Read-Only Memory (EEPROM) is another non-volatile memory available. It contains less storage than the flash memory but the number of write cycles it can endure substantially more. The Arduino UNO’s EEPROM is specified to 100,000 write cycles so it should be used for storing parameters and long term data but not as a scratch pad to write to a couple of times per second. Reading and writing to the EEPROM is generally quite slow and abstractions for it are collected in the \prog{EEPROM.h} library. Writing takes quite a lot of time (3.3ms on the UNO) so it pays off to first check whether the write is actually necessary by reading the value first. EEPROM can also be accessed like any other array with EEPROM[address].

Some important EEPROM functions:

  • EEPROM.write(address, val)
    • Writes exactly one byte, val, to address.
  • EEPROM.read(address)
    • Reads exactly one byte from address.
  • EEPROM.update(address, val)
    • Performs the same function as write(), but checks if the value is different before writing to reduce write cycles.
  • EEPROM.put(address, val)
    • Writes val, which can be any data type or object, to address. Uses update() in the background.
  • EEPROM.get(address, val)
    • Reads the datatype specified in val from address.
  • EEPROM.begin(mem_amnt)
    • Initializes mem_amnt} of bytes in the EEPROM. Only necessary on the ESP8266. Make sure this is called before any read/write operations.
  • EEPROM.commit()
    • Commits the changes made by the program to the EEPROM. Only necessary on the ESP8266.

The following is an example of how to store and get data from EEPROM on the ESP8266. It is the same on the UNO, except for the EEPROM.begin() and EEPROM.commit() function calls are not necessary.

#include <EEPROM.h>							// Include the EEPROM library
 
int address = 5;							// Address in memory we want to read
 
int ledState= 0;
 
void setup() {
  EEPROM.begin(512);    // Initialize the EEPROM. It has 512 bytes of memory, so that is what we initialize it with.
  Serial.begin (115200); // Start serial communication
  pinMode(LED_BUILTIN, OUTPUT);             // Set the LED pin to output mode
  EEPROM.get(address, ledState);            // Get the value stored at address and assign it to ledState
  digitalWrite(LED_BUILTIN, ledState);      // Turn the LED on or off depending on the value stored in EEPROM
}
void loop() {
  if (Serial.available() > 0) {             // Check if input has been submitted on the serial monitor
    char c = (char)Serial.read();           // Read the first byte of input as a character
    switch (c) {
      case '1':
      case 'i':
      case 'I':                             // For the input '1', 'i', or 'I'
        digitalWrite(LED_BUILTIN, HIGH);    // Turn off the LED
        ledState = HIGH;
        Serial.println("In");               // Print "In" to the serial monitor
        EEPROM.put(address, ledState);      // Update the value at address to ledState if it has changed
        break;
      case '0':
      case 'o':
      case 'O':                             // For the input '0', 'o', or 'O'
        digitalWrite(LED_BUILTIN, LOW);     // Turn on the LED
        ledState = LOW;
        Serial.println("Out");              // Print "Out" to the serial monitor
        EEPROM.put(address, ledState);      // Update the value at address to ledState if it has changed
        break;
    }
    while (Serial.available() > 0) {        // Read the rest of the input
      Serial.read();                        
    }
  EEPROM.commit();                          // Commit the changes to the EEPROM
  delay (250);                              // Wait 250ms
  }
}