#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Keypad.h>
#include <RTClib.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// OLED Display Configuration
#define SCREEN_WIDTH 128 // OLED width, in pixels
#define SCREEN_HEIGHT 64 // OLED height, in pixels
// Pin Configuration
#define TRIGGER_PIN 12 // GPIO pin connected to the trigger pin of the ultrasonic sensor
#define ECHO_PIN 13 // GPIO pin connected to the echo pin of the ultrasonic sensor
#define PIR_PIN 14 // GPIO pin connected to the signal pin of the PIR motion sensor
#define RELAY_PIN 27 // GPIO pin connected to the relay module
#define ONE_WIRE_BUS 26 // GPIO pin connected to the DS18B20 sensor
#define BUZZER_PIN 25 // GPIO pin connected to the buzzer
// Keypad Configuration
const byte ROWS = 4; // four rows
const byte COLS = 4; // four columns
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {15, 2, 4, 5}; // connect to the row pinouts of the keypad
byte colPins[COLS] = {34, 35, 32, 33}; // connect to the column pinouts of the keypad
// Keypad object
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Real-Time Clock (RTC) Configuration
RTC_DS3231 rtc;
// Ultrasonic Sensor Variables
long duration;
int distance;
// PIR Motion Sensor Variable
bool motionDetected = false;
// Temperature Sensor Configuration
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float temperature = 0.0;
// Define a struct to represent an alarm
struct Alarm {
int hour;
int minute;
bool active;
unsigned long snoozeTime;
};
// Array to store multiple alarms
Alarm alarms[] = {
{6, 0, false, 0}, // Example: 6:00 AM, inactive, no snooze
{7, 23, false, 0} // Example: 7:30 AM, inactive, no snooze
};
// OLED Display object
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Function declarations
void updateOLED(DateTime now);
void handleKeypadInput(char key);
void checkAlarms();
void setup() {
Serial.begin(9600);
// Pin configurations
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(PIR_PIN, INPUT);
pinMode(RELAY_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
// Initialize OLED display with I2C address 0x3C
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Failed to start SSD1306 OLED"));
while (1);
}
// Wait two seconds for initializing
delay(2000);
// Clear display
oled.clearDisplay();
// Set text size and color
oled.setTextSize(1);
oled.setTextColor(WHITE);
// Set cursor position for displaying text
oled.setCursor(0, 2);
// Display welcome message
oled.println("Hello! Welcome to the Hardest Alarm");
oled.println("Prn - 20220802028");
// Display on OLED
oled.display();
// Wait for a moment to read the welcome message
delay(3000);
// Clear display for the next content
oled.clearDisplay();
// Initialize RTC
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
// Check if RTC lost power and set the time if needed
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// Start the temperature sensor
sensors.begin();
}
void loop() {
DateTime now = rtc.now(); // Get the current time
// Handle keypad input
char key = keypad.getKey();
if (key) {
handleKeypadInput(key);
}
// Ultrasonic sensor measurement
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
duration = pulseIn(ECHO_PIN, HIGH);
distance = duration * 0.034 / 2;
// PIR motion sensor detection
motionDetected = digitalRead(PIR_PIN);
// Temperature sensor reading
sensors.requestTemperatures();
temperature = sensors.getTempCByIndex(0);
// Display time, date, temperature, and motion status on OLED
updateOLED(now);
// Check alarm conditions
checkAlarms();
// Display on OLED
oled.display();
// Adjust delay as needed
delay(500);
// Clear display for the next loop
oled.clearDisplay();
}
// Function to handle keypad input
void handleKeypadInput(char key) {
if (key == 'A') {
// Toggle alarm setting
alarms[0].active = !alarms[0].active;
Serial.println(alarms[0].active ? "Alarm set" : "Alarm not set");
} else if (key == 'B') {
// Snooze the first alarm for 5 minutes
alarms[0].snoozeTime = millis() + 300000;
Serial.println("Alarm snoozed");
} else if (key == 'C') {
// Set the alarm time
Serial.println("Enter alarm hour (0-23): ");
char hourKey = keypad.getKey();
int newHour = (hourKey - '0') * 10;
hourKey = keypad.getKey();
newHour += hourKey - '0';
Serial.println("Enter alarm minute (0-59): ");
char minuteKey = keypad.getKey();
int newMinute = (minuteKey - '0') * 10;
minuteKey = keypad.getKey();
newMinute += minuteKey - '0';
// Validate the entered time
if (newHour >= 0 && newHour <= 23 && newMinute >= 0 && newMinute <= 59) {
alarms[0].hour = newHour;
alarms[0].minute = newMinute;
Serial.println("Alarm time set successfully");
} else {
Serial.println("Invalid time. Please try again.");
}
} else if (key == 'D') {
// Activate/deactivate all alarms
for (int i = 0; i < sizeof(alarms) / sizeof(alarms[0]); i++) {
alarms[i].active = !alarms[i].active;
}
Serial.println("All alarms toggled");
}
}
// Function to update OLED display
void updateOLED(DateTime now) {
oled.setCursor(0, 10);
oled.print("Time: ");
oled.print(now.hour(), DEC);
oled.print(':');
oled.print(now.minute(), DEC);
oled.print(':');
oled.print(now.second(), DEC);
oled.setCursor(0, 20);
oled.print("Date: ");
oled.print(now.month(), DEC);
oled.print('/');
oled.print(now.day(), DEC);
oled.print('/');
oled.print(now.year(), DEC);
oled.setCursor(0, 30);
oled.print("Temp: ");
oled.print(temperature);
oled.print(" °C");
oled.setCursor(0, 40);
oled.print("Motion: ");
oled.print(motionDetected ? "Detected " : "Not Detected");
}
// Function to check alarm conditions
void checkAlarms() {
DateTime now = rtc.now(); // Get the current time
for (int i = 0; i < sizeof(alarms) / sizeof(alarms[0]); i++) {
Alarm &alarm = alarms[i];
Serial.print("Alarm ");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(alarm.hour);
Serial.print(':');
Serial.print(alarm.minute);
Serial.print(", Active: ");
Serial.print(alarm.active);
Serial.print(", Snooze Time: ");
Serial.print(alarm.snoozeTime);
Serial.println();
if (alarm.active && now.hour() == alarm.hour && now.minute() == alarm.minute && millis() > alarm.snoozeTime) {
if (motionDetected && distance < 50) {
digitalWrite(RELAY_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW); // Turn off the buzzer
Serial.println("ALARM OFF");
} else {
digitalWrite(RELAY_PIN, HIGH);
digitalWrite(BUZZER_PIN, HIGH); // Turn on the buzzer
Serial.println("ALARM!");
Serial.print("Alarm will ring at: ");
Serial.print(alarm.hour);
Serial.print(':');
Serial.print(alarm.minute);
Serial.println(":00");
delay(5000); // Adjust the delay as needed (5 seconds in this example)
digitalWrite(RELAY_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW); // Turn off the buzzer
}
alarm.active = false; // Reset alarm setting after activation
}
}
}