#include <Wire.h>
#include <RTClib.h>
#include <SoftwareSerial.h>
#define RX_PIN 10 // RS232 RX pin
#define TX_PIN 11 // RS232 TX pin
#define BUTTON_PIN 2 // Button pin
#define LED_PIN 3 // Button pin
#define PC_PIN 4 // Button pin
// Creating a structure for weekdays, on time, off time and a check if user wants to turn on or off the projector for that specific day
struct Schedule {
int weekday; // 1 = Monday, 2 = Tuesday, ..., 7 = Sunday
bool needsToSchedule; // Flag to check if projector needs to be scheduled for this day
int onHour; // 24-hour format
int onMinute; // 24-hour format
int offHour; // 24-hour format
int offMinute; // 24-hour format
bool turnOn; // Flag to check if projector is already ON
};
// Here's how the schedule structure works:
// { weekday, needsToSchedule, onHour, onMinute, offHour, offMinute, turnOn, turnOff }
// For example, the following schedule will turn on the projector at 8:00 and turn it off at 20:00 on Monday
// { 1, true, 8, 0, 20, 0, false, false }
// For example, the following schedule will turn on the projector at 8:00 and turn it off at 20:00 on Tuesday
// { 2, true, 8, 0, 20, 0, false, false }
// Creating an array of schedules for each day of the week
Schedule schedules[] = {
{ 0, false, 8, 0, 20, 0, false}, // Sunday
{ 1, true, 8, 0, 20, 0, false}, // Monday
{ 2, false, 8, 0, 20, 0, false}, // Tuesday
{ 3, false, 8, 0, 20, 0, false}, // Wednesday
{ 4, true, 8, 0, 20, 0, false}, // Thursday
{ 5, true, 0, 34, 0, 35, false}, // Friday
{ 6, false, 8, 0, 20, 0, false}, // Saturday
};
// Creating an object of the RTC_DS3231 class
RTC_DS3231 rtc;
SoftwareSerial rs232Serial(RX_PIN, TX_PIN);
bool projectorOn = false;
int previousSecondCheck = 0; // Variable to store the previous second check
void setup() {
Serial.begin(115200);
rs232Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP); // Configure button pin with internal pull-up
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), checkButton, FALLING); // Trigger on falling edge (button press)
pinMode(LED_PIN, OUTPUT); // Configure button pin with internal pull-up
pinMode(PC_PIN, OUTPUT); // Configure button pin with internal pull-up
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1)
;
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Set RTC to current compile time
}
Serial.println("System initialized.");
}
void loop() {
checkSerialCommands();
printCurrentTime(); // Print current time and also check for RTC schedule
checkButton();
delay(50); // Small delay to prevent high CPU usage
}
// Simplified button state check
void checkButton() {
if (digitalRead(BUTTON_PIN) == LOW) { // Check if button is pressed
delay(200); // Short debounce delay
if (digitalRead(BUTTON_PIN) == LOW) { // Check if still pressed
toggleProjector(); // Toggle projector state
Serial.println("Button pressed - toggling projector");
}
}
}
// Function to toggle projector ON/OFF state
void toggleProjector() {
if (projectorOn) {
sendRS232Command("OFF");
digitalWrite(LED_PIN, LOW);
projectorOn = false;
delay(10000); // Shutdown delay
activatePCRelay();
Serial.println("Projector turned OFF");
} else {
sendRS232Command("ON");
digitalWrite(LED_PIN, HIGH);
projectorOn = true;
delay(10000); // Shutdown delay
activatePCRelay();
Serial.println("Projector turned ON");
}
}
void activatePCRelay() {
digitalWrite(PC_PIN, HIGH);
delay(15000);
digitalWrite(PC_PIN, LOW);
}
// Function to send RS232 ON/OFF commands
void sendRS232Command(String command) {
if (command == "ON") {
byte onCommand[] = { 0x06, 0x14, 0x00, 0x04, 0x00, 0x34, 0x11, 0x00, 0x00, 0x5D };
rs232Serial.write(onCommand, sizeof(onCommand));
} else if (command == "OFF") {
byte offCommand[] = { 0x06, 0x14, 0x00, 0x04, 0x00, 0x34, 0x11, 0x01, 0x00, 0x5E };
rs232Serial.write(offCommand, sizeof(offCommand));
}
delay(1000); // Delay to ensure command is processed
}
void turnOnPcProjector() {
projectorOn = true; // Set projector on flag true
sendRS232Command("ON"); // Send ON command
digitalWrite(LED_PIN, HIGH);
digitalWrite(PC_PIN, HIGH); // Start with PC relay on
delay(1000);
digitalWrite(PC_PIN, LOW); // Turn PC relay off
}
void turnOffPcProjector() {
projectorOn = false; // Reset projector on flag
sendRS232Command("OFF"); // Send OFF command
digitalWrite(LED_PIN, LOW);
digitalWrite(PC_PIN, HIGH); // Start with PC relay on
delay(1000);
digitalWrite(PC_PIN, LOW); // Turn PC relay off
}
// Function to check for RTC schedule
void checkRTCSchedule() {
DateTime now = rtc.now();
// Check for schedule for current day
for (int i = 0; i < 7; i++) { // Loop through all schedules
if (now.dayOfTheWeek() == schedules[i].weekday && schedules[i].needsToSchedule == true) { // Check if current day matches schedule and schedule is enabled
if (now.hour() == schedules[i].onHour && now.minute() == schedules[i].onMinute && !schedules[i].turnOn) { // Check if ON time matches and projector is not already ON
if (projectorOn == false) // Check if previously projector is off then turn it on
turnOnPcProjector();
schedules[i].turnOn = true; // Set turn ON flag to true
Serial.println("Projector turned ON by schedule");
} else if (now.hour() == schedules[i].offHour && now.minute() == schedules[i].offMinute && schedules[i].turnOn) { // Check if OFF time matches and projector is not already OFF
if (projectorOn == true) // Check if previously projector is on only then call turn off fucntion
turnOffPcProjector();
schedules[i].turnOn = false;
Serial.println("Projector turned OFF by schedule");
schedules[i].turnOn = false;
}
}
}
}
// Function to check for serial commands (manual ON/OFF)
void checkSerialCommands() {
if (Serial.available() > 0) {
String controlCommand = Serial.readString();
controlCommand.trim();
if (controlCommand.equalsIgnoreCase("ON") && !projectorOn) {
turnOnPcProjector(); // Send ON command
Serial.println("Projector turned ON by serial command");
} else if (controlCommand.equalsIgnoreCase("OFF") && projectorOn) {
turnOffPcProjector(); // Send OFF command
Serial.println("Projector turned OFF by serial command");
}
}
}
// Function to print the current time from the RTC
void printCurrentTime() {
DateTime now = rtc.now();
if (now.second() != previousSecondCheck) { // Print time only once per minute
Serial.print("Current Date and Time: ");
char buf[] = "YY/MM/DD hh:mm:ss"; // Create a buffer for the date and time structure that needs to be printed
Serial.print(now.toString(buf)); // Print current date and time
Serial.print(", Day of week:");
Serial.println(now.dayOfTheWeek());
previousSecondCheck = now.second(); // Update the previous second check
checkRTCSchedule(); // Check for RTC schedule
}
}