author Dinu Diana-Gabriela ACES 2021
The purpose of the project is to create a smart security system.
The security alarm does not provide audio feedback when movement is detected. The owner can turn the alarm on and off without physical access to the system, but rather via a web page. When turned on, if the security system detects movement it will notify the owner with an E-mail and will update the web page as well.
The Security System consists of:
The hardware consists of:
Besides the main components mentioned above, a breadboard and wires were also used in the making of this project. The electrical schematic of the project can be seen below. [The diagram was made using circuit.io]
For software development, the Arduino IDE was used.
The main libraries used are:
The main functionality of the page is sketched in the diagram below.
When the program is uploaded to the board, it will start the setup process. During the setup it will initialize the board, the GPIO pins, it will connect to the Wi-fi Network and setup the web server. It will also get the local time, this is used for serial monitor debug.
After the setup is complete, regarding the Web server the following things will happen:
In parallel, the following things will happen, as per the diagram above:
The HTML code for teh web page is inserted below. Part of the code is edited out for saving space in the documentation, as it is not important functionality wise. Below we can see the placeholders for the button which will turn the system on and OFF and also for the live feedback of the motion status (if there is movement or not). The IDs for these placeholders and how they should be interpreted is mentioned in the script part of the page. The setInterval function will be called each 9.9 seconds to interrogate the state of the motions sensor. This time was chosen because the state machine is made to change the internal state on every 10 seconds, therefore sampling this every 9.9 ensures we will get a match for the least number of interrogations.
<body> <h2>ESP Security System</h2><br> <img src="secure" width="90" height="90"/><br> %BUTTONPLACEHOLDER%<br> <h3>Sensor Value:<span id="sensors">%MOTIONPLACEHOLDER%</span></h3><br> <script> function toggleCheckbox(element) { var xhr = new XMLHttpRequest(); if(element.checked){ xhr.open("GET", "/update?output="+element.id+"&state=1", true); } else { xhr.open("GET", "/update?output="+element.id+"&state=0", true); } xhr.send(); } setInterval(function ( ) { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("sensors").innerHTML = this.responseText; } }; xhttp.open("GET", "/sensors", true); xhttp.send(); }, 9900 ) ; </script>
In order to replace the placeholders, the processor function was created. In here we define the html code structure to be replaced in the html page, based on the IDs and the information received/requested.
String processor(const String& var){ if(var == "BUTTONPLACEHOLDER"){ String buttons = ""; //change the state of the onboard LED (2) buttons += "<h4>System State OFF/ON</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" " + outputState(2) + "><span class=\"slider\"></span></label>"; return buttons; } if(var == "MOTIONPLACEHOLDER"){ String buttons = ""; if(startTimer == true){ buttons += "<h4 style=\"color:red;\">MOTION DETECTED!</h4>"; } else { buttons += "<h4>Motion not detected</h4>"; } return buttons; } return String(); }
In order to initialize the web page, the following code was placed in the setup() function to initialize the motion state message and the state of the switch.
server.on("/sensors", HTTP_GET, [] (AsyncWebServerRequest *request) { if(startTimer == true){ request->send(200, "text/html", "<h4 style=\"color:red;\">MOTION DETECTED!</h4>"); } else { request->send(200, "text/html", "<h4>Motion not detected</h4>"); } }); // Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2> server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) { String inputMessage1; String inputMessage2; // GET input1 value on <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2> if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) { inputMessage1 = request->getParam(PARAM_INPUT_1)->value(); inputMessage2 = request->getParam(PARAM_INPUT_2)->value(); digitalWrite(inputMessage1.toInt(), inputMessage2.toInt()); } else { inputMessage1 = "No message sent"; inputMessage2 = "No message sent"; } if(inputMessage2 == "0"){ Serial.print("Security system is OFF \n\n"); Sec_Sys_State = "off"; } else { if(inputMessage2 == "1"){ Serial.print("Security system is ON \n\n"); Sec_Sys_State = "on"; }} request->send(200, "text/plain", "OK"); });
In order to place an image in the web page, SPIFFS was used. The image is uploaded to the board before uploading the code to the board. The image is placed in a separate folder names data.
When all of this is put together, the web page will look like in the screenshots below.
Side by side image of web page when the system is OFF, and when the system was turned ON and motion was detected.
In order to detect the input of the PIR sensor and detect the moments where movement happens, an interrupt was attached to a positive edge of the pin where the output of the PIR sensor was connected. This can be seen in the code selection below.
// Checks if motion was detected, sets LED HIGH and starts a timer void IRAM_ATTR detectsMovement() { if(Sec_Sys_State == "on"){ Serial.println("MOVEMENT DETECTED!!!"); digitalWrite(LED, HIGH); startTimer = true; lastTrigger = millis(); printLocalTime(); MOVEMENT = true; } } [...] void setup(){ [...] // PIR Motion Sensor mode INPUT_PULLUP pinMode(motionSensor, INPUT_PULLUP); // Set motionSensor pin as interrupt, assign interrupt function and set RISING mode attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING); [...] }
There have been a few issues met in the making of this project.
The first problem was related to the type of web page. In the beginning a synchronous web page was used. This did not allow the usage of images. In order to fix this and give more information in the web page, a asynchronous type web page was used.
There have also been a few issues with the sensor. The main problem was receiving false movement detection. This was because of small crowded spaces, or my presence near the sensor, but most probably is was due to the monitors, which were placed in close proximity of the sensor. The monitors do emit some amount of IR light, so this might have been messing with the PIR sensor. This is not a real issue in real life applications, but it was troubling when the demo was filmed, as the system needed to be close to a monitor in order to show the web page, received emails and debug information. This was solved in the demo by inclining the board of the system, slightly away from the monitor.
Overall I would say the challenges have been surpassed and that the project works well.
In conclusion, the project successfully implements a security system which can alert the user of unexpected movement close to the system. The project shows how smart systems can be implemented in our day to day life.
Despite the challenges that appeared along the way, this project was helpful in teaching us how we can implement our own smart systems without spending a fortune.
Documentation sources
1. Passive infrared sensor - Wikipedia
3. Electrical schematic tool - circuito.io
4. State machine diagram - draw.io
Components
1. Cleste
Libraries
2. AsyncTCP and ESPAsyncWebServer
4. Attaching interrupt routines
Download the Source code