How to Create an Indoor Temperature, Humidity, and Air Quality Monitoring System with ESP32-C6

Poor indoor air quality can lead to health problems. An indoor environment monitoring system based on the FireBeetle 2 ESP32-C6 IoT Development Board and other open-source hardware platforms is not only easy to configure and assemble but also more cost-effective than many commercial air monitoring systems. This tutorial will guide you through building an indoor environment monitoring system using the ESP32 development board, SHT31 temperature and humidity sensor, ENS160 air quality sensor, and a lithium battery. You'll be able to monitor and record indoor temperature, humidity, air quality index (AQI), volatile organic compounds (VOCs), and eCO2 in real-time.

 

An indoor environment monitoring system
HARDWARE LIST
1 FireBeetle ESP32-C6
1 Fermion: SHT31 Digital Temperature & Humidity Sensor
1 Fermion: ENS160 Air Quality Sensor
1 Lithium Battery

Hardware Connections

 

 Wiring Diagrams of FireBeetle ESP32 C6, Temperature & Humidity Sensor, and air quality sensor
Wiring Diagrams of FireBeetle ESP32 C6, Temperature & Humidity Sensor, and air quality sensor

Data Collection and Processing

The ESP32 microcontroller serves as the core processing unit, responsible for collecting sensor data, processing and analyzing it, and transmitting the data wirelessly to a server. The software logic includes:

 1. Battery Voltage Collection:

    - Use the ESP32 IO0 pin to collect battery voltage.

    - Convert the collected analog voltage signal to a digital signal via ADC for further processing.

 2. Temperature, Humidity, and Air Quality Data Collection:

    - Use the ESP32's I2C to read data from the sensors.

 3. Data Reporting:

    - Connect to a wireless network using the ESP32 WiFi module.

    - Report the collected data to a server via HTTP for remote monitoring and management.

 

Sample code

CODE
#include <WiFi.h>
#include <HTTPClient.h>
#include <DFRobot_SHT3x.h>
#include <DFRobot_ENS160.h>

DFRobot_SHT3x   sht3x;
DFRobot_ENS160_I2C ENS160(&Wire, /*iicAddr*/ 0x53);

// #define DATA_SEND_INTERVAL_MS 15 * 60 * 1000
#define DATA_SEND_INTERVAL_MS 60 * 1000

int lastDataSentTimestamp = 0;
unsigned long previousMillis = 0;
unsigned long interval = 30000;

// WiFi network information
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

// Server URL
const char* serverName = "http://192.168.1.236:5000/update";
const char* serverToken = "your_influx_token";

// Define ADC pin
const int batteryPin = 0; // IO0

void sendData() {
  // Collect battery voltage
  int batteryVoltage = analogReadMilliVolts(batteryPin)*2;
  Serial.print("BAT millivolts value = ");
  Serial.print(batteryVoltage);
  Serial.println("mV");
  
  // Collect temperature and humidity
  float temperature = sht3x.getHumidityRH();
  Serial.print("Temperature(C):");
  Serial.println(temperature);
  
  float humidity = sht3x.getTemperatureC();
  Serial.print("Humidity(RH):");
  Serial.println(humidity);

  
  // Collect air quality
  ENS160.setTempAndHum(temperature, humidity);
  
  uint8_t AQI = ENS160.getAQI();
  Serial.print("AIQ : ");
  Serial.println(AQI);
  
  uint16_t TVOC = ENS160.getTVOC();
  Serial.print("TVOC(ppb): ");
  Serial.println(TVOC);
  
  uint16_t ECO2 = ENS160.getECO2();
  Serial.print("ECO2(ppm): ");
  Serial.println(ECO2);
  
  // Create HTTP client
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(serverName);
    http.addHeader("Content-Type", "text/plain");
    http.addHeader("authorization", serverToken);
    // Create POST data
    String httpRequestData = "batteryVoltage=" + String(batteryVoltage) + "&Temperature=" + String(temperature) + "&Humidity=" + String(humidity) + "&AIQ=" + String(AQI) + "&TVOC=" + String(TVOC) + "&ECO2=" + String(ECO2);
    
    
    // Send HTTP POST request
    int httpResponseCode = http.POST(httpRequestData);
    
    // Print response result
    if (httpResponseCode > 0) {
      String response = http.getString();
      Serial.println(httpResponseCode);
      Serial.println(response);
    } else {
      Serial.print("Error on sending POST: ");
      Serial.println(httpResponseCode);
    }
    // End HTTP request
    http.end();
  }
}

void setup() {
  Serial.begin(115200);
  // Initialize SHT31
  while (sht3x.begin() != 0) {
    Serial.println("SHT31 error");
    delay(1000);
   }
  // Initialize ENS160
  while( NO_ERR != ENS160.begin() ){
    Serial.println("ENS160 error");
    delay(1000);
  }
  ENS160.setPWRMode(ENS160_STANDARD_MODE);
  
  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  sendData();
}

void loop() {
  unsigned long currentMillis = millis();
  // if WiFi is down, try reconnecting
  if ((WiFi.status() != WL_CONNECTED) && (currentMillis - previousMillis >= interval)) {
    Serial.print(millis());
    Serial.println("Reconnecting to WiFi...");
    WiFi.disconnect();
    WiFi.reconnect();
    previousMillis = currentMillis;
  }
  if (millis() > lastDataSentTimestamp + DATA_SEND_INTERVAL_MS) {
    sendData();

    Serial.print("Millis since last measurement: ");
    Serial.println(millis() - lastDataSentTimestamp);
    lastDataSentTimestamp = millis();
  }
}

 

Server Setup

 1. Install Python 3.

 2. Install Flask:

    - Press Win+R, type cmd, and open the command prompt.

    - Enter pip install flask to install Flask.

 3. Run the Python code in the command line.

CODE
from flask import Flask, request, jsonify

app = Flask(__name__)

# Endpoint to handle data from Arduino
@app.route('/update', methods=['POST'])
def update():
    auth_header = request.headers.get('authorization')
    if (auth_header == 'your_influx_token'):
        data = request.data.decode('utf-8')
        print(f"Received data: {data}")
        # Process the data sent from Arduino here, such as storing it in a database
        return jsonify({"status": "success", "message": "Data received"}), 200
    else:
        return jsonify({"status": "error", "message": "Unauthorized"}), 401

@app.route('/')
def home():
    return "Hello from Flask server!", 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

 

Now you can check the data:

 

Learn More About the Data:

For more information on interpreting air quality data, refer to: ENS160 Air Quality Sensor Wiki

Project Expansion

The onboard GDI interface allows for easy connection to screens, ensuring efficient data visualization. Detailed screen lists and configuration tutorials are provided to facilitate seamless integration of ESP32-C6 functionalities into any setup.

DFRobot's all Gravity and Fermion series sensors are compatible with the FireBeetle 2 ESP32-C6, offering a comprehensive selection for various projects.

Conclusion

This guide details the design and implementation of an indoor environment monitoring system based on the ESP32 development board, SHT31 temperature and humidity sensor, ENS160 air quality sensor, and a lithium battery. By integrating these advanced hardware devices and IoT technology, we successfully achieved real-time monitoring and data analysis of key indoor air quality parameters.

License
All Rights
Reserved
licensBg
0