├── assets ├── images │ ├── Design.png │ └── circuit.jpg └── docs │ ├── Final_Paper.pdf │ └── Air_Pollution.pdf ├── README.md ├── Nodemcu-cloud.ino └── arduino_code.ino /assets/images/Design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bairwa25/air_quality/HEAD/assets/images/Design.png -------------------------------------------------------------------------------- /assets/images/circuit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bairwa25/air_quality/HEAD/assets/images/circuit.jpg -------------------------------------------------------------------------------- /assets/docs/Final_Paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bairwa25/air_quality/HEAD/assets/docs/Final_Paper.pdf -------------------------------------------------------------------------------- /assets/docs/Air_Pollution.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bairwa25/air_quality/HEAD/assets/docs/Air_Pollution.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Air Pollution Monitoring System 2 | 3 | This is **IOT based Air Pollution Monitoring System** which measures indoor harmful gases present in air like Carbon Dioxide(CO2) using an MQ135 gas sensor and Carbon Monoxide(CO) using an MQ7 sensor. It will show the air quality in PPM(Parts Per Million) on the LCD and as well as on [Thingspeak](https://thingspeak.com/channels/1347787) so that we can monitor it very easily in PPM. 4 | 5 | ## Components Requirement: 6 | - Arduino Uno 7 | - Wi-Fi module Node-MCU ESP8266 8 | - 16x2 LCD 9 | - MQ135 Gas sensor 10 | - MQ 7 LPG gas sensor 11 | - Buzzer 12 | - LEDs 13 | 14 | ## System Architecture: 15 | ![architecture](assets/images/Design.png) 16 | 17 | ## Software Requirement: 18 | - [Arduino IDE](https://www.arduino.cc/) 19 | > Arduino IDE used to upload programming in Arduino board and Node-MCU board with required library. 20 | - [Thingspeak](https://thingspeak.com/) 21 | > ThingSpeak is an IoT analytics platform service that allows you to aggregate, visualize, and analyze live data streams in the cloud. You can send data to ThingSpeak from your devices, create instant visualization of live data, and send alerts. 22 | 23 | ## Measurement: 24 | The most important step is to calibrate the sensor in fresh air and then draw an equation that converts the sensor output voltage value into our convenient units PPM (parts per 25 | million). Here are the mathematical calculations derived: 26 | 27 | 28 | 29 | For a log-log scale, the formula looks like this: 30 | 31 | 32 | 33 | Let’s find the slope. The formula to calculate slope m(here) is the following: 34 | 35 | 36 | 37 | If we apply the logarithmic quotient rule we get the following: 38 | 39 | 40 | 41 | Now we substitute the values for x, x0, y, and y0. 42 | Now that we have m and b, we can find the gas concentration for any ratio with the following formula: 43 | 44 | 45 | 46 | Using this we will be able to convert the sensor output values into PPM (Parts per Million) 47 | 48 | However, in order to get the real value of the gas concentration according to the log-log plot we need to find the inverse log of x: 49 | 50 | 51 | 52 | > More details for calculation [here](assets/docs/Final_Paper.pdf) 53 | 54 | > Datasheets for: 55 | - [MQ135](https://www.olimex.com/Products/Components/Sensors/Gas/SNS-MQ135/resources/SNS-MQ135.pdf) 56 | - [MQ7](https://www.sparkfun.com/datasheets/Sensors/Biometric/MQ-7.pdf) 57 | 58 | ## Results: 59 |

60 | 61 | 62 |

63 | 64 |

65 | 66 |

67 | 68 | > **More details found in Document [here](assets/docs/Air_Pollution.pdf)** 69 | 70 | ## Credit: 71 | - [AJAY KUMAR BAIRWA](https://www.linkedin.com/in/ajay-bairwa) 72 | - [SURENDRA KUMAR](https://www.instagram.com/suruu.meena/) 73 | - [ROHIT KUMAR](https://www.instagram.com/rohit_meena__23/) 74 | -------------------------------------------------------------------------------- /Nodemcu-cloud.ino: -------------------------------------------------------------------------------- 1 | //------- Import Library ----------// 2 | #include "ThingSpeak.h" 3 | #include 4 | 5 | //------- WI-FI details ----------// 6 | char ssid[] = "Xav!er"; //SSID here 7 | char pass[] = "12345678"; // Passowrd here 8 | //--------------------------------// 9 | 10 | //----------- Channel details ----------------// 11 | unsigned long Channel_ID = 1347787; // Channel ID 12 | const int Field_1 = 1; // Don't change 13 | const int Field_2 = 2; // Don't change 14 | const char * myWriteAPIKey = "8UxxxxxxxxxxxxxOX"; //Your Thingspeak write API key 15 | //-------------------------------------------// 16 | 17 | int x; 18 | int y; 19 | WiFiClient client; 20 | 21 | void setup() 22 | { 23 | Serial.begin(115200); 24 | 25 | while (!Serial) { 26 | ; // wait for serial port to connect. Needed for Leonardo native USB port only 27 | } 28 | 29 | WiFi.mode(WIFI_STA); 30 | ThingSpeak.begin(client); 31 | internet(); 32 | } 33 | 34 | void loop() 35 | { 36 | internet(); 37 | get_value(); 38 | upload(); 39 | } 40 | 41 | 42 | void internet() 43 | { 44 | if (WiFi.status() != WL_CONNECTED) 45 | { 46 | delay(100); 47 | Serial.print("Attempting to connect to SSID: "); 48 | Serial.println(ssid); 49 | while (WiFi.status() != WL_CONNECTED) 50 | { 51 | WiFi.begin(ssid, pass); 52 | Serial.print("."); 53 | delay(5000); 54 | } 55 | Serial.println("\nWIFI CONNECTED."); 56 | } 57 | } 58 | 59 | 60 | const byte numChars = 32; 61 | char receivedChars[numChars]; 62 | char tempChars[numChars]; // temporary array for use when parsing 63 | 64 | //============ variables to hold the parsed data ============// 65 | float value1 = 0.0; 66 | float value2 = 0.0; 67 | 68 | boolean newData = false; 69 | 70 | //========================================================== // 71 | 72 | //============ 73 | 74 | void get_value() { 75 | if (Serial.available() > 0) 76 | { 77 | recvWithStartEndMarkers(); 78 | if (newData == true) { 79 | strcpy(tempChars, receivedChars); 80 | // this temporary copy is necessary to protect the original data 81 | // because strtok() used in parseData() replaces the commas with \0 82 | parseData(); 83 | showParsedData(); 84 | newData = false; 85 | } 86 | } 87 | else 88 | { 89 | get_value(); 90 | } 91 | } 92 | 93 | //============ 94 | 95 | void recvWithStartEndMarkers() { 96 | static boolean recvInProgress = false; 97 | static byte ndx = 0; 98 | char startMarker = '<'; 99 | char endMarker = '>'; 100 | char rc; 101 | 102 | while (Serial.available() > 0 && newData == false) { 103 | rc = Serial.read(); 104 | if (recvInProgress == true) { 105 | if (rc != endMarker) { 106 | receivedChars[ndx] = rc; 107 | ndx++; 108 | if (ndx >= numChars) { 109 | ndx = numChars - 1; 110 | } 111 | } 112 | else { 113 | receivedChars[ndx] = '\0'; // terminate the string 114 | recvInProgress = false; 115 | ndx = 0; 116 | newData = true; 117 | } 118 | } 119 | else if (rc == startMarker) { 120 | recvInProgress = true; 121 | } 122 | } 123 | } 124 | 125 | //============ 126 | 127 | void parseData() { // split the data into its parts 128 | 129 | char * strtokIndx; // this is used by strtok() as an index 130 | 131 | strtokIndx = strtok(tempChars, ","); // get the first part - the string 132 | value1 = atof(strtokIndx); // convert this part to an integer 133 | 134 | strtokIndx = strtok(NULL, ","); // this continues where the previous call left off 135 | value2 = atof(strtokIndx); // convert this part to a float 136 | 137 | } 138 | 139 | //============ 140 | 141 | void showParsedData() { 142 | Serial.print("value1: "); 143 | Serial.println(value1); 144 | Serial.print("value2: "); 145 | Serial.println(value2); 146 | } 147 | 148 | 149 | void upload() 150 | { 151 | //========== set the fields with the values 152 | ThingSpeak.setField(Field_1, value1); 153 | ThingSpeak.setField(Field_2, value2); 154 | if (Serial.available() > 0) 155 | { 156 | x = ThingSpeak.writeFields(Channel_ID,myWriteAPIKey); 157 | // int statusCode = ThingSpeak.getLastReadStatus(); 158 | 159 | if (x == 200){ 160 | Serial.print("Data Updated."); 161 | } 162 | else{ 163 | Serial.print("Data upload failed, retrying...."); 164 | upload(); 165 | } 166 | } 167 | else{ 168 | Serial.print("Serial Pin Connection Error!!, retrying...."); 169 | } 170 | // value = ""; 171 | delay(15000); 172 | } 173 | -------------------------------------------------------------------------------- /arduino_code.ino: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * Board: Arduino Uno (ATMega2560) 3 | * Developed by: Ajay Bairwa Email: yourfriend9014@gmail.com 4 | * 5 | * Nodemcu-ESP8266 WiFi Module is used to connect to Internet 6 | * and send data to https://thingspeak.com server 7 | * 8 | * Output is shown using GRAPH on thinkspeak server. 9 | * 10 | * NOTE: 11 | * Internal 10 bit ADC (A0) is used to read the Analog output of the Temperature Sensor. 12 | ********************************************************************/ 13 | /****************************************************************** 14 | * 15 | * PIN Diagram of ESP01: (This module works on 3.3v) (NOT 5v) 16 | * +---------------------------+ 17 | * | |=| |=| |=|============== | 18 | * | | | | | | | ANTENA | 19 | * | | |=| |=| | Facing ur side| 20 | * | ========================= | 21 | * | | 22 | * | GND GPIO0 GPIO2 RxD | 23 | * | o o o o | 24 | * | | 25 | * | o o o o | 26 | * | TxD CH_PD RST Vcc | 27 | * +---------------------------+ 28 | * 29 | * Connections for Communication: 30 | * ESP01 -> Arduino 31 | * Vcc -> 3.3V 32 | * GND -> GND 33 | * TxD -> Rx1 (Pin 10) 34 | * RxD -> Tx1 (Pin 11) 35 | * CH_PD -> 3.3V 36 | * 37 | * Serial Communication with PC through USB cable 38 | *****************************************************************/ 39 | 40 | /**************************************************************** 41 | * STEPS: 42 | * 1. Sign up at https://thingspeak.com 43 | * 2. Channels > New Channel > Update "Name" and "Field 1", "Field2" so on...-> Save Channel 44 | * 3. Click On API keys > Copy "Write API key" 45 | * 4. Make all the Connections to Arduino Mega board mentioned Above. 46 | * 5. Change Following in below written program. 47 | * a. apiKey by above copied "Write API key" (in step 3) 48 | * b. NOTE: ESP-01 is connected to wifi hotspot in a different approach using AT commands 49 | * AT, AT+CWMODE=1, AT+CWJAP="BKS","sai123456", AT+CWJAP? 50 | * 6. Upload Program to Arduino Mega Board 51 | * 7. Open Arduino Serial Monitor on PC (Set Baud Rate to 9600 and set "Both NL & CR" 52 | * 8. Go to https://thingspeak.com and login 53 | * Channels > My Channels > Click on Channel Name (created in step 2) > Private View 54 | * Here you can observe the Grapth of Temperature Vs Day. 55 | ****************************************************************/ 56 | 57 | //--------------------------------------------------------------------------------------------------------------- 58 | // LIBRARIES 59 | //--------------------------------------------------------------------------------------------------------------- 60 | #include 61 | #include 62 | #include 63 | 64 | LiquidCrystal_I2C lcd(0x27, 16,2); 65 | 66 | //--------------------------------------------------------------------------------------------------------------- 67 | // DEFINES VARIABLES 68 | //--------------------------------------------------------------------------------------------------------------- 69 | int buz = 5; //buzzer connected to pin 7 70 | int fan = 6; // fan connected to pin 6 71 | int greenled = 8; //green led connected to pin 8 72 | int redled = 9; //red led connected to pin 9 73 | 74 | SoftwareSerial Ser(2, 3); // RX, TX for Nodemcu-ESP8266 75 | 76 | //========== MQ135 Sensor variable 77 | int gas_sensor = A0; //Sensor pin 78 | float m = -0.353; //Slope 79 | float c = 0.711; //Y-Intercept 80 | float R0 = 23.30; //Sensor Resistance in fresh air from previous code 21.30 81 | 82 | //========== MQ7 Sensor variable 83 | int CO_sensor = A1; //Sensor pin 84 | float m1 = -0.67; //Slope 85 | float c1 = 1.34; //Y-Intercept 86 | float R01 = 5.80; //Sensor Resistance 4.80 87 | 88 | //--------------------------------------------------------------------------------------------------------------- 89 | // SETUP 90 | //--------------------------------------------------------------------------------------------------------------- 91 | void setup() { 92 | Serial.begin(9600); // PC to Arduino Serial Monitor 93 | Ser.begin(115200); // Arduino to ESP01 Communication or 115200 94 | 95 | lcd.init(); // initialize the lcd 96 | lcd.backlight(); 97 | lcd.print(" Air Pollution "); 98 | lcd.setCursor(0,1); 99 | lcd.print(" Monitor System "); 100 | delay(4000); 101 | lcd.clear(); 102 | 103 | 104 | pinMode(buz,OUTPUT); // buzzer is connected as Output from Arduino 105 | pinMode(greenled,OUTPUT); // green led is connected as output from Arduino 106 | pinMode(redled, OUTPUT); // red led is connected as output from Arduino 107 | pinMode(fan, OUTPUT); 108 | pinMode(gas_sensor, INPUT); 109 | pinMode(CO_sensor,INPUT); 110 | 111 | //------------------// Connection of Nodemcu-ESP8266 //------------------// 112 | unsigned char check_connection=0; 113 | unsigned char times_check=0; 114 | Serial.println("Connecting to Wifi"); 115 | lcd.print("Connect to Wifi."); 116 | delay(1000); 117 | lcd.clear(); 118 | 119 | while(check_connection==0) 120 | { 121 | if(Ser.find("\nWIFI CONNECTED.")==1 ) 122 | { 123 | Serial.println("WIFI CONNECTED."); 124 | lcd.print("WIFI CONNECTED."); 125 | delay(2000); 126 | lcd.clear(); 127 | break; 128 | } 129 | times_check++; 130 | if(times_check>3) 131 | { 132 | times_check=0; 133 | Serial.println("Trying to Reconnect.."); 134 | lcd.setCursor(0,0); 135 | lcd.print(" Trying to "); 136 | lcd.setCursor(0,1); 137 | lcd.print(" Reconnect... "); 138 | delay(2000); 139 | lcd.clear(); 140 | } 141 | } 142 | } 143 | //------------------// Connection of Nodemcu-ESP8266 //------------------// 144 | //--------------------------------------------------------------------------------------------------------------- 145 | // SETUP 146 | //--------------------------------------------------------------------------------------------------------------- 147 | 148 | 149 | //--------------------------------------------------------------------------------------------------------------- 150 | // MAIN LOOP 151 | //--------------------------------------------------------------------------------------------------------------- 152 | void loop() { 153 | //========== MQ135 Sensor variable 154 | float sensor_volt; //Define variable for sensor voltage 155 | float RS_gas; //Define variable for sensor resistance 156 | float ratio; //Define variable for ratio 157 | float sensorValue = analogRead(gas_sensor); //Read analog values of sensor 158 | sensor_volt = sensorValue*(5.0/1024.0); //Convert analog values to voltage 159 | RS_gas = ((5.0*10.0)/sensor_volt)-10.0; //Get value of RS in a gas 160 | ratio = RS_gas/R0; // Get ratio RS_gas/RS_air 161 | double ppm_log = (log10(ratio)-c)/m; //Get ppm value in linear scale according to the the ratio value 162 | double ppm = pow(10, ppm_log); //Convert ppm value to log scale 163 | 164 | Serial.print("Our Air Qualit PPM = "); 165 | Serial.println(ppm); 166 | Serial.println(ratio); 167 | 168 | 169 | lcd.setCursor(0,0); // set cursor of lcd to 1st row and 1st column 170 | lcd.print("CO2: "); // print message on lcd 171 | lcd.print(ppm); // print value of MQ135 172 | 173 | //========== MQ7 Sensor variable 174 | float sensor_volt1; //Define variable for sensor voltage 175 | float RS_gas1; //Define variable for sensor resistance 176 | float ratio1; //Define variable for ratio 177 | float sensorValue1 = analogRead(CO_sensor); //Read analog values of sensor 178 | sensor_volt1 = sensorValue1*(5.0/1024.0); //Convert analog values to voltage 179 | RS_gas1 = ((5.0*10.0)/sensor_volt1)-10.0; //Get value of RS in a gas 180 | ratio1 = RS_gas1/R01; // Get ratio RS_gas/RS_air 181 | double ppm_log1 = (log10(ratio1)-c1)/m1; //Get ppm value in linear scale according to the the ratio value 182 | double ppm1 = pow(10, ppm_log1); //Convert ppm value to log scale 183 | 184 | Serial.print("CO PPM = "); 185 | Serial.println(ppm1); 186 | 187 | Serial.println(analogRead(gas_sensor)); 188 | Serial.println(analogRead(CO_sensor)); 189 | 190 | lcd.setCursor(0,1); // set cursor of lcd to 1st row and 1st column 191 | lcd.print("CO PPM = "); // print message on lcd 192 | lcd.print(ppm1); // print value of MQ7 193 | delay(5000); 194 | 195 | 196 | //------Sending Data to Nodemcu ESP8266--------// 197 | Ser.print('<'); // Starting char 198 | Ser.print(ppm); // float data 199 | Ser.print(','); 200 | Ser.print(ppm1); // float data 201 | Ser.println('>'); // Ending char 202 | lcd.clear(); 203 | lcd.print("Upload to Cloud."); 204 | 205 | //------Check condition for buzzer and LED--------// 206 | if (ppm >= 10 || ppm1 >= 10) { 207 | digitalWrite(greenled, LOW); 208 | digitalWrite(buz, HIGH); 209 | digitalWrite(redled, HIGH); 210 | digitalWrite(fan, HIGH); 211 | lcd.setCursor(0,1); 212 | lcd.print("Polluted Air ಠ_ಠ"); 213 | Serial.println("Alert!!!"); 214 | delay(2000); // wait 2000ms 215 | lcd.clear(); 216 | } 217 | 218 | else { 219 | digitalWrite(greenled, HIGH); 220 | digitalWrite(redled, LOW); 221 | digitalWrite(buz, LOW); 222 | digitalWrite(fan, LOW); 223 | lcd.setCursor(0,1); 224 | lcd.print(" Normal Air ◉‿◉ "); 225 | Serial.println("Normal"); 226 | delay(2000); // wait 500ms 227 | lcd.clear(); 228 | } 229 | //------Check condition for buzzer and LED--------// 230 | 231 | //--------------------------------------------// 232 | 233 | 234 | 235 | 236 | 237 | // thingspeak free version needs 15-20 sec delay between every push 238 | // delay(15000); // wait for 16sec 239 | } 240 | --------------------------------------------------------------------------------