Table of Contents

Environment monitor with ESP32

Student: Șerban Remus
Video: https://www.youtube.com/watch?v=ozBD9OhMsT0
Project archive: iot_project.zip

1. Description

The purpose of the project is to develop an Environment Monitor using three different sensors In this project I used a temperature and humidity sensor, an gas sensor, a IR sensor and ESP32-WROOM Dev Board which is storing the data from the sensor and holds the webserver. The temperature and humidity are displayed on a web server held by the ESP32, which establishes the connection with the router inside the room, and when a gas leak is detected or a movement in front of the IR sensor an email is generated.

2. Hardware Description

The components used in this project are:

3. Software Implementation

The code begin with initialization of the the modules used in the project. First, the HTU21D sensor is initialized and the pins used for the rest of the sensor. Following that the function which handle the WiFi connection is called. Once the connection is establish, the files used for the server is upload from the flash memory of the ESP32 (The files was uploaded using SPIFFS library). Next step is the infinite loop where the data from the sensor are being read. The update of the server is made once at every 10 seconds. If the IR sensor detect a movement or the gas sensor detect a high value of the gas in the room, the module will send a request to the IFTTT, which will trigger an email.

The source code is represented below:

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "SPIFFS.h"
#include <Arduino_JSON.h>
#include <SparkFunHTU21D.h>
#include <Adafruit_Sensor.h>

#define LED 2
#define GAS_SENSOR_A 39
#define GAS_SENSOR_D 36
#define IR_SENSOR 34

int ir_var = 1;
int gassensorAnalog = 0;

const char* ssid = "DIGI-8779";
const char* password = "CdanaM2587";
const char* host = "maker.ifttt.com";
const char* apiKey = "f4i315_kOXujKT6W1SKEmU-kDSi50glvXXXXXXXXXX";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Create an Event Source on /events
AsyncEventSource events("/events");

// Json Variable to Hold Sensor Readings
JSONVar readings;

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 10000;

int lock = 0, lock_gas = 0 ;

// Create a sensor object
HTU21D myHumidity; // BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)

// Init HTU21D
void initHTU21D(){
    myHumidity.begin();
}

// Get Sensor Readings and return JSON object
String getSensorReadings(){
  readings["temperature"] = String(myHumidity.readTemperature());
  readings["humidity"] =  String(myHumidity.readHumidity());
  String jsonString = JSON.stringify(readings);
  return jsonString;
}

// Initialize SPIFFS
void initSPIFFS() {
  if (!SPIFFS.begin()) {
    Serial.println("An error has occurred while mounting SPIFFS");
  }
  Serial.println("SPIFFS mounted successfully");
}

// Initialize WiFi
void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
}

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);
  initHTU21D();
  initWiFi();
  initSPIFFS();

  pinMode(LED, OUTPUT);
  pinMode(GAS_SENSOR_A, INPUT);
  pinMode(IR_SENSOR, INPUT);

  // Web Server Root URL
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });

  server.serveStatic("/", SPIFFS, "/");

  // Request for the latest sensor readings
  server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){
    String json = getSensorReadings();
    request->send(200, "application/json", json);
    json = String();
  });

  events.onConnect([](AsyncEventSourceClient *client){
    if(client->lastId()){
      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
    }
    // send event with message "hello!", id current millis
    // and set reconnect delay to 1 second
    client->send("hello!", NULL, millis(), 10000);
  });
  server.addHandler(&events);

  // Start server
  server.begin();
}

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    // Send Events to the client with the Sensor Readings Every 10 seconds
    events.send("ping",NULL,millis());
    events.send(getSensorReadings().c_str(),"new_readings" ,millis());
    digitalWrite(LED, !digitalRead(LED));
    lock = 0;
    lastTime = millis();
  }

  if(!lock)
  {
    ir_var = digitalRead(IR_SENSOR);
    if(ir_var == LOW)
    {
      lock = 1;
      Serial.print("Motion detect");
      Serial.print("connecting to ");
      Serial.println(host);
      WiFiClient client;
      const int httpsPort = 80;
      if (!client.connect(host, httpsPort)) {
        Serial.println("connection failed");
        return;
      }

      String url = "/trigger/motion_detect/with/key/";
      url += apiKey;

      Serial.print("Requesting URL: ");
      Serial.println(url);
      client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP32\r\n" +
               "Connection: close\r\n\r\n");

      Serial.println("request sent");
      while (client.connected()) {
        String line = client.readStringUntil('\n');
        if (line == "\r") {
          Serial.println("headers received");
          break;
        }
      }
      String line = client.readStringUntil('\n');
      Serial.println("reply was:");
      Serial.println("==========");
      Serial.println(line);
      Serial.println("==========");
      Serial.println("closing connection");
      
    }
    if(!lock_gas)
    {
      gassensorAnalog = analogRead(GAS_SENSOR_A);
      
      if(gassensorAnalog > 700)
      {
        lock_gas = 1;
        Serial.print("connecting to ");
      Serial.println(host);
      WiFiClient client;
      const int httpsPort = 80;
      if (!client.connect(host, httpsPort)) {
        Serial.println("connection failed");
        return;
      }

      String url = "/trigger/gas_detect/with/key/";
      url += apiKey;

      Serial.print("Requesting URL: ");
      Serial.println(url);
      client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP32\r\n" +
               "Connection: close\r\n\r\n");

      Serial.println("request sent");
      while (client.connected()) {
        String line = client.readStringUntil('\n');
        if (line == "\r") {
          Serial.println("headers received");
          break;
        }
      }
      String line = client.readStringUntil('\n');
      Serial.println("reply was:");
      Serial.println("==========");
      Serial.println(line);
      Serial.println("==========");
      Serial.println("closing connection");
      }
    }
    
  }
  
}

The web server look like this:

4. Conclusions

The purpose of this project was to implement a system which is capable of collecting data from multiple sensors from an indoor room, to display the data collected on a web server and to warning the user in case of a motion or a gas detection. The project can be improved by adding more sensors, a microphone, the capability to send SMS. The project help me to understand how to run a web server on the ESP32, how to trigger an email using IFTTT.

5. Resources

*https://randomnerdtutorials.com/esp32-web-server-gauges/
*https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/
*https://diyi0t.com/esp32-tutorial-what-do-you-have-to-know-about-the-esp32-microcontroller/
*https://diyi0t.com/mq2-gas-sensor-arduino-esp8266-esp32/
*https://ifttt.com/