Office Environment Monitor of Arduino

by Lan_Makerfabs in Circuits > Arduino

2240 Views, 28 Favorites, 0 Comments

Office Environment Monitor of Arduino

results.jpg

Hello everyone, this is Makerfabs! Recently we moved our company in a new Science and Technology Industrial Park.

However, we meet an awful thing that we can Smell a strong pungent odor at sometimes. We think one of the nearby factories is secretly releasing pollutants. Then we want to verified my idea by using sensors. We all knew that too much pollutants in the air would affect our health. Our colleagues also felt a little dizzy, so we decided to measure the content of TVOC[1] in the air first to confirm our idea. 

We will open source all of this project, and you can try to measure the TVOC in your own environment.

Supplies

This ESP32-S3 board is configured 3.5" 320x480 TFT LCD to driver ILI9488, it uses 16bits parallel line for communication with ESP32-S3, the main clock could be up to 20MHz. And it has two Mabee ports can be use.

 

Mabee CO2 module is an air quality monitor. Based on SGP30, this module provides TVOC (Total Volatile Organic Compounds) and CO2eq output; Based on the Sensirion temperature/ humidity sensors SHT31, it output highest accuracy ±2% relative humidity and ±0.3°C accuracy temperature.

 

  • The reason I use this sensor is that: in the hardware design, as the SGP30 heat the air/ board in the testing, the slot is designed to isolate the 2 sensors, to ensure the SHT31 measures the true environment humidity/ temperature. and TVOC measurement use a Simplified algorithm. we can as for as possible convenience to check the Environment.


Hardware Assembly

assembly2.jpg
assembly.jpg

1.The Mabe CO2 sensor use I2C for communication with controller. The IC2 address of SGP30 is 0x58, The IC2 address of SHT10 is 0x44, while The ESP32-S2 Parallel TFT has build-on connectors(I2C/GPIO) for external sensors, so it can communicate with the Mabee CO2 by I2C. in the code , you just need initialize the I/O pin to achieve it.

 

2. Using the Mabee cable to connect the ESP32-S3 Parallel 4.3 TFT with Touch and Mabee CO2. the usb connect PC and the Touch.


Software

We use the ili9488 driver to display measurement in the screen, and we want to make the colleague can see the measure result where in Another office. So, we try to use a web page to display the measured data, in the LAN. To achieve the function, we use the ESPAsyncWebServer library and ESPAsyncTCP library in GitHub.


Get the code in GitHub.


Declare the WebServer object.

AsyncWebServer server(80);
AsyncEventSource events("/events");


The request is called in the callback function (AsyncWebServerRequest), the object is the user request, we can acquire a lot of information through this object, such as the following basic information:

request->version();       // uint8_t: 0 = HTTP/1.0, 1 = HTTP/1.1

request->method();        // enum:    HTTP_GET, HTTP_POST, HTTP_DELETE, HTTP_PUT, HTTP_PATCH, HTTP_HEAD, HTTP_OPTIONS

// HTTP_GET = 0b00000001, HTTP_POST = 0b00000010, HTTP_DELETE = 0b00000100, HTTP_PU = 0b00001000, HTTP_PATCH = 0b00010000, HTTP_HEAD = 0b00100000, HTTP_OPTIONS = 0b01000000, HTTP_ANY = 0b01111111

request->url();           // String:  URL of the request (not including host, port or GET parameters)

request->host();          // String:  The requested host (can be used for virtual hosting)

request->contentType();   // String:  ContentType of the request (not avaiable in Handler::canHandle)

request->contentLength(); // size_t:  ContentLength of the request (not avaiable in Handler::canHandle)

request->multipart();     // bool:    True if the request has content type "multipart"



Web page configuration by html.

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>SGP30 Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <link rel="icon" href="data:,">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    p {  font-size: 1.2rem;}
    body {  margin: 0;}
    .topnav { overflow: hidden; background-color: #4B1D3F; color: white; font-size: 1.7rem; }
    .content { padding: 20px; }
    .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
    .cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
    .reading { font-size: 2.8rem; }
    .card.temperature { color: #0e7c7b; }
    .card.humidity { color: #17bebb; }
    .card.tvoc { color: #d62246; }
    .card.gas { color: #3fca6b; }
  </style>
</head>
<body>
  <div class="topnav">
    <h3>R&D Office Environment Monitor</h3>
  </div>
  <div class="content">
    <div class="cards">
      <div class="card temperature">
        <h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>
      </div>
      <div class="card humidity">
        <h4><i class="fas fa-tint"></i> HUMIDITY</h4><p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>
      </div>
      <div class="card tvoc">
        <h4><i class="fas fa-angle-double-down"></i> TVOC</h4><p><span class="reading"><span id="tvoc">%TVOC%</span> ppb</span></p>
      </div>
      <div class="card gas">
        <h4><i class="fas fa-wind"></i> eCO2</h4><p><span class="reading"><span id="gas">%GAS%</span> ppm</span></p>
      </div>
    </div>
  </div>
<script>
if (!!window.EventSource) {
 var source = new EventSource('/events');
 
 source.addEventListener('open', function(e) {
  console.log("Events Connected");
 }, false);
 source.addEventListener('error', function(e) {
  if (e.target.readyState != EventSource.OPEN) {
    console.log("Events Disconnected");
  }
 }, false);
 
 source.addEventListener('message', function(e) {
  console.log("message", e.data);
 }, false);
 
 source.addEventListener('temperature', function(e) {
  console.log("temperature", e.data);
  document.getElementById("temp").innerHTML = e.data;
 }, false);
 
 source.addEventListener('humidity', function(e) {
  console.log("humidity", e.data);
  document.getElementById("hum").innerHTML = e.data;
 }, false);
 
 source.addEventListener('tvoc', function(e) {
  console.log("tvoc", e.data);
  document.getElementById("tvoc").innerHTML = e.data;
 }, false);
 
 source.addEventListener('gas', function(e) {
  console.log("gas", e.data);
  document.getElementById("gas").innerHTML = e.data;
 }, false);
}
</script>
</body>
</html>)rawliteral";

With this html, the web page can set the style to display your measurement and it doesn't just show data.


Return absolute humidity [mg/m^3] with approximation formula. can make the measurement more precise.

uint32_t getAbsoluteHumidity(float temperature, float humidity)
{
    // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
    const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
    const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity);                                                                // [mg/m^3]
    return absoluteHumidityScaled;
}


Check the I/O pin of the esp32-s3 board to search the I2C pin.

#define I2C_SDA_PIN 38
#define I2C_SCL_PIN 39

Test and Result

1.jpg
page1.JPG

In the attachment. we can see the Pollutant standard regulation. As the result, we measure the TVOC is 279 ppb, it means that air quality is not at its well. It's an awful information. It proved our idea was right. We need to seek help from the environmental authorities immediately!