Table of Contents

Security System with ESP32

author Dinu Diana-Gabriela ACES 2021

Video Demo

1. Project Objective

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.

2. Project Description

The Security System consists of:

3. Hardware Description

The hardware consists of:

  1. ESP32 Development Board - The ESP32 Development Board is a system development board powered by ESP-WROOM-32 module. The ESP-WROOM-32 is a powerful and compact module that combines Wi-Fi and Bluetooth to support a wide range of applications that require wireless and internet connectivity [2]. The Wi-fi support, discreet size and price range made it perfect for this application.

 ESP32 Development Board

  1. PIR sensor - A Passive Infrared Sensor was used to detect the movement. It is an electronic sensor that measures infrared light coming from objects in its field of view. This type of sensor is widely used in security alarms. [1] The sensor picked has a delay of 8 seconds between changing its output. It can be powered from the 5V pin of the ESP32 board. It has an output voltage of 3.3V which can be read by the ESP32 board. It can detect movement at a maximum distance of 3m.

 PIR sensor

  1. LEDs for visual feedback - the onboard LED of the ESP32 Development board is used for showing that the security system has the motion detection on or off. An external LED is also used to show if the Security System detected movement. In order to use the external LED, an additional resistor is also needed.

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]

 Board connections

4. Software Description

For software development, the Arduino IDE was used.

Libraries

The main libraries used are:

Functionality Breakdown

The main functionality of the page is sketched in the diagram below.

 Security System Diagram

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:

Code Breakdown

The Web page

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

Side by side image of web page when the system is OFF, and when the system was turned ON and motion was detected.

Motion Detection

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);
[...]
}

5. Issues and solutions

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.

6. Conclusions

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.

Bibliography

Documentation sources

1. Passive infrared sensor - Wikipedia

2. ESP32 Development board

3. Electrical schematic tool - circuito.io

4. State machine diagram - draw.io

Components

1. Cleste

2. OptimusDigital

Libraries

1. File uploader plugin

2. AsyncTCP and ESPAsyncWebServer

3. ESP32_MailClient

4. Attaching interrupt routines


Download the Source code

Source code