// https://forum.arduino.cc/t/sequencing-counter-save-count-after-power-outage/1414317/
// Reads EEPROM address 0 for data < 255.
// Starts counter at stored value.
// Counts button short-presses (< 500ms).
// Stores single byte in EEPROM address with long press (> 1000ms).
// Terminates program
#include <EEPROM.h>
byte address = 0, count = 0;
byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};
byte button = 2;
unsigned long shortPressTime = 500, longPressTime = 1000;
unsigned long timer, timeout = 50, timePressed, timeReleased;
bool buttonRead, buttonReadOld, buttonState;
bool shortPressed, longPressed, isPressed;
void setup() {
Serial.begin(115200);
instructions();
pinMode(button, INPUT_PULLUP); // configure button pin for INPUT using internal pullup resistor
for (byte i = 0; i < 8; i++)
pinMode(ledPin[i], OUTPUT); // configure LED pins for output
readEEPROM(); // read EEPROM address, display if not 0 or 255
}
void loop() {
readButton(); // read button press
}
void readButton() {
buttonRead = digitalRead(button); // store button state
if (buttonRead != buttonReadOld) { // when button state changes
timer = millis(); // ...start a timer
buttonReadOld = buttonRead; // ... store button reading
}
if ((millis() - timer) > timeout) { // if button change occured longer than debounce timeout...
if (buttonState == HIGH && buttonReadOld == LOW) { // button PRESSED
timePressed = millis(); // button PRESSED time
isPressed = true; // set button isPressed flag
shortPressed = true; // every button press starts as a short press
longPressed = false; // clear long press flag
}
if (buttonState == LOW && buttonReadOld == HIGH) { // button RELEASED
isPressed = false; // clear button isPressed flag
if (shortPressed) { // only count short presses
shortPressed = false; // clear flag
updateLEDs(++count); // increment count and displayed on LEDs
}
}
if ((isPressed == true) && (longPressed == false)) { // button pressed and held
unsigned long ispressingDuration = millis() - timePressed; // duration of press
if (ispressingDuration > longPressTime ) { // if it qualifies as long press
storeValue(count); // store value in EEPROM // store value, announce storage, exit
}
}
buttonState = buttonRead; // update button state
}
}
void updateLEDs(int count) {
// for (byte i = 0; i < 10; i++) { // count ten bits OOPS... should not be ten
for (byte i = 0; i < 8; i++) { // count eight bits
bool ledBit = bitRead(count, i); // test each bit in "count"
digitalWrite(ledPin[i], bitRead(count, i)); // set LED to bit value in "count"
// https://docs.arduino.cc/language-reference/en/functions/bits-and-bytes/bitRead/
}
}
void storeValue (int data) {
EEPROM.write(address, data);
Serial.print("EEPROM (address: ");
Serial.print(address);
Serial.print(" value: ");
Serial.print(EEPROM.read(address));
Serial.print(") stored. ");
Serial.println("LEDs cleared. Program terminated.");
Serial.println("Press RESET to recall data from EEPROM.");
// for (byte i = 0; i < 10; i++) // oops... should not be ten bits/LEDs
for (byte i = 0; i < 8; i++) // eight bits/LEDs
digitalWrite(ledPin[i], LOW); // all LEDs off
while (1) {}; // terminate program
// https://docs.arduino.cc/learn/programming/eeprom-guide/
// EEPROM.write() takes 3.3ms.
// EEPROM memory has 100,000 write/erase cycles.
// CAREFUL how often you write to it.
}
void readEEPROM() {
Serial.print("Data read from EEPROM (address: ");
Serial.print(address);
Serial.print(" value: ");
count = EEPROM.read(address);
if (count == 255) // addresses containing 255 never have been writen to.
count = 0;
else
updateLEDs(count); // show current EEPROM value stored at address
Serial.print(count);
Serial.println(")");
}
void instructions() {
Serial.println("Short press (< 1000ms) increments count.");
Serial.println("Long press (> 1000ms) stores value and terminates program.");
Serial.println("Press RESET to restore EEPROM value.");
}