The task is to build a human counter system using a microcontroller with two push buttons, one to increment and one to decrement the count, and display the value on a serial terminal (e.g., PuTTY or Arduino IDE).
Requirements
Why Use EEPROM?
EEPROM is a non-volatile memory that retains data without power, making it ideal for storing the count value so it remains available even after a restart.
Connect two push-button switches to GPIO pins using either a pull-up or pull-down configuration for reliable input detection.
This task can be implemented on the following microcontrollers:
We are using the ESP32 DevKitC v4 development board and programming it using the Arduino IDE.
ESP32 does not have a real EEPROM chip inside. Instead, part of its Flash memory is used to simulate EEPROM behavior.
Switch Interfacing with an internal pullup resistor
1) Increment switch → GPIO Pin 15
2)Decrement Switch → GPIO Pin 16
Circuit Connection

#include <EEPROM.h>
#define INC_BUTTON_PIN 15 // increment button (active LOW, INPUT_PULLUP)
#define DEC_BUTTON_PIN 16 // decrement button (active LOW, INPUT_PULLUP)
// Map switches to indices 0,1 for the debounce arrays (exact pattern you gave)
uint8_t switchPins[2] = { INC_BUTTON_PIN, DEC_BUTTON_PIN };
static const int EEPROM_BYTES = 4;
static const int COUNT_ADDR = 0; // always write/read the 32-bit count at 0
uint32_t humanCount = 0;
uint8_t debounceDelay = 50; // ms
unsigned long lastDebounceTime[2] = { 0, 0 }; // one per switch
uint8_t lastButtonState[2] = { HIGH, HIGH }; // previous sampled state
uint8_t ButtonState[2] = { HIGH, HIGH }; // debounced state
// Check if a button has been pressed with debouncing
bool isButtonPressed(uint8_t switchIndex) {
int reading = digitalRead(switchPins[switchIndex]);
// If the button state has changed, reset the debounce timer
if (reading != lastButtonState[switchIndex]) {
lastDebounceTime[switchIndex] = millis();
}
lastButtonState[switchIndex] = reading;
// If the state has remained stable for the debounce period (50 ms)
if ((millis() - lastDebounceTime[switchIndex]) > debounceDelay) {
if (reading != ButtonState[switchIndex]) {
ButtonState[switchIndex] = reading;
// Active LOW → pressed when LOW
if (ButtonState[switchIndex] == LOW) {
return true; // valid press detected
}
}
}
return false; // no valid press detected
}
void saveCount() {
EEPROM.put(COUNT_ADDR, humanCount); // write 4 bytes at address 0
EEPROM.commit(); // persist to flash on ESP32
}
void loadCount() {
uint32_t val;
EEPROM.get(COUNT_ADDR, val);
// Fresh-erased bytes read as 0xFFFFFFFF
if (val == 0xFFFFFFFFu) {
humanCount = 0;
saveCount(); // initialize persistent storage
} else {
humanCount = val;
}
}
void setup() {
Serial.begin(115200);
// Start EEPROM emulation with 4 bytes total
EEPROM.begin(EEPROM_BYTES);
// Buttons with internal pull-ups (active LOW)
pinMode(INC_BUTTON_PIN, INPUT_PULLUP);
pinMode(DEC_BUTTON_PIN, INPUT_PULLUP);
loadCount();
Serial.println("Human Counter System Started!");
Serial.print("Initial Count: ");
Serial.println(humanCount);
}
void loop() {
// Increment count
if (isButtonPressed(0)) { // index 0 → INC_BUTTON_PIN
humanCount++;
saveCount(); // write on every valid press (no 100 ms throttle)
Serial.print("Count Incremented: ");
Serial.println(humanCount);
}
// Decrement count
if (isButtonPressed(1)) { // index 1 → DEC_BUTTON_PIN
if (humanCount > 0) {
humanCount--;
saveCount();
Serial.print("Count Decremented: ");
Serial.println(humanCount);
}
}
}
isButtonPressed() to increment or decrement the counter, saves the updated count, and prints it.humanCount value to EEPROM address 0 and commits it to Flash for permanent storage.EEPROM.begin(8000)) can corrupt other Flash data or cause runtime errors.EEPROM.commit() only when values actually change.EEPROM.commit() after writingWe are using the Arduino UNO development board and programming it using the Arduino IDE.
Switch Interfacing with an internal pullup resistor
1) Increment switch → GPIO Pin 2
2)Decrement Switch → GPIO Pin 3
Circuit Connection

We are going to use EEPROM.h library to implement this task. In Arduino UNO, there is a separate 1KB EEPROM chip available.
#include <EEPROM.h>
// Pin Definitions
#define INC_BUTTON_PIN 2 // Button to increment count
#define DEC_BUTTON_PIN 3 // Button to decrement count
// Variables
int humanCount; // Current human count
const int eepromAddress = 0; // EEPROM address to store the count
void setup() {
Serial.begin(9600);
initiateCount();
// Configure button pins
pinMode(INC_BUTTON_PIN, INPUT_PULLUP);
pinMode(DEC_BUTTON_PIN, INPUT_PULLUP);
Serial.println("Human Counter System Started!");
Serial.print("Initial Count: ");
Serial.println(humanCount);
}
void loop() {
static bool incButtonState = HIGH;
static bool decButtonState = HIGH;
// Read button states with debounce
bool incButtonPressed = debounceButton(INC_BUTTON_PIN, incButtonState);
bool decButtonPressed = debounceButton(DEC_BUTTON_PIN, decButtonState);
// Increment count
if (incButtonPressed) {
humanCount++;
updateEEPROM();
Serial.print("Count Incremented: ");
Serial.println(humanCount);
}
// Decrement count
if (decButtonPressed && humanCount > 0) {
humanCount--;
updateEEPROM();
Serial.print("Count Decremented: ");
Serial.println(humanCount);
}
}
bool debounceButton(int pin, bool &lastState) {
bool currentState = digitalRead(pin);
if (lastState != currentState) {
delay(50); // Debounce delay
if (digitalRead(pin) == currentState) {
lastState = currentState;
return currentState == LOW; // Return true if button is pressed
}
}
return false;
}
void updateEEPROM() {
EEPROM.write(eepromAddress, humanCount);
}
void initiateCount() {
humanCount = EEPROM.read(eepromAddress);
if (humanCount == 255) {
humanCount = 0;
updateEEPROM();
}
}setup();loop();debounceButton();updateEEPROM();initiateCount();