Elijah Maluleke
Published © GPL3+

Community Hall Traffic and Air Quality Control IoT Project

Smart Community Hall Traffic and Air Quality Control IoT project counts the number of people in the hall and measures CO2 and Temperature.

IntermediateWork in progressOver 7 days261
Community Hall Traffic and Air Quality Control IoT Project

Things used in this project

Hardware components

Wio Terminal
Seeed Studio Wio Terminal
×1
Grove - LoRa Radio 868MHz
Seeed Studio Grove - LoRa Radio 868MHz
×1
Siren Transducer, 12VDC
Siren Transducer, 12VDC
×1
General Purpose Transistor NPN
General Purpose Transistor NPN
×3
5 mm LED: Red
5 mm LED: Red
×2
5 mm LED: Yellow
5 mm LED: Yellow
×1
5 mm LED: Green
5 mm LED: Green
×1
Resistor 1k ohm
Resistor 1k ohm
×7
Male Header 40 Position 1 Row (0.1")
Male Header 40 Position 1 Row (0.1")
×1
Female Header 20 Position 2 Row (0.1")
Female Header 20 Position 2 Row (0.1")
×1
DC POWER JACK 2.1MM BARREL-TYPE PCB MOUNT
TaydaElectronics DC POWER JACK 2.1MM BARREL-TYPE PCB MOUNT
×1
SparkFun USB Type A Female Breakout
SparkFun USB Type A Female Breakout
×1
1N4007 – High Voltage, High Current Rated Diode
1N4007 – High Voltage, High Current Rated Diode
×20
Test Accessory, Power Adapter
Test Accessory, Power Adapter
×1
Grove - I2C High Accuracy Temp&Humi Sensor (SHT35)
Seeed Studio Grove - I2C High Accuracy Temp&Humi Sensor (SHT35)
×1

Software apps and online services

Arduino IDE
Arduino IDE
Edge Impulse Studio
Edge Impulse Studio

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
PCB Holder, Soldering Iron
PCB Holder, Soldering Iron
Solder Wire, Lead Free
Solder Wire, Lead Free
Solder Dispenser, Solder-Mate
Solder Dispenser, Solder-Mate
Mini Side Cutter, 120mm Length with 25mm Jaw Capacity
Mini Side Cutter, 120mm Length with 25mm Jaw Capacity
Plier, Long Nose
Plier, Long Nose
10 Pc. Jumper Wire Kit, 5 cm Long
10 Pc. Jumper Wire Kit, 5 cm Long

Story

Read more

Schematics

Schematic_SmartHallTraffic_AirQualityControlIoTProject_2022-09-26

Code

SmartHallTrafficandAirQualityControlIoTProject.ino

C/C++
/********************************************************************************
 *
 ********************************************************************************/
#include <Arduino.h>
#include <SensirionI2CSht4x.h>
#include <Wire.h>
#include <SPI.h>        // 
#include <TFT_eSPI.h>   // Hardware-specific library
#include "Seeed_FS.h"   // Including SD card library
#include "RawImage.h"   // Including image processing library
#include "sensirion_common.h"
#include "sgp30.h"
#include "Seeed_Arduino_GroveAI.h"

/********************************************************************************
 *
 ********************************************************************************/
TFT_eSPI tft;
TFT_eSprite spr = TFT_eSprite(&tft); //Initializing buffer
SensirionI2CSht4x sht4x;
GroveAI ai(Wire);
uint8_t state = 0;
float temperature;
float humidity;
//Soil Moisture Sensor definitions
int sensorPin = A1; //Define variable to store soil moisture sensor pin
int sensorValue = 0; //Define variable to store soil moisture sensor value
uint16_t error;
char errorMessage[256];
uint32_t serialNumber;
u16 tvoc_ppb, co2_eq_ppm;

/********************************************************************************
 *
 ********************************************************************************/
void HumidityTemperature();
void Draw_Images(void);
void Buzzer(void);
void GasSensor(void);
void GasSensorSetup(void);
void GroveAISetup(void);
void GroveAIModule(void);
void DisplayData(void);

/********************************************************************************
 *
 ********************************************************************************/
void setup() {
  pinMode(WIO_LIGHT, INPUT); //Set light sensor pin as INPUT
  pinMode(WIO_BUZZER, OUTPUT); //Set buzzer pin as OUTPUT
  pinMode(BUTTON_1, INPUT);
  pinMode(BUTTON_2, INPUT);
  pinMode(BUTTON_3, INPUT);
  pinMode(BCM12, OUTPUT);
  pinMode(BCM16, OUTPUT);
  pinMode(BCM22, OUTPUT);
  //
  digitalWrite(BCM12, LOW);
  digitalWrite(BCM16, LOW);
  digitalWrite(BCM22, LOW);
  
  //
  Serial.begin(115200);
  Serial.println("serial start!!");
  
  // Initialise SD card
  if (!SD.begin(SDCARD_SS_PIN, SDCARD_SPI)) {
    //while (1);
  }
  tft.begin();
  tft.setRotation(3);
  Draw_Images();

  Wire.begin();
  sht4x.begin(Wire);
  error = sht4x.serialNumber(serialNumber);
  if (error) {
    Serial.print("Error trying to execute serialNumber(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } else {
    Serial.print("Serial Number: ");
    Serial.println(serialNumber);
  }
  spr.createSprite(TFT_HEIGHT,TFT_WIDTH); //Create buffer
  GasSensorSetup();
  GroveAISetup();
}

/********************************************************************************
 *
 ********************************************************************************/
void loop() {
  DisplayData(); 
  HumidityTemperature();
  GasSensor();
  GroveAIModule();
}

/********************************************************************************
 *
 ********************************************************************************/
void HumidityTemperature() {
  delay(1000);
  error = sht4x.measureHighPrecision(temperature, humidity);
  if (error) {
    Serial.print("Error trying to execute measureHighPrecision(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } else {
    Serial.print("Temperature:");
    Serial.print(temperature);
    Serial.print("\t");
    Serial.print("Humidity:");
    Serial.println(humidity);
    }
} 

/********************************************************************************
 *
 ********************************************************************************/
void GasSensorSetup(void) {
    s16 err;
    u32 ah = 0;
    u16 scaled_ethanol_signal, scaled_h2_signal;
    
    /*For wio link!*/
    #if defined(ESP8266)
    pinMode(15, OUTPUT);
    digitalWrite(15, 1);
    Serial.println("Set wio link power!");
    delay(500);
    #endif
    /*  Init module,Reset all baseline,The initialization takes up to around 15 seconds, during which
        all APIs measuring IAQ(Indoor air quality ) output will not change.Default value is 400(ppm) for co2,0(ppb) for tvoc*/
    while (sgp_probe() != STATUS_OK) {
        Serial.println("SGP failed");
        while (1);
    }
    /*Read H2 and Ethanol signal in the way of blocking*/
    err = sgp_measure_signals_blocking_read(&scaled_ethanol_signal,
                                            &scaled_h2_signal);
    if (err == STATUS_OK) {
        Serial.println("get ram signal!");
    } else {
        Serial.println("error reading signals");
    }

    //ah=get_relative_humidity();
    /*
        The function sgp_set_absolute_humidity() need your own implementation
    */
    //sgp_set_absolute_humidity(ah);
    // Set absolute humidity to 13.000 g/m^3
    //It's just a test value
    sgp_set_absolute_humidity(13000);
    err = sgp_iaq_init();
    //
}

/********************************************************************************
 *
 ********************************************************************************/
void GasSensor(void) {
    s16 err = 0;
    err = sgp_measure_iaq_blocking_read(&tvoc_ppb, &co2_eq_ppm);
    if (err == STATUS_OK) {
        Serial.print("tVOC  Concentration:");
        Serial.print(tvoc_ppb);
        Serial.println("ppb");

        Serial.print("CO2eq Concentration:");
        Serial.print(co2_eq_ppm);
        Serial.println("ppm");
    } else {
        Serial.println("error reading IAQ values\n");
    }
    delay(1000);
}

/********************************************************************************
 *
 ********************************************************************************/
void GroveAISetup(void) {
  if (ai.begin(ALGO_OBJECT_DETECTION, MODEL_EXT_INDEX_1)) { // Object detection and pre-trained model 1
    Serial.print("Version: ");
    Serial.println(ai.version());
    Serial.print("ID: ");
    Serial.println( ai.id());
    Serial.print("Algo: ");
    Serial.println( ai.algo());
    Serial.print("Model: ");
    Serial.println(ai.model());
    Serial.print("Confidence: ");
    Serial.println(ai.confidence());
    state = 1;
  }
  else {
    Serial.println("Algo begin failed.");
  }
}

/********************************************************************************
 *
 ********************************************************************************/
void GroveAIModule(void) {
  if (state == 1) {
    uint32_t tick = millis();
    if (ai.invoke()) { // begin invoke
      while (1) { // wait for invoking finished
        CMD_STATE_T ret = ai.state(); 
        if (ret == CMD_STATE_IDLE) {
          break;
        }
        delay(20);
      }

     uint8_t len = ai.get_result_len(); // receive how many people detect
     if(len) {
       int time1 = millis() - tick; 
       Serial.print("Time consuming: ");
       Serial.println(time1);
       Serial.print("Number of people: ");
       Serial.println(len);
       object_detection_t data;       //get data

       for (int i = 0; i < len; i++) {
          Serial.println("result:detected");
          Serial.print("Detecting and calculating: ");
          Serial.println(i+1);
          ai.get_result(i, (uint8_t*)&data, sizeof(object_detection_t)); //get result
  
          Serial.print("confidence:");
          Serial.print(data.confidence);
          Serial.println();
        }
     }
     else {
       Serial.println("No identification");
     }
    }
    else {
      delay(1000);
      Serial.println("Invoke Failed.");
    }
  }
  else {
    state == 0;
  }
}

/********************************************************************************
 *
 ********************************************************************************/
void DisplayData(void) {
  float t = temperature; //Assign variable to store temperature 
  float h = humidity; //Assign variable to store humidity 
  int light = analogRead(WIO_LIGHT); //Assign variable to store light sensor values

  //Setting the title header 
  spr.fillSprite(TFT_WHITE); //Fill background with white color
  spr.fillRect(0,0,320,50,TFT_DARKGREEN); //Rectangle fill with dark green 
  spr.setTextColor(TFT_WHITE); //Setting text color
  spr.setTextSize(2); //Setting text size 
  spr.drawString("Smart Hall Traffic and",20,4); //Drawing a text string 
  spr.drawString("Air Quality Control IoT",20,25); //Drawing a text string 
  
  spr.drawFastVLine(150,50,190,TFT_DARKGREEN); //Drawing verticle line
  spr.drawFastHLine(0,140,320,TFT_DARKGREEN); //Drawing horizontal line

  //Setting temperature
  spr.setTextColor(TFT_BLACK);
  spr.setTextSize(2);
  spr.drawString("Temperature",10,65);
  spr.setTextSize(3);
  spr.drawNumber(t,50,95); //Display temperature values 
  spr.drawString("C",90,95);

  //Setting humidity
  spr.setTextSize(2);
  spr.drawString("Humidity",25,160);
  spr.setTextSize(3);
  spr.drawNumber(h,30,190); //Display humidity values 
  spr.drawString("%RH",70,190);

  //Setting TVOC
  tvoc_ppb = map(sensorValue,1023,400,0,100); //Map sensor values 
  spr.setTextSize(2);
  spr.drawString("TVOC",200,65);
  spr.setTextSize(3);
  spr.drawNumber(tvoc_ppb,200,95); //Display sensor values as percentage  
  spr.drawString("ppb",260,95);
  
  //Setting CO2eq 
  spr.setTextSize(2);
  spr.drawString("CO2eq",200,160);
  spr.setTextSize(3);
  //co2_eq_ppm = map(co2_eq_ppm,0,1023,0,100); //Map sensor values 
  spr.drawNumber(co2_eq_ppm,205,190); //Display sensor values as percentage  
  spr.drawString("ppm",260,190);

  //Condition for 
  if(co2_eq_ppm > 700){
    spr.fillSprite(TFT_RED);
    spr.drawString("Time to Ventilate!",5,100);
    Buzzer(); 
    digitalWrite(BCM12, HIGH);
    digitalWrite(BCM16, HIGH);
    digitalWrite(BCM22, HIGH);
  }
  else if(co2_eq_ppm <= 400) {
    digitalWrite(BCM12, LOW);
    digitalWrite(BCM16, LOW);
    digitalWrite(BCM22, LOW);
  }
  spr.pushSprite(0,0); //Push to LCD
  delay(50);
}

/********************************************************************************
 *
 ********************************************************************************/
void Draw_Images(void){
  drawImage<uint16_t>("IoTintoTheWildContest1.bmp", 0, 0); //Display this 8-bit image in sd card from (0, 0)
  delay(5000);
  drawImage<uint16_t>("5BiggestRealWorldChallengesToTackle.bmp", 0, 0); //Display this 8-bit image in sd card from (0, 0)
  delay(5000);  
}
  
/********************************************************************************
 *
 ********************************************************************************/
void Buzzer(void) {
  analogWrite(WIO_BUZZER, 128);
  delay(1000);
  analogWrite(WIO_BUZZER, 0);
  delay(1000);
}

/********************************************************************************
 *
 ********************************************************************************/
  

Credits

Elijah Maluleke

Elijah Maluleke

4 projects • 25 followers

Comments