#include <LiquidCrystal_I2C.h>
#include <Wire.h>
// Constants for the pins
const int LED_PINS[] = {2, 3, 4};
const int BUTTON_PINS[] = {5, 6, 7};
const int SWITCH_PINS[] = {8, 9, 10};
const int BUZZER_PIN = 11;
const int NUM_BUTTONS = 3;
const unsigned long ALARM_DURATION = 90 * 1000; // 90 seconds in milliseconds
// LCD constants
const int I2C_ADDR = 0x27;
const int LCD_COLUMNS = 20;
const int LCD_LINES = 4;
// Global declaration for lastButtonState
int lastButtonState[NUM_BUTTONS]; // This array will hold the last state of each button
// Initialize the LCD
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// Enumeration for button and alarm identifiers
enum AlarmType { SIX_H, TWELVE_H, TWENTY_FOUR_H };
// Time simulation settings
unsigned long startTime; // The time at which the Arduino was started
unsigned long currentTime; // The current simulated time since the Arduino started
float timeMultiplier = 1; // Speed up time by a factor for simulation
// Add alarm duration constants here
const unsigned long sixHourAlarmTime = 6 * 3600; // 6 hours in seconds
const unsigned long twelveHourAlarmTime = 12 * 3600; // 12 hours in seconds
const unsigned long twentyFourHourAlarmTime = 24 * 3600; // 24 hours in seconds
// Start time settings (24-hour format)
unsigned long simulatedDays = 1; // Start counting from day 1
int startHour = 15; // Starting at 15:59:50 for testing purposes
int startMinute = 59; // Starting at the 59th minute
int startSecond = 50; // Starting at the 50th second
unsigned long lastButtonPressedTime[NUM_BUTTONS]; // This array will hold the last time each button was pressed
// Structure for button state
struct ButtonState {
bool pressed;
bool alarmActive;
unsigned long alarmStartTimeInSeconds; // Start time of the alarm in seconds
};
ButtonState buttonStates[NUM_BUTTONS];
void initializePins() {
for (int i = 0; i < NUM_BUTTONS; i++) {
pinMode(LED_PINS[i], OUTPUT);
pinMode(BUTTON_PINS[i], INPUT_PULLUP);
pinMode(SWITCH_PINS[i], INPUT_PULLUP);
lastButtonState[i] = HIGH; // Initialize the last known button state to HIGH
}
pinMode(BUZZER_PIN, OUTPUT);
}
void handleBuzzer();
// Function to calculate the current simulated time
void updateCurrentTime() {
unsigned long elapsedMillis = (millis() - startTime) * timeMultiplier;
unsigned long totalSeconds = elapsedMillis / 1000;
unsigned long simulatedSeconds = totalSeconds % 60;
unsigned long totalMinutes = totalSeconds / 60;
unsigned long simulatedMinutes = totalMinutes % 60;
unsigned long totalHours = totalMinutes / 60;
unsigned long simulatedHours = totalHours % 24;
// Update days counter
if (totalHours / 24 >= simulatedDays) {
simulatedDays = (totalHours / 24) + 1; // Increase day by one to account for the new day
}
currentTime = simulatedDays * 1000000 + simulatedHours * 10000 + simulatedMinutes * 100 + simulatedSeconds;
}
// Global variables for debouncing
unsigned long lastDebounceTime[NUM_BUTTONS] = {0}; // Last time the output pin was toggled
unsigned long debounceDelay = 50; // Debounce time in milliseconds
// Function to check buttons and activate or deactivate alarm
// Function to check buttons (now slide switches) and activate or deactivate alarm
void checkButtons() {
for (int i = 0; i < NUM_BUTTONS; i++) {
int reading = digitalRead(BUTTON_PINS[i]);
// Since we are using slide switches, a simple ON/OFF check is sufficient
if (reading == LOW) { // Assuming LOW means activated
buttonStates[i].alarmActive = true;
buttonStates[i].alarmStartTimeInSeconds = calculateCurrentSimulatedTimeInSeconds();
} else {
buttonStates[i].alarmActive = false;
}
}
}
// Remove the debounce logic as it's not necessary for slide switches
// The variables and logic associated with debouncing can be removed
// Function to check cover switches and deactivate alarm if necessary
void checkCovers() {
for (int i = 0; i < NUM_BUTTONS; i++) {
// If the cover is opened (switch is HIGH), deactivate the alarm
if (digitalRead(SWITCH_PINS[i]) == HIGH) {
buttonStates[i].alarmActive = false;
digitalWrite(LED_PINS[i], LOW); // Turn off LED
}
}
}
// Function to blink LEDs
void blinkLEDs() {
unsigned long currentSimulatedTimeInSeconds = calculateCurrentSimulatedTimeInSeconds();
for (int i = 0; i < NUM_BUTTONS; i++) {
if (buttonStates[i].alarmActive) {
unsigned long timeSinceAlarmActivated = currentSimulatedTimeInSeconds - buttonStates[i].alarmStartTimeInSeconds;
// Handle different alarm durations based on the button index
unsigned long alarmDuration = (i == SIX_H) ? sixHourAlarmTime :
((i == TWELVE_H) ? twelveHourAlarmTime : twentyFourHourAlarmTime);
if (timeSinceAlarmActivated < alarmDuration) {
// Blinking logic
digitalWrite(LED_PINS[i], (timeSinceAlarmActivated % 2) == 0 ? HIGH : LOW);
} else {
// Turn off LED after the duration is over
buttonStates[i].alarmActive = false;
digitalWrite(LED_PINS[i], LOW);
}
}
}
}
// Function to update the LCD display
void updateLCD() {
// Display the simulated day and time
lcd.setCursor(0, 0);
unsigned long days = currentTime / 1000000;
int hours = (currentTime % 1000000) / 10000;
int minutes = (currentTime % 10000) / 100;
int seconds = currentTime % 100;
lcd.print("Day ");
lcd.print(days);
lcd.print(" ");
lcd.print(hours < 10 ? "0" : ""); lcd.print(hours);
lcd.print(":");
lcd.print(minutes < 10 ? "0" : ""); lcd.print(minutes);
lcd.print(":");
lcd.print(seconds < 10 ? "0" : ""); lcd.print(seconds);
// Correctly display the alarm status based on 'alarmActive', not 'pressed'
lcd.setCursor(0, 1);
lcd.print("6H:");
lcd.print(buttonStates[SIX_H].alarmActive ? "ON " : "OFF");
lcd.print("12H:");
lcd.print(buttonStates[TWELVE_H].alarmActive ? "ON " : "OFF");
lcd.print("24H:");
lcd.print(buttonStates[TWENTY_FOUR_H].alarmActive ? "ON " : "OFF");
// Display the cover status with 'C' for "closed" and 'O' for "open"
lcd.setCursor(0, 2);
lcd.print("6H:");
lcd.print(digitalRead(SWITCH_PINS[SIX_H]) == HIGH ? "C " : "O ");
lcd.print("12H:");
lcd.print(digitalRead(SWITCH_PINS[TWELVE_H]) == HIGH ? "C " : "O ");
lcd.print("24H:");
lcd.print(digitalRead(SWITCH_PINS[TWENTY_FOUR_H]) == HIGH ? "C" : "O");
}
// Function to initialize the LCD
void initializeLCD() {
lcd.init();
lcd.backlight();
}
// Function to calculate current simulated time in seconds
unsigned long calculateCurrentSimulatedTimeInSeconds() {
updateCurrentTime(); // Make sure currentTime is updated
unsigned long daysInSeconds = ((currentTime / 1000000) - 1) * 86400;
unsigned long hoursInSeconds = ((currentTime % 1000000) / 10000) * 3600;
unsigned long minutesInSeconds = ((currentTime % 10000) / 100) * 60;
unsigned long seconds = currentTime % 100;
return daysInSeconds + hoursInSeconds + minutesInSeconds + seconds;
}
void setup() {
initializePins(); // Initialize the digital pins for LEDs, buttons, and switches
initializeLCD(); // Initialize the LCD display
Serial.begin(9600); // Start the serial communication for debugging
for (int i = 0; i < NUM_BUTTONS; i++) {
lastButtonPressedTime[i] = 0; // Initialize the last button press time to 0
buttonStates[i].pressed = false; // Initialize the pressed state to false
buttonStates[i].alarmActive = false; // Initialize the alarm active state to false
buttonStates[i].alarmStartTimeInSeconds = 0; // Initialize the alarm start time
lastButtonState[i] = digitalRead(BUTTON_PINS[i]); // Read the initial state of the button
}
// Calculate the initial simulated time in seconds
unsigned long initialTimeInSeconds = startHour * 3600L + startMinute * 60L + startSecond;
// Adjust the start time based on the time multiplier
startTime = millis() - (initialTimeInSeconds * 1000L / timeMultiplier);
}
void loop() {
updateCurrentTime(); // Update the current simulated time
checkButtons(); // Check and handle button presses
checkCovers(); // Check the state of the switch covers
handleBuzzer(); // Call the buzzer function
blinkLEDs(); // Handle LED blinking based on alarm status
updateLCD(); // Update the LCD display with the latest information
delay(1000 / timeMultiplier); // Delay for a second, adjusted by the time multiplier
}
void handleBuzzer() {
bool anyAlarmActive = false;
for (int i = 0; i < NUM_BUTTONS; i++) {
if (buttonStates[i].alarmActive) {
anyAlarmActive = true;
break;
}
}
if (anyAlarmActive) {
tone(BUZZER_PIN, 1000); // Buzzer on
} else {
noTone(BUZZER_PIN); // Buzzer off
}
}