├── 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 | 
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 |
--------------------------------------------------------------------------------