#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
// Initialize RTC and LCD
RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 columns, 2 rows
// Alarm time (initially set to an invalid value)
int alarmHour = -1; // Will be set by user input
int alarmMinute = -1; // Will be set by user input
// Pins
const int buzzerPin = 9;
const int ledPin = 11;
// Alarm state (whether the alarm is ringing or not)
bool alarmRinging = false;
void setup() {
// Initialize the serial monitor for input
Serial.begin(9600);
while (!Serial);
// Initialize the RTC
if (!rtc.begin()) {
lcd.print("RTC not found");
while (1);
}
// Initialize the LCD
lcd.begin(16, 2);
lcd.backlight();
// Set up pin modes
pinMode(buzzerPin, OUTPUT);
pinMode(ledPin, OUTPUT);
// Display a welcome message
lcd.clear();
lcd.print("Alarm Clock");
delay(2000);
// Ask for alarm time input via serial
lcd.clear();
lcd.print("Set Alarm Time");
lcd.setCursor(0, 1);
lcd.print("HH:MM");
delay(2000);
// Prompt user to set the alarm time through serial
Serial.println("Enter alarm time in HH:MM format (e.g., 07:30):");
}
void loop() {
// Read current time from the RTC
DateTime now = rtc.now();
// Display the current time on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(now.hour(), DEC);
lcd.print(":");
lcd.print(now.minute(), DEC);
lcd.print(":");
lcd.print(now.second(), DEC);
// Check if the alarm time has been set
if (alarmHour != -1 && alarmMinute != -1) {
// Check if the current time matches the alarm time
if (now.hour() == alarmHour && now.minute() == alarmMinute && now.second() == 0) {
triggerAlarm();
}
}
// Listen for user input on the serial monitor to set alarm time or turn off the alarm
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n'); // Read input from serial
input.trim(); // Remove any extra spaces or newlines
// Check if the input is in the correct format (HH:MM) to set alarm time
if (input.length() == 5 && input[2] == ':') {
int hour = input.substring(0, 2).toInt();
int minute = input.substring(3, 5).toInt();
if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60) {
alarmHour = hour;
alarmMinute = minute;
// Confirm the new alarm time
lcd.clear();
lcd.print("Alarm Set to:");
lcd.setCursor(0, 1);
lcd.print(alarmHour);
lcd.print(":");
lcd.print(alarmMinute);
delay(2000);
}
else {
// Invalid time input
lcd.clear();
lcd.print("Invalid time");
delay(1000);
}
}
// Check if the user wants to turn off the alarm
else if (input.equalsIgnoreCase("off") && alarmRinging) {
stopAlarm();
}
else {
// Invalid input
lcd.clear();
lcd.print("Invalid input");
delay(1000);
}
}
delay(1000);
}
void triggerAlarm() {
// If the alarm is already ringing, do nothing
if (alarmRinging) return;
// Set alarm state to ringing
alarmRinging = true;
// Trigger buzzer and LED
digitalWrite(buzzerPin, HIGH); // Turn on buzzer
digitalWrite(ledPin, HIGH); // Turn on LED
lcd.clear();
lcd.print("ALARM RINGING!");
// Display message to user for turning off the alarm
lcd.setCursor(0, 1);
lcd.print("Type 'off' to stop");
// Print message to serial monitor
Serial.println("ALARM is ringing! Type 'off' in the serial monitor to stop the alarm.");
// No delay here. The alarm will keep ringing until the user stops it.
}
void stopAlarm() {
// Stop buzzer and LED
digitalWrite(buzzerPin, LOW);
digitalWrite(ledPin, LOW);
// Reset the alarm state
alarmRinging = false;
// Clear the LCD
lcd.clear();
lcd.print("Alarm Off");
delay(2000);
}