The air quality is a pretty big problem in my city. We have a monitoring station but it’s quite far from where I live so I decided to build myself a local, simple and nice-looking air quality monitor. You can learn more about the whole project and how I made it in this video:
Below you can find all the files and code for the project. And here are the parts that I used:
Part | Link |
Arduino Nano | https://bit.ly/32xGF06 |
Air Quality Sensor | https://bit.ly/36jWXLj |
NeoPixel Ring | https://bit.ly/3lhRM4O |
Code
#include <Adafruit_NeoPixel.h> #include <SoftwareSerial.h> #define LED_PIN 6 #define SLEEP_PIN 5 #define MAX_PM1_LEVEL 50 #define MAX_PM25_LEVEL 30 #define MAX_PM10_LEVEL 40 #define NUMPIXELS 24 Adafruit_NeoPixel pixels(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800); // 0 - green, 1 - blue, 2- orange, 3 - red int last_color = 5; #define LENG 31 //0x42 + 31 bytes equal to 32 bytes unsigned char buf[LENG]; SoftwareSerial SoftSerial(10, 11); // RX, TX void setup() { SoftSerial.begin(9600); Serial.begin(9600); pixels.begin(); pinMode(5, OUTPUT); } void loop() { digitalWrite(SLEEP_PIN, HIGH); delay(1000L * 60L); int pm01_level = 0; int pm25_level = 0; int pm10_level = 0; int air_quality[3]; CheckAirQuality(air_quality); pm01_level = air_quality[0]; pm25_level = air_quality[1]; pm10_level = air_quality[2]; if(pm01_level < MAX_PM1_LEVEL && pm25_level < MAX_PM25_LEVEL && pm10_level < MAX_PM10_LEVEL){ if(last_color != 0){ SetColor(0,30,0); } last_color = 0; }else if((pm01_level > MAX_PM1_LEVEL && pm25_level < MAX_PM25_LEVEL && pm10_level < MAX_PM10_LEVEL) || (pm01_level < MAX_PM1_LEVEL && pm25_level > MAX_PM25_LEVEL && pm10_level < MAX_PM10_LEVEL) || (pm01_level < MAX_PM1_LEVEL && pm25_level < MAX_PM25_LEVEL && pm10_level > MAX_PM10_LEVEL)){ if(last_color != 1){ SetColor(0,0,30); } last_color = 1; }else if((pm01_level > MAX_PM1_LEVEL && pm25_level > MAX_PM25_LEVEL && pm10_level < MAX_PM10_LEVEL) || (pm01_level > MAX_PM1_LEVEL && pm25_level < MAX_PM25_LEVEL && pm10_level > MAX_PM10_LEVEL) || (pm01_level < MAX_PM1_LEVEL && pm25_level > MAX_PM25_LEVEL && pm10_level > MAX_PM10_LEVEL)){ if(last_color != 2){ SetColor(30,10,0); } last_color = 2; }else if(pm01_level > MAX_PM1_LEVEL && pm25_level > MAX_PM25_LEVEL && pm10_level > MAX_PM10_LEVEL){ if(last_color != 3){ SetColor(30,0,0); } last_color = 3; } Serial.print("PM01: "); Serial.println(pm01_level); Serial.print("PM2.5: "); Serial.println(pm25_level); Serial.print("PM10: "); Serial.println(pm10_level); digitalWrite(SLEEP_PIN, LOW); delay(1000L * 60L * 3L); } void SetColor(int r, int g, int b){ for(int a = 255; a > 0; a--){ pixels.setBrightness(a); pixels.show(); delay(20); } pixels.clear(); pixels.setBrightness(255); pixels.show(); for(int i = 0; i < NUMPIXELS; i++) { pixels.setPixelColor(i, pixels.Color(r, g, b)); pixels.show(); delay(50); } } void CheckAirQuality(int* air_quality){ if(SoftSerial.find(0x42)){ //start to read when detect 0x42 SoftSerial.readBytes(buf,LENG); if(buf[0] == 0x4d){ if(checkValue(buf,LENG)){ air_quality[0] = transmitPM01(buf); //count PM1.0 value of the air detector module air_quality[1] = transmitPM2_5(buf);//count PM2.5 value of the air detector module air_quality[2] = transmitPM10(buf); //count PM10 value of the air detector module } } } } char checkValue(unsigned char *thebuf, char leng) { char receiveflag=0; int receiveSum=0; for(int i=0; i<(leng-2); i++){ receiveSum=receiveSum+thebuf[i]; } receiveSum=receiveSum + 0x42; if(receiveSum == ((thebuf[leng-2]<<8)+thebuf[leng-1])) //check the serial data { receiveSum = 0; receiveflag = 1; } return receiveflag; } int transmitPM01(unsigned char *thebuf) { int PM01Val; PM01Val=((thebuf[3]<<8) + thebuf[4]); //count PM1.0 value of the air detector module return PM01Val; } //transmit PM Value to PC int transmitPM2_5(unsigned char *thebuf) { int PM2_5Val; PM2_5Val=((thebuf[5]<<8) + thebuf[6]);//count PM2.5 value of the air detector module return PM2_5Val; } //transmit PM Value to PC int transmitPM10(unsigned char *thebuf) { int PM10Val; PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module return PM10Val; }
It’s hard to create a nice schematic for this project as there is no Fritzing library for PM2.5 sensor, and I have no idea how to create one 🙂 That’s why below you can find a text only explanation on connection, definitely not a perfect option but at the same time better than nothing:
Devices | Arduino |
Air Sensor RX | PIN 10 |
Air Sensor TX | PIN 11 |
Air Sensor 5V | 5V |
Air Sensor GND | GND |
Air Sensor SLEEP | PIN 5 |
LED Ring DI | PIN 6 |
LED Ring 5V | 3.3V |
LED Ring GND | GND |
As you can see in the table above I connected LED ring 5V to the 3.3V on the Arduino, that’s because there is only one 5V pin on Arduino Nano and it has to be used for Air quality sensor because it doesn’t work with 3.3V.
Thanks a lot for reading and happy making! I hope my air quality sensor will serve you well! And don’t forget to check out my other projects: