Smart Home Security System is a hands-on project designed for creating a basic home security setup.
This project will involve:
- one or more Passive Infrared (PIR) motion sensor to detect movement in the environment
- a keypad for arming/disarming
- an alarm system or a buzzer to alert users when unauthorized motion is detected.
This alarm system will be designed mostly to be used on doors or windows, setting the sensors on the trajectory of motion realized by the door or window.
I will also create a web application in order to be able to arm or disarm the alarm from a distance.
Additionally, the system will send emails with every update, arming, disarming or alarm set-offs.
These are the hardware components used for the alarm:
The hardware with everything connected can be seen below:
Library and Pin Definitions:
#include <Keypad.h> #define buzzer 10 #define trigPin 11 #define echoPin 12 #define RXp2 16 #define TXp2 17
The code starts by including the Keypad library and defining pin numbers for various components like the buzzer and PIR sensor. Global Variables:
long duration; int distance, initialDistance, currentDistance, i; int screenOffMsg = 0; String password = "1234"; String tempPassword; boolean activated = false; // State of the alarm boolean isActivated; boolean activateAlarm = true; boolean alarmActivated = false; boolean specialAlarmActivated = true; boolean enteredPassword; // State of the entered password to stop the alarm boolean passChangeMode = false; boolean passChanged = false;
Keypad Configuration:
In the Smart Home Security System project, the keypad configuration plays a crucial role. It involves mapping each button on the keypad to a specific function or input. The keypad uses a matrix layout, which means it has rows and columns of buttons. In the code, the keyMap array defines the characters or numbers associated with each button.
The pins of the Arduino are configured to interface with this matrix. Each row and column of the keypad is connected to a specific pin on the Arduino. The rowPins and colPins arrays in the code specify which Arduino pins are connected to which rows and columns of the keypad.
When a button is pressed, the Arduino detects which row and column are activated, and the corresponding character from the keyMap is identified. This setup allows for efficient detection of multiple button presses and is commonly used in security systems for password input.
const byte ROWS = 4; const byte COLS = 4; char keypressed; char keyMap[ROWS][COLS] = { {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'} }; byte rowPins[ROWS] = {9, 8, 7, 6}; byte colPins[COLS] = {5, 4, 3, 2}; Keypad myKeypad = Keypad(makeKeymap(keyMap), rowPins, colPins, ROWS, COLS);
The setup function in the Arduino code for the Smart Home Security System is where the initial configuration of the system takes place. It begins by initializing serial communication, which is crucial for debugging and interfacing with other devices. The function then sets up the pin modes for various components, such as the buzzer and the PIR sensor, to define their roles as input or output. This step is essential for the Arduino to interact correctly with these hardware components. While the specific initialization of the keypad is not detailed in the provided snippet, typically, this would also be configured here, linking the physical keypad layout to the Arduino's input pins. This initial setup ensures that all components are ready to function as intended when the main program loop begins.
void setup() { Serial.begin(9600); // Serial2.begin(9600, SERIAL_8N1, RXp2, TXp2); pinMode(buzzer, OUTPUT); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); }
In the main loop of the Arduino program for the Smart Home Security System, the code continuously monitors and responds to various conditions. It checks for incoming commands from the ESP32, which are critical for remotely controlling the alarm system. Depending on the received commands, the system is either armed or disarmed. The loop also manages the state of the alarm, activating it based on predefined conditions like detecting motion through the PIR sensor. Additionally, it handles user interactions with the keypad, allowing for manual arming/disarming and password changes. This loop is the heart of the system, constantly checking and responding to changes in its environment and user inputs.
void loop() { // Check for commands from ESP32 if (Serial.available() > 0) { String command = Serial.readStringUntil('\n'); // Read the command from ESP32 command.trim(); // Remove any whitespace Serial.print("Received command: "); Serial.println(command); if (command.equals("ARM")) { // specialActivateAlarm = true; // Set the alarm activation flag activateAlarm = true; } else if (command.equals("DISARM")) { specialAlarmActivated = false; // Set the alarm deactivation flag activateAlarm = false; alarmActivated = false; screenOffMsg = 0; } } // Serial2.println("Message Received: "); // Serial2.println(Serial2.readString()); if(activateAlarm == true) { Serial.println("Alarm will be activated in: "); int countdown = 1; while(countdown != 0) { Serial.println(countdown); countdown--; // tone(buzzer, 700, 1000); digitalWrite(buzzer, LOW); delay(1000); digitalWrite(buzzer, HIGH); } Serial.println("Alarm Activated!"); // initialDistance = getDistance(); initialDistance = 10; activateAlarm = false; alarmActivated = true; } if(alarmActivated == true) { currentDistance = getDistance(); // Serial.println(currentDistance); if(currentDistance < initialDistance) { // tone(buzzer, 1000); // Serial.print("ALARM"); digitalWrite(buzzer, LOW); enterPassword(specialAlarmActivated); } } if(!alarmActivated) { if(screenOffMsg == 0) { Serial.println("A - Activate"); Serial.println("B - Change Password"); screenOffMsg = 1; } keypressed = myKeypad.getKey(); Serial.print(keypressed); if(keypressed == 'A') { // tone(buzzer, 1000, 200); digitalWrite(buzzer, LOW); delay(200); digitalWrite(buzzer, HIGH); activateAlarm = true; } else if(keypressed == 'B') { int i = 1; // tone(buzzer, 2000, 100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); tempPassword = ""; Serial.println("Current Password"); Serial.println(">"); passChangeMode = true; passChanged = true; while(passChanged) { keypressed = myKeypad.getKey(); if(keypressed != NO_KEY) { if(keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' || keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' || keypressed == '8' || keypressed == '9') { tempPassword += keypressed; Serial.print("*"); i++; // tone(buzzer, 2000, 100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); } } if(i > 5 || keypressed == '#') { tempPassword = ""; i = 1; Serial.println("Current Password: "); Serial.println(">"); } if(keypressed == '*') { i = 1; // tone(buzzer, 2000, 100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); if(password == tempPassword) { tempPassword = ""; Serial.println("Set New Password: "); Serial.println('>'); while(passChangeMode) { keypressed = myKeypad.getKey(); if(keypressed != NO_KEY) { if(keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' || keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' || keypressed == '8' || keypressed == '9') { tempPassword += keypressed; Serial.print("*"); i++; // tone(buzzer, 2000, 100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); } } if(i > 5 || keypressed == '#') { tempPassword = ""; i = 1; // tone(buzzer, 2000, 100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); Serial.println("Set New Password: "); Serial.println(">"); } if(keypressed == '*') { i = 1; // tone(buzzer, 2000, 100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); password = tempPassword; passChangeMode = false; passChanged = false; screenOffMsg = 0; } } } } } } } }
The enterPassword function in the Arduino program for the Smart Home Security System is responsible for handling the process of password entry through the keypad. This function is activated when there is a need to disarm the alarm, typically after it has been triggered. It prompts the user to enter the correct password, reading the input from the keypad. The function checks if the entered password matches the predefined one. If the correct password is entered, it deactivates the alarm and resets relevant system states. If an incorrect password is entered, it prompts the user to try again, maintaining the alarm's active state. This function is crucial for ensuring that only authorized individuals can disarm the system.
void enterPassword(bool specialAlarmActivated) { int k = 5; tempPassword = ""; activated = true; Serial.println("*** ALARM ***"); Serial.println("Password >"); if(specialAlarmActivated == false) { activated = false; alarmActivated = false; // noTone(buzzer); digitalWrite(buzzer, HIGH); screenOffMsg = 0; return; } while(activated) { keypressed = myKeypad.getKey(); if(keypressed != NO_KEY) { if(keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' || keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' || keypressed == '8' || keypressed == '9') { tempPassword += keypressed; Serial.print("*"); digitalWrite(buzzer, LOW); delay(500); digitalWrite(buzzer, HIGH); k++; } } if(k > 9 || keypressed == '#') { tempPassword = ""; k = 5; Serial.println("Try Again Please!"); Serial.println("*** ALARM ***"); Serial.println("Password >"); } if(keypressed == '*') { if(tempPassword == password) { activated = false; alarmActivated = false; // noTone(buzzer); digitalWrite(buzzer, HIGH); screenOffMsg = 0; } else if(tempPassword != password) { Serial.println("Wrong! Try Again!"); delay(2000); Serial.println("*** ALARM ***"); Serial.println("Password >"); } } } }
The getDistance function in the Arduino code is a critical part of the Smart Home Security System, specifically designed to work with the PIR sensor. This function calculates the distance of an object from the sensor, which is crucial for detecting movement in the system's vicinity. It sends a pulse from the sensor, waits for it to bounce back, and then calculates the distance based on the time taken for the pulse to return. This distance measurement is used to determine whether an object is within a predefined range, which can trigger the alarm if the system is armed. This functionality is key for motion detection in security applications.
long getDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = (duration / 29) / 2; return distance; }
The provided ESP32 code integrates several functionalities for a smart home security system. It starts by including necessary libraries for WiFi and server capabilities. The code establishes a WiFi connection using predefined SSID and password and sets up an asynchronous web server.
The server listens for HTTP GET requests on root (”/”) and handles ARM/DISARM actions. When either ARM or DISARM is triggered via the web interface, the ESP32 logs this event over serial communication and sends an email notification. The email functionality is achieved using the ESP_Mail_Client library, which allows the ESP32 to send emails via an SMTP server.
For the email part, SMTP server details, sender, and recipient information are defined. When ARM/DISARM actions are activated, the ESP32 composes and sends an email indicating the system's status (armed or disarmed). This feature is essential for remote monitoring and notification.
The server begins listening for incoming connections after the initial setup, and the loop function remains empty as the primary functionality is handled within the web server's routes and callbacks.
This combination of web server and email notifications offers a robust approach for remote security system management.
#include <WiFi.h> #include <ESPAsyncWebServer.h> #include <ESP_Mail_Client.h> #define SMTP_server "smtp.gmail.com" #define SMTP_Port 465 #define sender_email "esp32.test.iot.2024@gmail.com" #define sender_password "hvzyfnpqlvfozkzx" #define Recipient_email "nanurobert8@gmail.com" #define Recipient_name "Robert" SMTPSession smtp; const char* ssid = "Robert 2,4"; // Replace with your WiFi SSID const char* password = "robert2000"; // Replace with your WiFi Password AsyncWebServer server(80); void setup() { Serial.begin(9600); // Connect to Wi-Fi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); // Print the IP address Serial.print("IP Address: "); Serial.println(WiFi.localIP()); smtp.debug(1); ESP_Mail_Session session; session.server.host_name = SMTP_server ; session.server.port = SMTP_Port; session.login.email = sender_email; session.login.password = sender_password; session.login.user_domain = ""; SMTP_Message message; /* Declare the message class */ message.sender.name = "ESP 32"; message.sender.email = sender_email; message.subject = "ESP32 Testing Email"; message.addRecipient(Recipient_name,Recipient_email); String textMsg = "The alarm system application is on."; message.text.content = textMsg.c_str(); message.text.charSet = "us-ascii"; message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit; // Route for root / web page server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ String html = "<html><body><h1>Alarm Control</h1>" "<button onclick=\"location.href='/arm'\">Arm Alarm</button>" "<button onclick=\"location.href='/disarm'\">Disarm Alarm</button>" "</body></html>"; request->send(200, "text/html", html); }); // Handler for the ARM action server.on("/arm", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println("ARM"); // Send ARM command to Arduino ESP_Mail_Session session; session.server.host_name = SMTP_server ; session.server.port = SMTP_Port; session.login.email = sender_email; session.login.password = sender_password; session.login.user_domain = ""; SMTP_Message message; /* Declare the message class */ message.sender.name = "ESP 32"; message.sender.email = sender_email; message.subject = "ESP32 Testing Email"; message.addRecipient(Recipient_name,Recipient_email); String textMsg = "The alarm system application is on."; message.text.content = textMsg.c_str(); message.text.charSet = "us-ascii"; message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit; if (!MailClient.sendMail(&smtp, &message)) Serial.println("Error sending Email, " + smtp.errorReason()); request->redirect("/"); // Redirect back to the main page }); // Handler for the DISARM action server.on("/disarm", HTTP_GET, [](AsyncWebServerRequest *request){ Serial.println("DISARM"); // Send DISARM command to Arduino ESP_Mail_Session session; session.server.host_name = SMTP_server ; session.server.port = SMTP_Port; session.login.email = sender_email; session.login.password = sender_password; session.login.user_domain = ""; SMTP_Message message; /* Declare the message class */ message.sender.name = "ESP 32"; message.sender.email = sender_email; message.subject = "ESP32 Testing Email"; message.addRecipient(Recipient_name,Recipient_email); String textMsg = "The alarm system application is on."; message.text.content = textMsg.c_str(); message.text.charSet = "us-ascii"; message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit; if (!MailClient.sendMail(&smtp, &message)) Serial.println("Error sending Email, " + smtp.errorReason()); request->redirect("/"); // Redirect back to the main page }); /* //Send simple text message String textMsg = "Hello"; message.text.content = textMsg.c_str(); message.text.charSet = "us-ascii"; message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;*/ if (!smtp.connect(&session)) return; if (!MailClient.sendMail(&smtp, &message)) Serial.println("Error sending Email, " + smtp.errorReason()); // Start server server.begin(); } void loop() { // Nothing needed here for now }
Web Application
The smart alarm comes with a web application in order to arm and disarm the alarm, including a login system.
After you login with your credentials you will see the two buttons used for arming and disarming the alarm system.
The application also has a web server on which you are presented with two buttons for arming and disarming.
The buttons pressed will send an email with the information regarding that action.
Working on the Smart Home Security System project has been an enlightening journey into the world of IoT. This experience taught me the intricacies of integrating hardware and software to create a functional, real-world application. I've gained valuable insights into how IoT technologies can simplify and enhance our daily lives, especially in terms of home security. The project not only honed my technical skills but also demonstrated the practical impact of IoT in making our homes safer and more connected. It's a testament to how technology can be leveraged to create solutions that are both innovative and highly relevant to modern living.