#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define MODEBUTTON_PIN 2
#define BELLBUTTON_PIN 3
#define potPin A0
#define MODE_LED_PIN 7
#define BUZZER_PIN 8
#define RELAY_PIN 9
int mode = 1;
int debug = 1;
bool alarmTriggered = false; // Variable to track whether the alarm has been triggered
String msg;
String mode_Msg;
int ringDuration = 100; // how long to ring
const int numAlarms = 14; // array length + 1
const int alarmTimes[numAlarms][2] = {
{10, 40} // 0 - 10:40 AM Prayer Starts
, {10, 50} // 1 - 10:50 AM 1st period
, {11, 35} // 2 - 11:35 AM 2nd period
, {12, 15} // 3 - 12:15 AM 3rd period
, {12, 55} // 4 - 12:55 AM 4th period
, {13, 35} // 5 - 1:35 PM Tiffin / RECESS
, {14, 15} // 6 - 2:15 PM 5th period
, {14, 50} // 7 - 2:50 PM 6th period
, {15, 25} // 9 - 3:25 PM 7th period
, {16, 0} // 10 - 4:00 PM 8th period
, {16, 30} // 11 - 4:30 PM SCHOOL Ends
, {01, 51} // 12 -- custom for debug
, {01,00 } // 13 -- custom for debug
};
void setup() {
Serial.begin(9600);
lcd.begin(16, 2); lcd.backlight();
Wire.begin();
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
pinMode(MODEBUTTON_PIN, INPUT_PULLUP);
pinMode(BELLBUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(MODE_LED_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
tone(BUZZER_PIN, 3900, 370);
}
void loop() {
DateTime now = rtc.now();
//--------Clock function start ----------------------
int currentHour = now.hour(); int currentMin = now.minute(); int currentSec = now.second();
int currentDay = now.day(); int currentMonth = now.month(); int currentYear = now.year();
int temp = rtc.getTemperature();
int dayOfWeek = now.dayOfTheWeek(); //index to match a representation where Sunday is 1.
// if(debug){Serial.print(dayOfWeek);}
//--------Clock function end ----------------------
//---- LCD TOP ROW ----starts
lcd.clear(); lcd.setCursor(0, 0);// clear screen & start at upper row
printLcd(0,0, String(currentHour)); printLcd(2,0,":");
printLcd(3,0,String(currentMin)); printLcd(5,0,":");
printLcd(6,0,String(currentSec));
printLcd(9,0,String(currentDay) + monthToString(currentMonth) + String(currentYear % 100));
//---- LCD TOP ROW ----ENDS
//----- LCD Bottom row ------start
printLcd(0, 1, dayToString(dayOfWeek));
printLcd(4, 1, msg);
printLcd(9, 1, String(temp));
printLcd(11, 1, "C");
printLcd(13, 1, mode_Msg);
// ----- LCD Bottom row -----end
int modeButtonState = digitalRead(MODEBUTTON_PIN);
static unsigned long lastModeButtonPress = 0;
if (modeButtonState == LOW && millis() - lastModeButtonPress > 1000) {
lastModeButtonPress = millis();
mode = 1 - mode; // toggle between Auto and manual mode
}
if(mode){
mode_Msg = "(A)";
digitalWrite(MODE_LED_PIN, HIGH); // switch on AUTO MODE LED
// Check if it's time for any of the alarms
for (int i = 0; i < numAlarms; ++i) {
if (now.hour() == alarmTimes[i][0] && now.minute() == alarmTimes[i][1] && !alarmTriggered) {
switch(i){
case 0: msg = "Pray"; break;
case 1: msg = "1p"; break;
case 2: msg = "2p"; break;
case 3: msg = "3p"; break;
case 4: msg = "4p"; break;
case 5: msg = "MDM"; break;
case 6: msg = "5p"; break;
case 7: msg = "6p"; break;
case 8: msg = "7p"; break;
case 9: msg = "8p"; break;
case 10: msg = "END"; break;
case 11: msg = "88p"; break;
case 12: msg = "END"; break;
default: msg = "SSC"; break;
}
Serial.println(i);
triggerAlarm(i);
}
}
}
else{
mode_Msg = "(M)";
digitalWrite(MODE_LED_PIN, LOW); // switch off AUTO MODE LED
}
int bellButtonState = digitalRead(BELLBUTTON_PIN); // the button to ring the bell
if (bellButtonState == LOW) {
beep();
}
//-------------Variable Ring Duration starts ------------------//
int potValue = analogRead(potPin); // Read the analog value from the potentiometer
ringDuration = map(potValue, 0, 1023, 100, 2000); // 100 mili sec to 2 sec here
if(debug){Serial.println("Ring duration is now : " + String(ringDuration));}
// Add a delay to avoid rapid changes
// delay(100);
// ------------Variable Ring Duration ends --------------------//
delay(1000); // Update every second
} // loop ends
void triggerAlarm(int alarmIndex) {
lcd.setCursor(0, 1);
//lcd.print("ALARM " + String(alarmIndex + 1));
// printLcd(4,1,"A"+ String(alarmIndex + 1));
printLcd(4, 1, "Ring>"+ String(ringDuration)+"ms-");
// Add your alarm-triggering code here
// For example, you can sound a buzzer or activate a relay
// Be mindful of how long your alarm function takes to execute
beep();
///delay(300); // Display the alarm message for 0.5 seconds
// Set the flag to indicate that the alarm has been triggered
alarmTriggered = true;
// Reset the flag after a delay (adjust as needed)
delay(60000); // Reset the flag after 60 seconds (1 minute)
alarmTriggered = false;
}
void beep() {
digitalWrite(RELAY_PIN, HIGH); // switch on relay
const int melody[] = {2100, 2000, 2200, 1900, 2300, 1800, 3000, 3500, 2000};// in Hz
for (int c = 0; c < sizeof(melody) / sizeof(melody[0]); c++) {
tone(BUZZER_PIN, melody[c], ringDuration);
delay(ringDuration);
noTone(BUZZER_PIN);
}
digitalWrite(RELAY_PIN, LOW); // switch off relay
}
void printLcd (int shuru, int sesh, String myWords) { // For LCD Display
lcd.setCursor(shuru, sesh); lcd.print(myWords);
}
String monthToString(int month) {
switch (month) {
case 1: return "Jan"; case 2: return "Feb"; case 3: return "Mar";
case 4: return "Apr"; case 5: return "May"; case 6: return "Jun";
case 7: return "Jul"; case 8: return "Aug"; case 9: return "Sep";
case 10: return "Oct"; case 11: return "Nov"; case 12: return "Dec";
default: return "";
}
}
String dayToString(int theDay) {
switch (theDay) {
case 0: return "Sun"; case 1: return "Mon"; case 2: return "Tue";
case 3: return "Wed"; case 4: return "Thu"; case 5: return "Fri";
case 6: return "Sat"; default: return "Invalid day";
}
}