Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Arduino & Microcontrollers

Arduino EEPROM: Save Data Permanently Without SD Card

Arduino EEPROM: Save Data Permanently Without SD Card

March 11, 2026 /Posted byJayesh Jain / 0

One of the most useful features built into the ATmega328P is its internal EEPROM — 1 KB of non-volatile memory that survives power cycles without any extra hardware. With this arduino EEPROM tutorial, you will learn how to read, write, and manage the Arduino’s built-in EEPROM to save settings, calibration values, sensor offsets, device IDs, and user configurations — all without needing an SD card, external flash chip, or any additional components. It is the simplest form of permanent storage available on any Arduino board.

Table of Contents

  • What Is EEPROM and How Does It Work?
  • The Arduino EEPROM Library
  • Reading and Writing Bytes
  • Storing Structs and Objects with EEPROM.put/get
  • EEPROM Lifespan and Wear Considerations
  • Practical Examples
  • Frequently Asked Questions

What Is EEPROM and How Does It Work?

EEPROM stands for Electrically Erasable Programmable Read-Only Memory. Unlike RAM (SRAM), which loses its contents when power is removed, EEPROM retains stored data indefinitely without power — for decades in ideal conditions. Unlike Flash memory (where your sketch is stored), EEPROM can be erased and written one byte at a time rather than in entire pages or sectors.

The ATmega328P contains 1,024 bytes of EEPROM (addresses 0 to 1023). The ATmega2560 (Arduino Mega) has 4,096 bytes. The ATmega4809 (Arduino Nano Every) has only 256 bytes — a notable reduction from the classic ATmega328P.

EEPROM has a guaranteed write endurance of at least 100,000 write cycles per byte. Reads are unlimited and do not cause wear. This means you can write a configuration byte every minute for over 69 days before reaching the endurance limit — and in practice most applications write far less frequently, making EEPROM extremely durable for typical use cases.

Recommended: Arduino Uno R3 Beginners Kit — The Uno’s ATmega328P provides 1 KB of EEPROM and is the standard platform for all examples in this tutorial. The kit includes everything needed to build sensor projects that save calibration data to EEPROM.

The Arduino EEPROM Library

Arduino includes the EEPROM library in the standard installation — no installation required. Include it at the top of your sketch:

#include <EEPROM.h>

The library provides the following functions:

  • EEPROM.read(address) — Read one byte from a given address (0–1023)
  • EEPROM.write(address, value) — Write one byte (always erases first, even if value matches)
  • EEPROM.update(address, value) — Write one byte only if value differs from stored value (saves wear cycles)
  • EEPROM.get(address, variable) — Read any data type from EEPROM into a variable
  • EEPROM.put(address, variable) — Write any data type to EEPROM from a variable
  • EEPROM.length() — Returns the total EEPROM size in bytes (1024 for Uno)

Reading and Writing Bytes

Writing a Byte

#include <EEPROM.h>

void setup() {
  // Write the value 42 to EEPROM address 0
  EEPROM.write(0, 42);
  
  // Write a sensor offset value
  int offset = -5;
  EEPROM.write(10, (byte)(offset + 128));  // Shift to fit in 0-255 range
}

void loop() {}

Reading a Byte

void setup() {
  Serial.begin(9600);
  
  byte storedValue = EEPROM.read(0);
  Serial.print("Stored value: ");
  Serial.println(storedValue);
  
  // A freshly erased EEPROM byte reads as 255
  // Check for uninitialized state:
  if (storedValue == 255) {
    Serial.println("EEPROM not yet written (blank)");
  }
}

Using EEPROM.update() to Reduce Wear

Always prefer EEPROM.update() over EEPROM.write() when the value might not change between writes. update() reads the current value first and only writes if the new value differs, saving a wear cycle when the value is the same:

// Instead of:
EEPROM.write(0, newValue);  // Always writes, uses a wear cycle

// Use:
EEPROM.update(0, newValue);  // Only writes if value changed

Storing Integers (Multi-Byte Values)

Integers are 2 bytes on Arduino. To store them manually in EEPROM:

int myValue = 1234;

// Write high byte then low byte
EEPROM.update(0, highByte(myValue));
EEPROM.update(1, lowByte(myValue));

// Read back:
int readBack = (EEPROM.read(0) << 8) | EEPROM.read(1);
Serial.println(readBack);  // prints 1234

Or much more easily, use EEPROM.put() and EEPROM.get() (see next section).

Recommended: Arduino Pro Mini 328 – 3.3V/8 MHz — For battery-powered sensor nodes that need to remember calibration values and settings across power cycles, the Pro Mini’s 1 KB EEPROM combined with its exceptional low-power sleep capability is the perfect combination.

Storing Structs and Objects with EEPROM.put/get

The most powerful feature of the EEPROM library is the ability to store and retrieve any C++ data type — including structs — with a single function call. This is the recommended approach for real projects with multiple settings.

Defining a Settings Struct

#include <EEPROM.h>

struct Settings {
  float temperatureOffset;
  int sampleInterval;       // in seconds
  byte displayBrightness;
  bool alarmEnabled;
  char deviceName[16];
};

Settings mySettings;
const int EEPROM_ADDR = 0;  // Start address for struct

Writing the Struct to EEPROM

void saveSettings() {
  EEPROM.put(EEPROM_ADDR, mySettings);
  // put() uses update() internally — only writes bytes that changed!
}

Reading the Struct from EEPROM

void loadSettings() {
  EEPROM.get(EEPROM_ADDR, mySettings);
  
  // Check if EEPROM has valid data (look for a magic number)
  // A blank EEPROM has 0xFF in all bytes — floats with all 0xFF are NaN
  if (isnan(mySettings.temperatureOffset)) {
    // First boot — apply defaults
    mySettings.temperatureOffset = 0.0;
    mySettings.sampleInterval = 60;
    mySettings.displayBrightness = 128;
    mySettings.alarmEnabled = false;
    strcpy(mySettings.deviceName, "SensorNode1");
    saveSettings();
  }
}

Using a Magic Number for Validation

A more robust approach stores a magic number (a specific constant) at a known EEPROM address. On boot, check if the magic number is present — if not, the EEPROM is blank or corrupted and you should apply defaults:

const uint16_t MAGIC = 0xAB42;
const int MAGIC_ADDR = 0;
const int DATA_ADDR = 2;

void setup() {
  uint16_t storedMagic;
  EEPROM.get(MAGIC_ADDR, storedMagic);
  
  if (storedMagic != MAGIC) {
    // First boot — write defaults
    mySettings = defaultSettings;
    EEPROM.put(DATA_ADDR, mySettings);
    EEPROM.put(MAGIC_ADDR, MAGIC);
  } else {
    EEPROM.get(DATA_ADDR, mySettings);
  }
}
Recommended: DHT11 Digital Relative Humidity and Temperature Sensor Module — A classic sensor to pair with EEPROM for data logging. Store calibration offsets for temperature and humidity in EEPROM so they are remembered after power cycles, without needing any user reconfiguration.

EEPROM Lifespan and Wear Considerations

The ATmega328P’s EEPROM is rated for 100,000 write cycles per byte. For most hobby and maker projects this is effectively unlimited — but for applications that write frequently, you should think about wear.

Calculating Write Life

  • Write every second: 100,000 / (60 × 60 × 24 × 365) ≈ 3.2 years before that byte fails
  • Write every minute: ~190 years — practically unlimited
  • Write every 10 minutes: over 1,900 years

For most configuration storage (writing settings only when the user changes them), wear is never a concern. For high-frequency data logging, consider using external flash memory instead.

Simple Wear Levelling

If you must write frequently to EEPROM, spread writes across multiple bytes rather than repeatedly writing the same byte. A simple approach for a counter:

// Use 10 bytes as a circular buffer for a wear-levelled counter
const int COUNTER_START = 0;
const int COUNTER_COUNT = 10;
int currentSlot = 0;

void incrementCounter() {
  currentSlot = (currentSlot + 1) % COUNTER_COUNT;
  EEPROM.update(COUNTER_START + currentSlot, counterValue);
}

This distributes writes 10× across multiple bytes, effectively multiplying the EEPROM’s life for that counter by 10.

Always Use EEPROM.update()

The single most impactful wear-reduction practice is using EEPROM.update() instead of EEPROM.write(). In many applications (configuration save on button press), the value being written is often the same as what is already stored. update() skips the write in that case, saving wear cycles.

Practical Examples

Remember Last LED State After Power Cut

#include <EEPROM.h>

const int LED_PIN = 13;
const int BTN_PIN = 2;
const int EEPROM_ADDR = 0;

bool ledState;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT_PULLUP);
  
  ledState = EEPROM.read(EEPROM_ADDR);
  if (ledState > 1) ledState = 0;  // Handle blank EEPROM
  digitalWrite(LED_PIN, ledState);
}

void loop() {
  if (digitalRead(BTN_PIN) == LOW) {
    delay(50);  // Debounce
    if (digitalRead(BTN_PIN) == LOW) {
      ledState = !ledState;
      digitalWrite(LED_PIN, ledState);
      EEPROM.update(EEPROM_ADDR, ledState);
      while (digitalRead(BTN_PIN) == LOW);  // Wait for release
    }
  }
}

Temperature Sensor Calibration Storage

#include <EEPROM.h>
#include <DHT.h>

struct CalibData {
  float tempOffset;
  float humOffset;
};

CalibData calib;

void loadCalibration() {
  EEPROM.get(0, calib);
  if (isnan(calib.tempOffset)) { calib.tempOffset = 0.0; }
  if (isnan(calib.humOffset))  { calib.humOffset = 0.0; }
}

float getCalibratedTemp(float raw) {
  return raw + calib.tempOffset;
}

Device Configuration Menu

A common pattern for configurable IoT devices:

  1. On boot, load all settings from EEPROM using EEPROM.get()
  2. If magic number is missing, apply factory defaults and save to EEPROM
  3. Provide a serial configuration menu to update settings
  4. On each setting change, call EEPROM.put() to persist immediately
  5. Next boot loads user configuration automatically
Recommended: Arduino Starter Kit with 170 Pages Project Book — Contains hands-on projects that naturally lead to EEPROM use for saving settings — a perfect companion resource for making your projects retain their configuration across power cycles.

Frequently Asked Questions

How do I clear or erase all EEPROM data on an Arduino?

Write 0xFF (255) to every EEPROM address to restore the blank factory state:

for (int i = 0; i < EEPROM.length(); i++) {
  EEPROM.write(i, 0xFF);
}

This is equivalent to “erasing” the EEPROM. It takes a few seconds to complete and uses one write cycle per byte.

Does uploading a new sketch erase the EEPROM?

No. Uploading a new Arduino sketch via the USB bootloader does NOT erase EEPROM. Only the Flash memory (where the sketch lives) is overwritten. EEPROM data persists across sketch uploads. This is by design — it lets you retain user settings when updating firmware. To intentionally clear EEPROM, run an erase sketch or use the AVRDUDE command with the -D flag removed (which causes a chip erase).

What is the difference between EEPROM.write() and EEPROM.update()?

write() always performs a physical write operation, which uses a wear cycle even if the value is already the same. update() reads the current byte first and only writes if the new value differs — saving a wear cycle when the value has not changed. Always use update() unless you have a specific reason to force a write.

Can I store floats and strings in EEPROM?

Yes. Use EEPROM.put(address, floatVar) to store a float (4 bytes). For strings, either store them as character arrays (char arrays) using put(), or write them byte by byte. The Arduino String class should not be stored directly due to its dynamic memory allocation — use fixed-size char arrays instead.

My EEPROM data seems correct sometimes but corrupted other times. What is wrong?

The most likely causes are: (1) Incorrect address calculation — writing a large struct beyond the EEPROM boundary silently wraps around or truncates. Always verify that address + sizeof(struct) does not exceed EEPROM.length(). (2) Power loss during a write — EEPROM writes take approximately 3.4 ms each. If power is lost during a write, the byte is corrupted. A magic number or checksum helps detect this on the next boot.

How does Arduino EEPROM compare to using an SD card?

EEPROM is simpler (no wiring, no library setup, no file system), faster for small data (microseconds vs milliseconds), and more reliable (no card removal issues, no FAT corruption). But it is tiny (1 KB vs gigabytes) and has a limited write endurance per byte. Use EEPROM for settings, calibration, and configuration; use an SD card for logging large amounts of data over time.

Arduino EEPROM is one of the most underutilised features available on every ATmega-based board. With just the built-in EEPROM library and the techniques in this tutorial — struct storage with put()/get(), magic number validation, and update() for wear reduction — you can build Arduino projects that remember their state across power cycles, hold user configuration reliably, and function like polished commercial products without a single extra component.

Shop Arduino Boards at Zbotic →

Tags: Arduino EEPROM, Arduino permanent storage, ATmega328P EEPROM, EEPROM tutorial, non-volatile memory, save data Arduino
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Arduino Finite State Machine: ...
blog arduino finite state machine writing cleaner code for complex projects 594663
blog bootloader burning on arduino fix bricked boards 594665
Bootloader Burning on Arduino:...

Related posts

Svg%3E
Read more

Arduino Batch Programming: Flash Multiple Boards Quickly

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Based Radar System with Ultrasonic Sensor

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Automatic Plant Monitor: Sunlight, Moisture, Temperature

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Lie Detector: GSR Sensor Polygraph Project

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Metal Detector: Build a Treasure Finder

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now