first version
This commit is contained in:
160
README.md
Normal file
160
README.md
Normal file
@@ -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 <Wire.h>
|
||||||
|
#include <RTClib.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
***
|
||||||
76
arduino_logic.ino
Normal file
76
arduino_logic.ino
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include <Wire.h>
|
||||||
|
#include <RTClib.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user