n the world of microcontrollers, data is typically lost the moment power is disconnected. But what if you need a device that remembers its count, even after being unplugged or during a power outage? This is where the power of EEPROM comes in. A digital counter that uses Arduino's built-in EEPROM is a brilliant project that demonstrates how to create a non-volatile memory system, perfect for applications like production line tallying, visitor counters, or inventory tracking that requires data persistence.
The core concept of this project is to combine a simple counting mechanism with memory that survives without power. Every time a button is pressed, the counter increments. The ingenious part is that this new value is immediately saved to the EEPROM. When the system is powered back on, it doesn't start from zero; it retrieves the last saved count from the EEPROM and continues from there, creating a robust and reliable counting system.
Components in Full DetailArduino Uno: The brain of the project. It handles button input, processes the logic, updates the display, and manages all read/write operations to the EEPROM.
- Arduino Uno: The brain of the project. It handles button input, processes the logic, updates the display, and manages all read/write operations to the EEPROM.
16x2 LCD Display: This is the primary output device. It displays the current count and any relevant messages. It requires 6 digital pins to interface with the Arduino.
- 16x2 LCD Display: This is the primary output device. It displays the current count and any relevant messages. It requires 6 digital pins to interface with the Arduino.
I2C LCD Module (Recommended): While optional, this small adapter is highly recommended. It simplifies wiring by reducing the number of required pins from 6 to just 2 (SDA and SCL) by using the I2C communication protocol.
- I2C LCD Module (Recommended): While optional, this small adapter is highly recommended. It simplifies wiring by reducing the number of required pins from 6 to just 2 (SDA and SCL) by using the I2C communication protocol.
Push Button: This is the input sensor. Each press of the button signals the Arduino to increment the counter. It is connected to a digital pin and is read as a digital input.
- Push Button: This is the input sensor. Each press of the button signals the Arduino to increment the counter. It is connected to a digital pin and is read as a digital input.
10kΩ Resistor: This is used as a pull-down resistor for the push button. It ensures that the Arduino's input pin is at a known LOW state (0V) when the button is not pressed, preventing a "floating" pin and ensuring reliable button detection.
- 10kΩ Resistor: This is used as a pull-down resistor for the push button. It ensures that the Arduino's input pin is at a known LOW state (0V) when the button is not pressed, preventing a "floating" pin and ensuring reliable button detection.
Breadboard and Jumper Wires: Used for creating the circuit connections without soldering, making the prototyping process easy and flexible.
- Breadboard and Jumper Wires: Used for creating the circuit connections without soldering, making the prototyping process easy and flexible.
The code is what brings intelligence and memory to the system. It uses the built-in EEPROM.h
library to interact with the non-volatile memory.
How the Code Works:
Initialization: In the setup()
function, the LCD is initialized, and the button pin is set as an input. The most critical step here is reading the last saved count from the EEPROM address (e.g., address 0) and loading it into the counter variable. This ensures the count persists across power cycles.
- Initialization: In the
setup()
function, the LCD is initialized, and the button pin is set as an input. The most critical step here is reading the last saved count from the EEPROM address (e.g., address 0) and loading it into the counter variable. This ensures the count persists across power cycles.
The Main Loop: The loop()
continuously checks the state of the push button.
Debouncing: When a button press is detected, the code implements a short delay to account for mechanical "bouncing, " ensuring a single press is registered as one count.
- Debouncing: When a button press is detected, the code implements a short delay to account for mechanical "bouncing, " ensuring a single press is registered as one count.
Increment and Save: After a valid press, the counter variable is incremented. Crucially, this new value is immediately written to the EEPROM using EEPROM.write()
.
- Increment and Save: After a valid press, the counter variable is incremented. Crucially, this new value is immediately written to the EEPROM using
EEPROM.write()
.
Update Display: The LCD is updated to show the new count.
- Update Display: The LCD is updated to show the new count.
- The Main Loop: The
loop()
continuously checks the state of the push button.Debouncing: When a button press is detected, the code implements a short delay to account for mechanical "bouncing, " ensuring a single press is registered as one count.Increment and Save: After a valid press, the counter variable is incremented. Crucially, this new value is immediately written to the EEPROM usingEEPROM.write()
.Update Display: The LCD is updated to show the new count.
EEPROM Limitations: The code must be mindful that the EEPROM has a finite write endurance (about 100, 000 writes per cell). For a high-traffic counter, more advanced wear-leveling logic would be needed.
- EEPROM Limitations: The code must be mindful that the EEPROM has a finite write endurance (about 100, 000 writes per cell). For a high-traffic counter, more advanced wear-leveling logic would be needed.
cpp
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int buttonPin = 2; // Push button connected to digital pin 2
int count = 0; // Counter variable
int buttonState = 0; // Current state of the button
int lastButtonState = LOW; // Previous state of the button
// EEPROM address where the count is stored
const int eepromAddr = 0;
void setup() {
lcd.init();
lcd.backlight();
lcd.print("Counter Value:");
pinMode(buttonPin, INPUT);
// Read the last saved count from EEPROM on startup
count = EEPROM.read(eepromAddr);
lcd.setCursor(0, 1);
lcd.print(count);
}
void loop() {
// Read the button state
buttonState = digitalRead(buttonPin);
// Check if the button state has changed (from low to high)
if (buttonState != lastButtonState) {
if (buttonState == HIGH) {
// If the button is pressed, increment the counter
count++;
// Save the new count to EEPROM immediately
EEPROM.write(eepromAddr, count);
// Update the LCD display
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the previous number
lcd.setCursor(0, 1);
lcd.print(count);
}
// A small delay to avoid bouncing
delay(50);
}
// Save the current state as the last state for the next loop
lastButtonState = buttonState;
}
By building this project, you move beyond simple volatile circuits and create a device with true memory. This foundational knowledge of EEPROM is a gateway to more complex data-logging projects and is a cornerstone of reliable embedded systems design.
Comments