#include <Wire.
h>
#include "RTClib.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
// === RTC & OLED Setup ===
RTC_DS3231 rtc;
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// === Pin Configuration for ESP32 ===
#define btnHour 25
#define btnMin 26
#define btnSwitch 27
#define btnStop 14
#define buzzer 13
#define I2C_SDA 21
#define I2C_SCL 22
// === LED Pins ===
#define LED1 17
#define LED2 16
#define LED3 4
#define LED4 2
int ledPins[4] = {LED1, LED2, LED3, LED4};
// === Alarm Variables ===
const int maxAlarms = 4;
int alarmHour[maxAlarms];
int alarmMin[maxAlarms];
bool alarmTriggered[maxAlarms] = {false, false, false, false};
int currentAlarm = 0;
unsigned long alarmStartTime = 0;
// === Debounce Variables ===
const unsigned long debounceDelay = 200;
unsigned long lastDebounceHour = 0;
unsigned long lastDebounceMin = 0;
unsigned long lastDebounceSwitch = 0;
unsigned long lastDebounceStop = 0;
bool lastBtnHour = HIGH, lastBtnMin = HIGH, lastBtnSwitch = HIGH;
// === EEPROM Constants ===
#define EEPROM_SIZE 32
void saveAlarmsToEEPROM() {
for (int i = 0; i < maxAlarms; i++) {
EEPROM.write(i * 2, alarmHour[i]);
EEPROM.write(i * 2 + 1, alarmMin[i]);
}
EEPROM.commit();
}
void setup() {
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
rtc.begin();
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED not found");
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("ESP32 Alarm Clock");
display.display();
delay(2000);
pinMode(btnHour, INPUT_PULLUP);
pinMode(btnMin, INPUT_PULLUP);
pinMode(btnSwitch, INPUT_PULLUP);
pinMode(btnStop, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
digitalWrite(buzzer, LOW);
// Set up LED pins
for (int i = 0; i < maxAlarms; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
EEPROM.begin(EEPROM_SIZE);
for (int i = 0; i < maxAlarms; i++) {
alarmHour[i] = EEPROM.read(i * 2);
alarmMin[i] = EEPROM.read(i * 2 + 1);
if (alarmHour[i] > 23) alarmHour[i] = 0;
if (alarmMin[i] > 59) alarmMin[i] = 0;
}
}
void loop() {
DateTime now = rtc.now();
updateOLED(now);
bool stateHour = digitalRead(btnHour);
bool stateMin = digitalRead(btnMin);
bool stateSwitch = digitalRead(btnSwitch);
bool stateStop = digitalRead(btnStop);
if (stateHour == LOW && lastBtnHour == HIGH && millis() - lastDebounceHour >
debounceDelay) {
alarmHour[currentAlarm] = (alarmHour[currentAlarm] + 1) % 24;
saveAlarmsToEEPROM();
Serial.print("Alarm hour updated: ");
Serial.println(alarmHour[currentAlarm]);
lastDebounceHour = millis();
}
if (stateMin == LOW && lastBtnMin == HIGH && millis() - lastDebounceMin >
debounceDelay) {
alarmMin[currentAlarm] = (alarmMin[currentAlarm] + 1) % 60;
saveAlarmsToEEPROM();
Serial.print("Alarm minute updated: ");
Serial.println(alarmMin[currentAlarm]);
lastDebounceMin = millis();
}
if (stateSwitch == LOW && lastBtnSwitch == HIGH && millis() - lastDebounceSwitch
> debounceDelay) {
currentAlarm = (currentAlarm + 1) % maxAlarms;
Serial.print("Switched to alarm: ");
Serial.println(currentAlarm + 1);
lastDebounceSwitch = millis();
}
if (stateStop == LOW && millis() - lastDebounceStop > debounceDelay) {
Serial.println("Stop button pressed — BUZZER OFF");
digitalWrite(buzzer, LOW);
alarmStartTime = 0;
for (int i = 0; i < maxAlarms; i++) {
alarmTriggered[i] = false;
digitalWrite(ledPins[i], LOW); // Turn off all LEDs
}
lastDebounceStop = millis();
}
lastBtnHour = stateHour;
lastBtnMin = stateMin;
lastBtnSwitch = stateSwitch;
for (int i = 0; i < maxAlarms; i++) {
if (now.hour() == alarmHour[i] && now.minute() == alarmMin[i] && now.second()
== 0 && !alarmTriggered[i]) {
digitalWrite(buzzer, HIGH);
digitalWrite(ledPins[i], HIGH); // Turn on corresponding LED
alarmTriggered[i] = true;
alarmStartTime = millis();
Serial.print("Alarm "); Serial.print(i + 1); Serial.println(" Triggered!
BUZZER & LED ON");
}
}
if (digitalRead(buzzer) == HIGH && millis() - alarmStartTime >= 10000) {
digitalWrite(buzzer, LOW);
for (int i = 0; i < maxAlarms; i++) {
digitalWrite(ledPins[i], LOW); // Turn off all LEDs
alarmTriggered[i] = false;
}
Serial.println("Buzzer auto-stopped after 10s");
}
delay(200);
}
void updateOLED(DateTime now) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Time: ");
print2Digits(display, now.hour());
display.print(":");
print2Digits(display, now.minute());
display.print(":");
print2Digits(display, now.second());
display.setCursor(0, 16);
display.print("Alarm "); display.print(currentAlarm + 1); display.print(": ");
print2Digits(display, alarmHour[currentAlarm]);
display.print(":");
print2Digits(display, alarmMin[currentAlarm]);
display.display();
}
void print2Digits(Adafruit_SSD1306 &d, int num) {
if (num < 10) d.print("0");
d.print(num);
}