Twitter icon
Facebook icon
LinkedIn icon
Google icon
Reddit icon
StumbleUpon icon
Del.icio.us icon

Arduino Based Air Quality Monitoring IoT Project

Added to IoTplaybook or last updated on: 01/20/2020

Story

Air pollution has become a common phenomenon everywhere. Especially in urban areas, air pollution is a real-life problem. A lot of people get sick only due to air pollution. In the urban areas, the increased number of petrol and diesel vehicles and the presence of industrial areas on the outskirts of the major cities are the main causes of air pollution. The problem is seriously intensified in the metropolitan cities. Also, climate change is now apparent. The governments all around the world are taking every measure in their capacity. Many European countries have aimed to replace petrol and diesel vehicles with electric vehicles by 2030. Even India has aimed to do so by 2025. The use of coal for electricity generation is now going to be a thing of the past. The nations are now focusing to generate energy from nuclear reactors and renewable resources like solar energy, wind energy, and hydroelectric power. 

It is now important to monitor air pollution in real-time in most of the urban areas. This project is aimed at developing an IoT device that can monitor air pollution in real-time and log data to a remote server. Remote monitoring was facilitated using classical motes in the past, which has some pitfalls like limited memory, processing speed and complex programming strategies. By using the Internet of Things and recording sensor data to a remote server, the limitations of memory in the monitoring devices and manual collection of data from the installed devices can be overcome. The IoT also helps to monitor the data in real-time. 

The air pollution monitoring device developed in this project is based on Arduino UNO. The Arduino board connects with the ThingSpeak platform using the ESP8266 Wi-Fi Module. As the cities usually have Wi-Fi hotspots at most of the places, so the device can be easily installed near any hotspot for its operation. The ThingSpeak is a popular IoT platform that is easy to use and program. The sensor used for monitoring air pollution is the MQ-135 gas sensor. The sensor data is also displayed on a character LCD interfaced in the monitoring IoT device. 

The sensing of data and sending it to the ThingSpeak server using the Wi-Fi module is managed by the Arduino Sketch. The Arduino sketch is written, compiled and loaded to the Arduino board using Arduino IDE. 

Circuit Connections

The air pollution monitoring device is built by assembling the following components - 

Arduino based Real-Time Air Pollution Monitoring IOT device Circuit Connections

Arduino UNO - Arduino UNO is one of the most popular prototyping boards. It is small in size and packed with rich features. The board comes with a built-in Arduino boot loader. It is an Atmega 328 based controller board that has 14 GPIO pins, 6 PWM pins, 6 Analog inputs, and onboard UART, SPI and TWI interfaces. In this IoT device, 9 pins of the board are utilized. There are six pins used to interface the character LCD. There are two pins utilized to interface the ESP8266 Wi-Fi Module and an analog input pin is used to connect with the MQ-135 sensor. Learn more about Arduino UNO from ]]>here. ]]>

16X2 Character LCD - The 16X2 LCD display is used to monitor the sensor values read by the Arduino board from MQ-135. It is interfaced with the Arduino UNO by connecting its data pins D4 to D7 with pins 6 down to 3 of the controller respectively. The RS and E pins of the LCD are connected to pins 13 and 12 of the controller respectively. The RW pin of the LCD module is connected to the ground. The circuit connections of the character LCD with the Arduino board are summarized in the following table - 

ESP8266 Wi-Fi Module - The ESP8266 Wi-Fi Module is used to connect with any available internet hotspot and transfer sensor data to ThingSpeak Platform via Wi-Fi. The ESP8266 Wi-Fi Module is a self-contained SOC with integrated TCP/IP protocol stack that can give any microcontroller access to a Wi-Fi network.

The ESP8266 is capable of either hosting an application or offloading all Wi-Fi networking functions from another application processor. Each ESP8266 module comes pre-programmed with an AT command set firmware.  So, one can simply hook this up to an Arduino device. Here it uploads the monitoring data to the cloud. The module comes available in two models - ESP-01 and ESP-12. ESP-12 has 16 pins available for interfacing while ESP-01 has only 8 pins available for use. The ESP-12 has the following pin configuration - 

The ESP-12 model is used in the project. The Reset and VCC pins of the module are connected to the 5V DC while the Ground pin is connected to the common ground. The Tx and Rx pins of the module are connected to the pins 10 and 11 of the Arduino board respectively. The Arduino pins 10 and 11 are configured to the serial receiver and transmitter through software serial function. 

MQ-135 Sensor - MQ-135 is a gas sensor which is used to measure the concentration of combustible gases. It has lower conductivity in clean air while its conductivity increases with the presence of the combustible gases in the air. The sensor is highly sensitive to gases like Ammonia, Sulphide and Benzene steam. The sensor can detect the concentration of combustible gases in a range from 100 PPM to 1000 PPM. 

Sensitivity Curve of MQ-135 Sensor

From the sensitivity curve of the sensor, it can be seen that the resistance of the sensor decreases as the concentration of the target gas is increased in PPM while for clean air its resistance remains constant. In the graph, the Rs is the resistance in target gas and Ro is the resistance in clean air. The graph is shown for Carbon dioxide, Carbon Monoxide, and Ammonia. The sensitivity of this sensor can be adjusted and calibrated to detect specific concentration levels of a target gas. The sensor has four terminals - Ground, VCC, Digital Out and Analog Out. The VCC and Ground terminals of the sensor are connected to the common VCC and Ground. The Analog Output pin of the sensor is connected to the A0 pin of the Arduino. The analog output voltage from the sensor can be assumed directly proportional to the concentration of CO2 gas in PPM under standard conditions. The analog voltage is sensed from the sensor and converted to a digital value in a range from 0 to 1023 by the inbuilt ADC channel of the controller. The digitized value is hence equal to the gas concentration in PPM. 

Power Supply - The Arduino board and the Wi-Fi module require 3.3 V while LCD and MQ-135 sensor needs 5V DC for their operation. The Arduino can be powered by connecting it to a USB connection. Since the voltage supply and ground pins of the other modules are connected with the common VCC and ground respectively, the rest of the components draw power from the 5V output of the Arduino board itself. 

How the circuit works - 

The device developed in this project can be installed near any Wi-Fi hotspot in a populated urban area. As the device is powered, the Arduino board loads the required libraries flashes some initial messages on the LCD screen and starts sensing data from the MQ-135 sensor. The sensitivity curve of the sensor for different combustible gases is already mentioned above. The sensor can be calibrated so that its analog output voltage is proportional to the concentration of polluting gases in PPM. The analog voltage sensed at the pin A0 of the Arduino is converted to a digital value by using the in-built ADC channel of the Arduino. The Arduino board has 10-bit ADC channels, so the digitized value ranges from 0 to 1023. The digitized value can be assumed proportional to the concentration of gases in PPM. The read value is first displayed on the LCD screen and passed to the ESP8266 module wrapped in a proper string through virtual serial function.  The Wi-Fi module is configured to connect with the ThingSpeak IoT platform. ThingSpeak is an IoT analytics platform service that allows us to aggregate, visualize and analyze live data streams in the cloud. ThingSpeak provides instant visualizations of data posted by the IoT devices to the ThingSpeak server. With the ability to execute MATLAB code in ThingSpeak one can perform online analysis and processing of the data as it comes in. 

The Wi-Fi module can be connected with the ThingSpeak server by sending AT commands from the module. The module first test the AT startup by sending the following command - 

AT

The command is passed by the controller to the Wi-Fi module using software serial function. In response to the command 'AT', the platform must respond with 'OK' if the cloud service is running. Then, the AT command to view the version information is passed as follow - 

AT + GMR

 In response to this command, the IoT platform must respond by sending back the version information, SDK version and the time bin is compiled. Next, the AT command to set the connection to Wi-Fi mode is sent as follow - 

AT + CWMODE = 3

By setting the parameter in CWMODE to 3, the Wi-Fi connection is configured to SoftAP as well as station mode. This AT command can in fact take three parameters as follow - 

1 - set Wi-Fi connection to station mode

2 - set Wi-Fi connection to SoftAP mode

3 - set Wi-Fi connection to SoftAP + station mode

In response to this command, the IoT platform must send back the string indication of the Wi-Fi connection mode set. Now the AT command to reset the module is sent as follow - 

AT + RST

In response to this command, the Wi-Fi module must restart and send back a response of 'OK'. After resetting the module, AT command to set up multiple connections is enabled by sending the following command -

AT + CIPMUX=1

 This AT command can take two parameters - 0 for setting a single connection and 1 for setting multiple connections. Next, the command to connect with the Access Point (AP) is passed which takes two parameters where the first parameter is the SSID of the registered cloud service on ThingSpeak and the other parameter is the password to login to the cloud service. 

AT+CWJAP=\"EngineersGarage\", \"egP@$$w0rd?\

Now, the AT command to get local IP address is passed as follow - 

AT + CIFSR

In response to this command, the local IP address of the Wi-Fi connection is sent back by the module. Now, the module is ready to establish a TCP IP connection with the ThingSpeak server. The controller reads the sensor data and stores it in a string variable. The TCP IP connection is established by sending the following AT command - 

AT + CIPSTART = 4, "TCP", "184.106.153.149", 80

The AT + CIPSTART command can be used to establish a TCP connection, register a UDP port or establish an SSL connection. In the above command, it is used to establish a TCP IP connection. For establishing a TCP-IP connection, the command takes four parameters where the first parameter is link ID which can be a number between 0 to 4, second parameter is connection type which can be TCP or UDP, third parameter is remote IP address or IP address of the cloud service to connect with and the last parameter is detection time interval for checking if the connection is live. If the last parameter is set to 0, the TCP keep-alive feature is disabled otherwise a time interval in seconds range from 1 to 7200 can be passed as parameter. In response to this command, the server must respond with 'OK' if the connection is successfully established otherwise it should respond with the message 'ERROR'. 

Now when the connection with the server is successfully established and the controller has read the sensor value, it can send the data to the cloud using the following command - 

AT + CIPSEND = 4

 This command takes four parameters, where the first parameter is the link ID which can be a number between 0 to 4, the second parameter is data length which can be maximum 2048 bytes long, the third parameter is remote IP in case of a UDP connection and remote port number in case of UDP connection. The third and fourth parameter is optional and used only in case of UDP connection with the server. Since the TCP IP connection is established, these parameters are not used. The command is followed by a string containing the URL having the field names and values passed through the HTTP GET method. In this project, a string containing the URL having API Key and the sensor value as the field and value is passed. The passed field and its value are logged on the cloud server.  It is important to pass the API key in this URL as one of the field-value in order to connect with the registered cloud service. The Air quality measured by the Thinsensor can now be monitored and recorded through the ThingSpeak IoT platform through the Wi-Fi module.  The recorded data is shown at the ThingSpeak platform as follow - 

User Interface of ThingSpeak Platform

The user needs to log in the ThingSpeak platform from the registered account to view and monitor the sensor data. The Arduino sketch manages to read sensor data and send the AT commands for connecting with the IoT platform. Get an understanding of the Arduino code from the programming guide. 

Programming Guide - 

The program code is intended to be loaded on an Arduino UNO. In the program code, first, the standard open-source libraries of Arduino for interfacing LCD and setting up virtual serial communication are imported. The software serial library is imported for serial communication with the Wi-Fi module. This followed by a declaration of variables representing the circuit connections of the Arduino with the character LCD, MQ-135 sensor and Wi-Fi module. The API key is stored in a variable and objects of LCD and virtual serial type are instantiated. 

The setup() function is called in which baud rate for the serial communication with Wi-Fi module and serial data transmission to the LCD module is set to 9600. The LCD is initialized using begin() method and some flash messages are flashed on it. The WiFi mode and network connectivity are established using the AT commands with some delays. The delay should be given according to the time it takes to connect with the network.

The loop() function is called in which the sensor value is read using the analogRead() function and the value is stored in a variable. The user-defined esp8266() function is called for transmitting the sensor data to the cloud.

In the esp8266() function, the AT command for establishing a TCP connection is passed, and then the API key of the ThingSpeak server is transmitted along with the sensor data in the form of a URL string. At an interval of every 16 seconds, the data gets updated to the ThingSpeak channel.

The loop function iterates infinitely sending the sensor data to the cloud in real-time. This completes the Arduino sketch for Arduino based IOT Air Quality Monitoring IoT Project. Check out the complete code from the code section.

Arduino Based Air Quality Monitoring IOT Project

Source Code

//Program to 
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(13, 12, 6, 5, 4, 3);
float t=0;
char data = 0;
// replace with your channel's thingspeak API key
String apiKey = "8NBNB4VQ9F2EEWQM";
// connect 10 to TX of Serial USB
// connect 11 to RX of serial USB
SoftwareSerial ser(10,11); // RX, TX
// this runs once
void setup() 
{                
  // enable debug serial 
  //Serial.begin(9600);
  // enable software serial
  ser.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0,0); 
  lcd.print("Engineers Garage");
  lcd.setCursor(0,1);
  lcd.print("               "); 
  delay(3000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("    IOT AIR");
  lcd.setCursor(0,1);
  lcd.print("QUALITY MONITOR");  
  delay(3000); 
 // pinMode(12, INPUT);
  
  // reset ESP8266 WiFi connection AT+CIPMUX=1 AT+CWJAP
  ser.println("AT");
  delay(1000);
  ser.println("AT+GMR");
  delay(1000);
  ser.println("AT+CWMODE=3");
  delay(1000);
  ser.println("AT+RST");
  delay(5000);
  ser.println("AT+CIPMUX=1");
  delay(1000);
  String cmd="AT+CWJAP=\"EngineersGarage\",\"egP@$$w0rd?\"";
  ser.println(cmd);
  delay(1000);
  ser.println("AT+CIFSR");
  delay(1000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("      WIFI");
  lcd.setCursor(0,1);
  lcd.print("   CONNECTED");
 }
// the loop 
void loop()
{
  delay(1000);
  t = analogRead(A0);
  Serial.print("Airquality = ");
  Serial.println(t);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("  SENDING DATA");
  lcd.setCursor(0,1);
  lcd.print("    TO CLOUD");
  esp_8266();
}
void esp_8266()
{
   // TCP connection AT+CIPSTART=4,"TCP","184.106.153.149",80 
    String cmd = "AT+CIPSTART=4,\"TCP\",\"";
    cmd += "184.106.153.149"; // api.thingspeak.com
    cmd += "\",80";
    ser.println(cmd);
    Serial.println(cmd); 
    if(ser.find("Error"))
    {
      Serial.println("AT+CIPSTART error");
      return;
    }
  
  // prepare GET string GET https://api.thingspeak.com/update?api_key=LHAG4NSIYJ5UWS6U&field1=0\r\n\r\n
  String getStr = "GET /update?api_key=";
  getStr += apiKey;
  //getStr +="&field1=";
  //getStr +=String(h);
  getStr +="&field1=";
  getStr +=String(t);
  getStr += "\r\n\r\n";
  // send data length
  cmd = "AT+CIPSEND=4,";
  cmd += String(getStr.length());
  ser.println(cmd);
  Serial.println(cmd);
  delay(1000);
  ser.print(getStr);
  Serial.println(getStr);
     
  // thingspeak needs 15 sec delay between updates
  delay(16000);  
}
[/restrict]

Schematics

Arduino Based Air Quality Monitoring IoT Project

Code Snippet #1

//Program to 

#include <SoftwareSerial.h>

#include <LiquidCrystal.h>


LiquidCrystal lcd(13, 12, 6, 5, 4, 3);


float t=0;


char data = 0;


// replace with your channel's thingspeak API key

String apiKey = "8NBNB4VQ9F2EEWQM";


// connect 10 to TX of Serial USB

// connect 11 to RX of serial USB

SoftwareSerial ser(10,11); // RX, TX


// this runs once

void setup() 

{                

  // enable debug serial 

  //Serial.begin(9600);

  // enable software serial

  ser.begin(9600);

  lcd.begin(16, 2);


  lcd.setCursor(0,0); 

  lcd.print("Engineers Garage");

  lcd.setCursor(0,1);

  lcd.print("               "); 

  delay(3000);


  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("    IOT AIR");

  lcd.setCursor(0,1);

  lcd.print("QUALITY MONITOR");  

  delay(3000); 


 // pinMode(12, INPUT);

  

  // reset ESP8266 WiFi connection AT+CIPMUX=1 AT+CWJAP

  ser.println("AT");

  delay(1000);

  ser.println("AT+GMR");

  delay(1000);

  ser.println("AT+CWMODE=3");

  delay(1000);

  ser.println("AT+RST");

  delay(5000);

  ser.println("AT+CIPMUX=1");

  delay(1000);

  String cmd="AT+CWJAP=\"EngineersGarage\",\"egP@$$w0rd?\"";

  ser.println(cmd);

  delay(1000);

  ser.println("AT+CIFSR");

  delay(1000);


  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("      WIFI");

  lcd.setCursor(0,1);

  lcd.print("   CONNECTED");

 }



// the loop 

void loop()

{

  delay(1000);

  t = analogRead(A0);

  Serial.print("Airquality = ");

  Serial.println(t);


  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("  SENDING DATA");

  lcd.setCursor(0,1);

  lcd.print("    TO CLOUD");

  esp_8266();


}


void esp_8266()

{

   // TCP connection AT+CIPSTART=4,"TCP","184.106.153.149",80 

    String cmd = "AT+CIPSTART=4,\"TCP\",\"";

    cmd += "184.106.153.149"; // api.thingspeak.com

    cmd += "\",80";

    ser.println(cmd);

    Serial.println(cmd); 

    if(ser.find("Error"))

    {

      Serial.println("AT+CIPSTART error");

      return;

    }

  

  // prepare GET string GET https://api.thingspeak.com/update?api_key=LHAG4NSIYJ5UWS6U&field1=0\r\n\r\n

  String getStr = "GET /update?api_key=";

  getStr += apiKey;

  //getStr +="&field1=";

  //getStr +=String(h);

  getStr +="&field1=";

  getStr +=String(t);

  getStr += "\r\n\r\n";

  // send data length

  cmd = "AT+CIPSEND=4,";

  cmd += String(getStr.length());

  ser.println(cmd);

  Serial.println(cmd);

  delay(1000);

  ser.print(getStr);

  Serial.println(getStr);

     

  // thingspeak needs 15 sec delay between updates

  delay(16000);  

}

[/restrict]

 

Code for AIR Quality Monitoring System - C Header File

//Program to 

#include <SoftwareSerial.h>

#include <LiquidCrystal.h>


LiquidCrystal lcd(13, 12, 6, 5, 4, 3);


float t=0;


char data = 0;


// replace with your channel's thingspeak API key

String apiKey = "8NBNB4VQ9F2EEWQM";


// connect 10 to TX of Serial USB

// connect 11 to RX of serial USB

SoftwareSerial ser(10,11); // RX, TX


// this runs once

void setup() 

{                

  // enable debug serial 

  //Serial.begin(9600);

  // enable software serial

  ser.begin(9600);

  lcd.begin(16, 2);


  lcd.setCursor(0,0); 

  lcd.print("Engineers Garage");

  lcd.setCursor(0,1);

  lcd.print("               "); 

  delay(3000);


  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("    IOT AIR");

  lcd.setCursor(0,1);

  lcd.print("QUALITY MONITOR");  

  delay(3000); 


 // pinMode(12, INPUT);

  

  // reset ESP8266 WiFi connection AT+CIPMUX=1 AT+CWJAP

  ser.println("AT");

  delay(1000);

  ser.println("AT+GMR");

  delay(1000);

  ser.println("AT+CWMODE=3");

  delay(1000);

  ser.println("AT+RST");

  delay(5000);

  ser.println("AT+CIPMUX=1");

  delay(1000);

  String cmd="AT+CWJAP=\"EngineersGarage\",\"egP@$$w0rd?\"";

  ser.println(cmd);

  delay(1000);

  ser.println("AT+CIFSR");

  delay(1000);


  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("      WIFI");

  lcd.setCursor(0,1);

  lcd.print("   CONNECTED");

 }



// the loop 

void loop()

{

  delay(1000);

  t = analogRead(A0);

  Serial.print("Airquality = ");

  Serial.println(t);


  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("  SENDING DATA");

  lcd.setCursor(0,1);

  lcd.print("    TO CLOUD");

  esp_8266();


}


void esp_8266()

{

   // TCP connection AT+CIPSTART=4,"TCP","184.106.153.149",80 

    String cmd = "AT+CIPSTART=4,\"TCP\",\"";

    cmd += "184.106.153.149"; // api.thingspeak.com

    cmd += "\",80";

    ser.println(cmd);

    Serial.println(cmd); 

    if(ser.find("Error"))

    {

      Serial.println("AT+CIPSTART error");

      return;

    }

  

  // prepare GET string GET https://api.thingspeak.com/update?api_key=LHAG4NSIYJ5UWS6U&field1=0\r\n\r\n

  String getStr = "GET /update?api_key=";

  getStr += apiKey;

  //getStr +="&field1=";

  //getStr +=String(h);

  getStr +="&field1=";

  getStr +=String(t);

  getStr += "\r\n\r\n";

  // send data length

  cmd = "AT+CIPSEND=4,";

  cmd += String(getStr.length());

  ser.println(cmd);

  Serial.println(cmd);

  delay(1000);

  ser.print(getStr);

  Serial.println(getStr);

     

  // thingspeak needs 15 sec delay between updates

  delay(16000);  

}

 

Credits

TechnicalEngineer

  TechnicalEngineer

 

 

Hackster.io

This content is provided by our content partner Hackster.io, an Avnet developer community for learning, programming, and building hardware. Visit them online for more great content like this.

This article was originally published at Hackster.io. It was added to IoTplaybook or last modified on 01/20/2020.