Nowadays, most of us out there face the problem of impure air quality due to the increase in pollutants and impurities mixed with the air. Pollutants like CO2, CO, CH4 emitted from vehicles and SO2, SO4 and other gases emitted from industries add to the amount of impurity in the air. Also, fireworks and crackers during festive seasons, occasions and events further increase the pollution level in the atmosphere. As a result of this, various health-related and respiratory issues are also increasing among the common masses. So to keep a track of the air quality around you, this is a mini IoT based air quality monitoring system that will monitor the air quality over a web server using the internet and alarm or trigger if the air quality goes poorer than a certain level, i.e. if there are sufficient amount of harmful gases present in the air. It shows the air quality in PPM on the LCD as well as on the webpage so that you can monitor it easily. Objective To measure and monitor the air pollution levels To detect highly polluted conditions To alert user as and when the levels cross a specified limit Components you'll require ESP32 system on a chip microcontroller MQ135 gas sensor LEDs Resistors Buzzer Some wires and a breadboard Block Diagram Circuitry Software Used Arduino IDE Working Make the connections as per the circuit diagram above. Connect the ESP32 with your computer/laptop. Select a suitable port and Esp32 board and hit 'Upload' to upload the code into the ESP32. (I’ve used the MQ135 gas sensor here which is basically a Air Quality sensor capable of sensing gases like NH3, NOx, alcohol, Benzene, smoke, CO2 and other harmful gases. MQ135 will sense the gases and we will get the Pollution/Air quality level in PPM (parts per million). The MQ135 sensor will give us output in form of voltage levels and we convert it into PPM (our code and the module libraries will take care of that). For this project, I’ve set good air quality levels upto 800 PPM, poor levels in between 800 to 2000 and alert us if it exceeds 2000 PPM. ) Provide the sensor with different types of smoke inputs and observe the output PPM levels in the web browser. All the web browser implementation is taken care by the code. Real time PPM values can also be viewed/observed in the Arduino IDE Serial Monitor. Just paste the IP address in the web browser and observe the PPM levels. Green LED will be ON until the PPM level is 800, Red LED will be ON post 800 mark and Red LED with Buzzer will be ON post 2000 mark. Code } } { } { } { } previousTime = currentTime; header += c; { } { } { } } } } } } } # include "MQ135.h" # include <WiFi.h> # include <Wire.h> int air_quality; const char * ssid = "Enter your wifi" ; //Replace with your network name const char * password = "Enter your wifi password" ; //Replave with your network password // Set web server port number to 80 WiFiServer server ( 80 ) ; // Variable to store the HTTP request String header; // Current time unsigned long currentTime = millis (); // Previous time unsigned long previousTime = 0 ; // Define timeout time in milliseconds (example: 2000ms = 2s) const long timeoutTime = 2000 ; void setup () { delay ( 1000 ); Serial . begin ( 115200 ); pinMode ( 12 , OUTPUT ); //Buzzer will be output to ESP32 pinMode ( 18 , OUTPUT ); //Green Led will be Output to ESP32 pinMode ( 19 , OUTPUT ); //Red Led will be output to ESP32 pinMode ( 34 , INPUT ); //Gas sensor will be an input to the ESP32 digitalWrite ( 18 , HIGH ); digitalWrite ( 19 , HIGH ); Serial . print ( "Connecting to " ); Serial . println (ssid); WiFi . begin (ssid, password); while ( WiFi . status () != WL_CONNECTED) { delay ( 500 ); Serial . print ( "." ); // Print local IP address and start web server Serial . println ( "" ); Serial . println ( "WiFi connected." ); Serial . println ( "IP address: " ); Serial . println ( WiFi . localIP ()); server. begin (); void loop () { MQ135 gasSensor = MQ135 ( 34 ); float air_quality = gasSensor. getPPM (); if (air_quality >= 2000 ) digitalWrite ( 12 , HIGH ); //Buzzer is ON digitalWrite ( 19 , LOW ); //RED LED is ON digitalWrite ( 18 , HIGH ); //GREEN LED is OFF delay ( 1000 ); digitalWrite ( 12 , LOW ); if (air_quality > 800 && air_quality < 2000 ) digitalWrite ( 12 , LOW ); //Buzzer is OFF digitalWrite ( 19 , LOW ); //RED LED is ON digitalWrite ( 18 , HIGH ); //GREEN LED is OFF delay ( 1000 ); digitalWrite ( 12 , LOW ); if (air_quality < 800 ) digitalWrite ( 12 , LOW ); //Buzzer is OFF digitalWrite ( 18 , LOW ); //GREEN LED is ON digitalWrite ( 19 , HIGH ); //RED LED id OFF delay ( 100 ); Serial . print (air_quality); Serial . println ( " PPM" ); delay ( 200 ); WiFiClient client = server. available (); // Listen for incoming clients if (client) { // If a new client connects, currentTime = millis (); Serial . println ( "New Client." ); // print a message out in the serial port String currentLine = "" ; // make a String to hold incoming data from the client while (client. connected () && currentTime - previousTime <= timeoutTime) { // loop while the client's connected currentTime = millis (); if (client. available ()) { // if there's bytes to read from the client, char c = client. read (); // read a byte, then Serial . write (c); // print it out the serial monitor if (c == '\n' ) { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine. length () == 0 ) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client. println ( "HTTP/1.1 200 OK" ); client. println ( "Content-type:text/html" ); client. println ( "Connection: close" ); client. println (); // Display the HTML web page client. println ( "<!DOCTYPE html><html>" ); client. println ( "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" ); client. println ( "<link rel=\"icon\" href=\"data:,\">" ); // CSS to style the table client. println ( "<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}" ); client. println ( "table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }" ); client. println ( "th { padding: 12px; background-color: #0043af; color: white; }" ); client. println ( "tr { border: 1px solid #ddd; padding: 12px; }" ); client. println ( "tr:hover { background-color: #bcbcbc; }" ); client. println ( "td { border: none; padding: 12px; }" ); client. println ( ".sensor { color:black; font-weight: bold; padding: 1px; }" ); // Web Page Heading client. println ( "</style></head><body><h2>AIR POLLUTION MONITOR</h2>" ); if (air_quality < 800 ) client. println ( "</style></head><body><h2>FRESH AIR!</h2>" ); else if (air_quality > 800 && air_quality < 2000 ) client. println ( "</style></head><body><h2>POOR AIR :(</h2>" ); else if (air_quality >= 2000 ) client. println ( "</style></head><body><h2>ALERT!TOXIC AIR!ALERT</h2>" ); client. println ( "<table><tr><th>MEASUREMENT</th><th>VALUE</th></tr>" ); client. println ( "<tr><td>Pollution PPM</td><td><span class=\"sensor\">" ); client. println (air_quality); client. println ( "</span></td></tr></table>" ); // The HTTP response ends with another blank line client. println (); // Break out of the while loop break ; } else { // if you got a newline, then clear currentLine currentLine = "" ; } else if (c != '\r' ) { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine // Clear the header variable header = "" ; // Close the connection client. stop (); Serial . println ( "Client disconnected." ); Serial . println ( "" ); Conclusion This is how you can build a small scale air quality monitoring system of your own and in the process, learn about Arduino, ESP32, environmental impacts of pollutants etc. on the go.