From a358f5709e8358233778e2e32748c0110329acf5 Mon Sep 17 00:00:00 2001 From: dtoro Date: Wed, 18 Feb 2026 20:53:27 +0100 Subject: [PATCH] first version --- README.md | 160 ++++++++++++++++++++++++++++++++++++++++++++++ arduino_logic.ino | 76 ++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 README.md create mode 100644 arduino_logic.ino diff --git a/README.md b/README.md new file mode 100644 index 0000000..f41202f --- /dev/null +++ b/README.md @@ -0,0 +1,160 @@ +# Arduino Powerbank Keep-Alive + Daily Reset Counter + +This project uses an Arduino, a DS3231 real-time clock (RTC), buttons, LEDs, and a resistor to: + +- Keep a USB power bank **awake** by periodically pulsing a load on a digital pin. +- Control 4 LEDs with 4 buttons (toggle on/off). +- Remember LED states across power loss using EEPROM. +- Automatically reset all LEDs every day at 12:00 PM. + +*** + +### Features + +- **Silent keep-alive:** +Periodic pulse on a resistor connected to pin 6 so power banks don’t auto-shutoff. +- **4 independent channels:** +4 buttons control 4 LEDs (via a mapping array), each toggling its own state. +- **Persistent state:** +LED on/off states are stored in EEPROM and restored on startup. +- **Daily auto reset:** +At exactly 12:00:00 PM (noon), all LED states are cleared and saved as off. + +*** + +### Hardware Requirements + +- Arduino (e.g., Uno, Nano, Pro Mini) +- DS3231 RTC module (connected via I²C: SDA/SCL) +- 4 momentary push buttons +- 4 LEDs with appropriate current-limiting resistors +- 1 additional resistor as keep-alive load (between pin 6 and GND) +- USB power bank (optional but typical use case) +- Jumper wires and breadboard or PCB + +*** + +### Pinout + +- Buttons (with internal pullups): + - Button 1 → pin 2 + - Button 2 → pin 3 + - Button 3 → pin 4 + - Button 4 → pin 5 +- LEDs: + - LED 1 → pin 8 + - LED 2 → pin 9 + - LED 3 → pin 10 + - LED 4 → pin 11 +- Keep-alive resistor: + - One side of resistor → pin 6 + - Other side of resistor → GND +- RTC (DS3231): + - SDA → Arduino SDA (A4 on Uno) + - SCL → Arduino SCL (A5 on Uno) + - VCC → 5 V + - GND → GND +- Onboard LED (pin 13) is explicitly disabled. + +*** + +### Libraries Used + +Install the following via the Arduino Library Manager: + +- **RTClib** (by Adafruit) +- **EEPROM** (included with Arduino core) +- **Wire** (included with Arduino core) + +Include them in your sketch: + +```cpp +#include +#include +#include +``` + + +*** + +### How It Works + +1. **Setup phase** + - Initializes the DS3231 RTC. + - Sets pin 6 LOW and disables the onboard LED on pin 13. + - Configures button pins with `INPUT_PULLUP`. + - Configures LED pins as outputs and restores each LED state from EEPROM. +2. **Keep-alive pulses** + - Every `pulseInterval` milliseconds, pin 6 goes HIGH for `pulseDuration` milliseconds, then returns LOW. + - Default values in the code: + - `pulseDuration = 800` + - `pulseInterval = 10000` + - Adjust these if your power bank requires a different pattern. +3. **Button handling** + - Buttons are active LOW (because of `INPUT_PULLUP`). + - On press: + - Debounces with a 50 ms delay. + - Uses `ledMap[]` to map button index to a specific LED index. + - Toggles that LED’s state, writes it to EEPROM, and waits for the button to be released. + +Example mapping from code: + +```cpp +const int ledMap[] = {3, 1, 0, 2}; +``` + +This means: + - Button on pin 2 controls LED index 3 (pin 11) + - Button on pin 3 controls LED index 1 (pin 9) + - Button on pin 4 controls LED index 0 (pin 8) + - Button on pin 5 controls LED index 2 (pin 10) +4. **Daily reset at 12:00 PM** + - Reads current time from the DS3231 each loop. + - When time is exactly 12:00:00: + - If reset not yet done today, all LEDs are turned OFF and EEPROM is updated. + - `resetPerformed` flag prevents multiple resets within the same second. + - When time is no longer 12:00:00, `resetPerformed` resets to `false` for the next day. + +*** + +### EEPROM Usage + +- EEPROM addresses 0–3 store the 4 LED states (`true`/`false` as bytes 1/0). +- The code uses `EEPROM.update(address, value)` to avoid unnecessary writes. + +*** + +### Setup Instructions + +1. Build the circuit according to the pinout. +2. Connect the DS3231 and set the correct time once (e.g., using an example sketch from RTClib). +3. Upload this sketch to the Arduino. +4. Power the Arduino from your USB power bank. +5. Press buttons to toggle LEDs; states will persist after power loss. +6. At 12:00 PM every day, all LEDs will automatically reset to OFF. + +*** + +### Configuration + +You can tweak these constants: + +```cpp +const int pulseDuration = 800; // ms HIGH time +const int pulseInterval = 10000; // ms between pulses +``` + +- Increase `pulseDuration` if the power bank needs a stronger signal. +- Decrease `pulseInterval` if it shuts off too quickly. + +*** + +### Example Use Case + +Use this as a simple daily habit tracker powered by a USB power bank: + +- Each LED represents a daily task (e.g., exercise, reading). +- Press the corresponding button when done; LED turns on and stays on. +- At noon, all LEDs reset, ready for the next day, while the keep-alive pulse keeps the power bank from sleeping. + +*** diff --git a/arduino_logic.ino b/arduino_logic.ino new file mode 100644 index 0000000..d7f007f --- /dev/null +++ b/arduino_logic.ino @@ -0,0 +1,76 @@ +#include +#include +#include + +RTC_DS3231 rtc; + +const int buttonPins[] = {2, 3, 4, 5}; +const int ledPins[] = {8, 9, 10, 11}; +const int ledMap[] = {3, 1, 0, 2}; +const int resistorPin = 6; // RESISTOR GOES HERE (Pin 6 to GND) + +bool ledState[] = {false, false, false, false}; +bool resetPerformed = false; +unsigned long lastKeepAlive = 0; +const int pulseDuration = 800; // 0.2s is usually enough to reset the timer +const int pulseInterval = 10000; // 20s interval (test if your power bank handles this) + +void setup() { + rtc.begin(); + + // Ensure the resistor pin starts LOW (off) + pinMode(resistorPin, OUTPUT); + digitalWrite(resistorPin, LOW); + + // Disable the onboard LED explicitly + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + + for (int i = 0; i < 4; i++) { + pinMode(buttonPins[i], INPUT_PULLUP); + pinMode(ledPins[i], OUTPUT); + ledState[i] = EEPROM.read(i); + digitalWrite(ledPins[i], ledState[i] ? HIGH : LOW); + } +} + +void loop() { + DateTime now = rtc.now(); + unsigned long currentMillis = millis(); + + // --- 1. SILENT KEEP-ALIVE (PIN 6 ONLY) --- + if (currentMillis - lastKeepAlive > pulseInterval) { + digitalWrite(resistorPin, HIGH); + + if (currentMillis - lastKeepAlive > (pulseInterval + pulseDuration)) { + digitalWrite(resistorPin, LOW); + lastKeepAlive = currentMillis; + } + } + + // --- 2. BUTTONS --- + for (int i = 0; i < 4; i++) { + if (digitalRead(buttonPins[i]) == LOW) { + delay(50); + int targetLed = ledMap[i]; + ledState[targetLed] = !ledState[targetLed]; + digitalWrite(ledPins[targetLed], ledState[targetLed] ? HIGH : LOW); + EEPROM.update(targetLed, ledState[targetLed]); + while(digitalRead(buttonPins[i]) == LOW); + } + } + + // --- 3. DAILY RESET (12:00 PM) --- + if (now.hour() == 12 && now.minute() == 0 && now.second() == 0) { + if (!resetPerformed) { + for (int k = 0; k < 4; k++) { + ledState[k] = false; + digitalWrite(ledPins[k], LOW); + EEPROM.update(k, false); + } + resetPerformed = true; + } + } else { + resetPerformed = false; + } +}