RTC Alarm Clock
ESP32 DevKit (WROOM-32)·Arduino C++·Updated Jul 27, 2026·by FluxBench TeamIncludes Lab + Schematic
A real alarm clock built on the DS3231 real-time clock: an SSD1306 OLED shows the date, big zero-padded HH:MM:SS time and the alarm status, and a piezo buzzer on GPIO 4 beeps at 1600 Hz when the alarm fires. The simulator RTC starts at 12:00:00, so the alarm (12:00:15) rings 15 seconds after you press Run — then click the bench push button (GPIO 14) to snooze it for 20 seconds, or click it while quiet to toggle the alarm on/off. Comments in the sketch show the two lines to change for real hardware: set the RTC from the compile time, and use a 5-minute snooze.
sketch.ino
// RTC Alarm Clock - DS3231 real-time clock, OLED face, buzzer + snooze button
// ESP32 DevKit v1. DS3231 @0x68 and SSD1306 @0x3C share the I2C bus
// (SDA=21, SCL=22). Buzzer on GPIO 4, snooze/enable button on GPIO 14.
//
// In the Lab simulator the DS3231 starts at 12:00:00, so the demo alarm is
// set for 12:00:15 - it rings 15 seconds after you press Run. While it rings,
// click the bench button to snooze (+20 s). When it is quiet, the button
// toggles the alarm on/off. On real hardware you would set alarmHour/alarmMin
// to a real wake-up time and let rtc.adjust() sync the clock once.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#define BUZZER_PIN 4
#define SNOOZE_PIN 14
RTC_DS3231 rtc;
Adafruit_SSD1306 display(128, 64, &Wire, -1);
// Demo alarm time (simulator clock starts at 12:00:00)
int alarmHour = 12;
int alarmMinute = 0;
int alarmSecond = 15;
bool alarmEnabled = true;
bool ringing = false;
bool beepOn = false;
unsigned long lastBeepToggle = 0;
unsigned long lastDraw = 0;
int lastButton = HIGH;
long snoozeUntil = -1; // unixtime when a snooze ends (-1 = none)
void startRinging() {
ringing = true;
Serial.println("ALARM! Press the button to snooze (+20 s).");
}
void stopRinging() {
ringing = false;
beepOn = false;
noTone(BUZZER_PIN);
}
void setup() {
Serial.begin(115200);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(SNOOZE_PIN, INPUT_PULLUP);
Wire.begin();
rtc.begin();
// On real hardware, uncomment once to set the clock from build time:
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
Serial.println("RTC Alarm Clock ready - alarm set for 12:00:15");
}
void loop() {
DateTime now = rtc.now();
long t = now.unixtime();
// ---- alarm trigger ----
bool atAlarm = (now.hour() == alarmHour && now.minute() == alarmMinute && now.second() == alarmSecond);
bool atSnooze = (snoozeUntil >= 0 && t >= snoozeUntil);
if (alarmEnabled && !ringing && (atAlarm || atSnooze)) {
snoozeUntil = -1;
startRinging();
}
// ---- button: snooze while ringing, enable/disable while quiet ----
int btn = digitalRead(SNOOZE_PIN);
if (btn == LOW && lastButton == HIGH) { // falling edge = press
if (ringing) {
stopRinging();
snoozeUntil = t + 20; // snooze 20 s (use +300 for 5 min on hardware)
Serial.println("Snoozed for 20 seconds...");
} else {
alarmEnabled = !alarmEnabled;
if (!alarmEnabled) snoozeUntil = -1;
Serial.print("Alarm ");
Serial.println(alarmEnabled ? "ENABLED" : "DISABLED");
}
}
lastButton = btn;
// ---- beeper: 1600 Hz, 250 ms on / 250 ms off while ringing ----
if (ringing && millis() - lastBeepToggle >= 250) {
lastBeepToggle = millis();
beepOn = !beepOn;
if (beepOn) tone(BUZZER_PIN, 1600);
else noTone(BUZZER_PIN);
}
// ---- OLED clock face, redrawn 4x per second ----
if (millis() - lastDraw >= 250) {
lastDraw = millis();
char buf[16];
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
sprintf(buf, "%04d-%02d-%02d", now.year(), now.month(), now.day());
display.print(buf);
display.setTextSize(2);
display.setCursor(16, 20);
sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
display.print(buf);
display.setTextSize(1);
display.setCursor(0, 48);
if (ringing) {
display.print("WAKE UP! btn=snooze");
} else if (snoozeUntil >= 0) {
sprintf(buf, "Snooze %lds", snoozeUntil - t);
display.print("Zzz... ");
display.print(buf);
} else if (alarmEnabled) {
sprintf(buf, "Alarm %02d:%02d:%02d", alarmHour, alarmMinute, alarmSecond);
display.print(buf);
} else {
display.print("Alarm off");
}
display.display();
}
delay(20);
}Built with FluxBench.AI — the AI workbench for embedded projects.