//oM zrii gurave namaH
const int debug = 0;
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
//#include <pitches.h>
// Define the pins -- i.e. assigning the function to the PIN
#define RELAY_PIN 2
#define BUZZER_PIN 3
#define modeButton 13
#define bellButton 12
#define autoLed_PIN A0
#define potPin A1 // Pin connected to the potentiometer
int ringTime = 1; // how many times to ring, cycles
int ringDuration = 100; // how long to ring
String msg; String mode_Msg;
int mode = 1; // 1 = auto, 0 = manual
int currentHour; int currentMin; int currentSec;
int currentDay; int currentMonth; int currentYear;
int dayOfWeek ; int temp;
// Create objects
LiquidCrystal_I2C lcd(0x27, 16, 2);// ref: datasheet
RTC_DS3231 rtc;
void setup() { /// ------Setup starts---------------
// -----IMPORTANT ------//
Wire.begin(); //to ensure I2C bus is properly initialized before any communication takes place.
lcd.begin(16, 2); lcd.backlight();// // Initialize LCD COLUMN, ROW and backlight ON
Serial.begin(9600); //---Initialize Serial Monitor for debugging purpose
// Initialize pins
pinMode(RELAY_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT);
pinMode (modeButton, INPUT_PULLUP); pinMode(bellButton, INPUT_PULLUP);
pinMode(autoLed_PIN, OUTPUT);
// Initialize RTC
if (!rtc.begin()) {Serial.println("Couldn't find RTC");
while (1); delay(10);
}if (rtc.lostPower()) {Serial.println("RTC lost power, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
/////-----IMPORTANT ----------------------//
// Uncomment the next line on the first run to set the correct time
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// manual setup example: January 1, 2023, 12:28:00 : >>>
//rtc.adjust(DateTime(2023, 12, 28, 12, 28, 0)); // for manual adjustment with buttons
delay(1000);// give rtc module some time to initialize
beep();
} /// ------Setup ends -------------------------
void loop() { /// ------------ void loop starts ===============
//--------Clock function start ----------------------
DateTime now = rtc.now();
currentHour = now.hour(); currentMin = now.minute(); currentSec = now.second();
currentDay = now.day(); currentMonth = now.month(); currentYear = now.year();
temp = rtc.getTemperature();
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
unsigned long timeCode = (currentHour * 10000UL) + ( currentMin * 100UL) + currentSec;
if (debug){Serial.println(timeCode);}// debug
/// ---- For always on msg -- starts
if (timeCode > 104000 && timeCode < 105000) { // 10:40 AM Prayer Starts
msg = "Pray";
} else if (timeCode > 105000 && timeCode < 113000) { // 10:50 AM 1st period starts
msg = "(1p)";
} else if (timeCode > 113000 && timeCode < 121000) { // 11:35 AM 2nd period starts
msg = "(2p)";
} else if (timeCode > 121000 && timeCode < 125000) { // 12:15 AM 3rd period starts
msg = "(3p)";
} else if (timeCode > 125000 && timeCode < 133000) { // 12:55 AM 4th period starts
msg = "(4p)";
} else if (timeCode > 133000 && timeCode < 141000) { // 1:35 PM Tiffin starts
msg = "MDM";
} else if (timeCode > 141000 && timeCode < 144500) { // 2:15 PM 5th period
msg = "(5p)";
} else if (timeCode > 144500 && timeCode < 152000) { // 2:50 PM 6th period
msg = "(6p)";
} else if (timeCode > 152000 && timeCode < 155500) { // 3:25 PM 7th period
msg = "(7p)";
} else if (timeCode > 155500 && timeCode < 163000) { // 4:00 PM 8th period
msg = "(8p)";
} else if (timeCode > 163000 && timeCode < 170000) { // 4:30 PM END of SCHOOL
msg = "End";
} else if (timeCode > 170000) { // 4:30 PM END of SCHOOL
msg = "SSC";
}
/// ---- For always on msg -- ends
if (mode){
mode_Msg = "(A)";
digitalWrite(autoLed_PIN, HIGH); // Automatic Bell Mode Indicator LED
////----switch case starts -------//
switch (timeCode) {
case 104000 : // 10:40 AM Prayer Starts
//msg = "Pray";
ring(3);
break;
case 105000: // 10:50 AM 1st period starts
// msg = "(1p)"; 40 min
ring(1);
break;
case 113000: // 11:30 AM 2nd period starts
// msg = "(2p)"; 40 min
ring(1);
break;
case 121000: // 12:10 AM 3rd period starts
// msg = "(3p)"; 40 min
ring(1);
break;
case 125000: // 12:50 AM 4th period starts
// msg = "(4p)"; 40 min
ring(1);
break;
case 133000: // 1:30 PM Tiffin starts
// msg = "MDM"; 40 min
ring(3);
break;
case 141000: // 2:10 PM 5th period
// msg = "(5p)"; 35 min
ring(1);
break;
case 144500: // 2:45 PM 6th period
// msg = "(6p)"; 35 min
ring(1);
break;
case 152000: // 3:20 PM 7th period
// msg = "(7p)"; 35 min
ring(1);
break;
case 155500: // 3:55 PM 8th period
// msg = "(8p)"; 35 min
ring(1);
break;
case 163000: // 4:30 PM END of SCHOOL
// msg = "End";
ring(3);
break;
case 170000: // 5:00 PM END of SCHOOL
beep();
break;
case 180000: // 6:00 PM END of SCHOOL
beep();
break;
case 190000: // 7:00 PM END of SCHOOL
beep();
break;
case 200000: // 8:00 PM END of SCHOOL
beep();
break;
case 210000: // 9:00 PM END of SCHOOL
beep();
break;
case 220000: // 10:00 PM END of SCHOOL
beep();
break;
case 230000: // 11:00 PM END of SCHOOL
beep();
break;
case 100000: // 10:00 AM END of SCHOOL
beep();
break;
default:
// Code to execute if the current time does not match any case
break;
}
}
else{// -----in Manual Mode -------//
mode_Msg = "(M)"; digitalWrite(autoLed_PIN, LOW);// switch off AUTO MODE LED
}
//----- LCD Bottom row ------start
printLcd(0, 1, dayToString(dayOfWeek));
printLcd(4, 1, msg);
printLcd(9, 1, String(temp-3)); // to subtrack heat inside the box
printLcd(11, 1, "C");
printLcd(13, 1, mode_Msg);
// ----- LCD Bottom row -----end
//~~~~~~~~~~~~~~~~~~ BUTTON CODE STARTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int modeButtonState = digitalRead(modeButton);
static unsigned long lastModeButtonPress = 0;
if (modeButtonState == LOW && millis() - lastModeButtonPress > 1000) { // 1 sec pause before 2nd press
lastModeButtonPress = millis();
mode = 1 - mode; // toggle between Auto and manual mode
if (debug) {Serial.println("mode is " + String(mode) );} //debug
}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int bellButtonState = digitalRead(bellButton); // the button to ring the bell when needed
if (bellButtonState == LOW) {// if the button is pressed
ring(1); // cycle 3 times
}//~~~~~~~~~~~~~~~~~~ BUTTON CODE ENDS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------Variable Ring Duration starts ------------------//
// Read the analog value from the potentiometer
int potValue = analogRead(potPin);
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); //delay for stability-- IMPORTANT
}// /// ------------ void loop ends ===================================
//--------------------UDF starts -----------------------
void beep(){
tone(BUZZER_PIN, 3700, 170); delay(100); noTone(BUZZER_PIN);
}
void ring(int t) {
//ringDuration = 100; // patch to test, remove later
printLcd(4, 1, "Ring>"+ String(ringDuration)+"ms-"+String(t));
for (int i = 1; i <= t; ++i) {
digitalWrite(RELAY_PIN, HIGH); // switch on relay
if(debug){Serial.println("running for " + String(i) + " time");}
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
// Add a delay for silence between iterations
delay(1000); // Adjust the duration of silence as needed
}
noTone(BUZZER_PIN); // stop buzzer sound // double check
digitalWrite(RELAY_PIN, LOW); // switch off relay // double check
}
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";
}
}//-------------- UDF ends -----------------//