Sunday, February 2, 2020

ESP8266-based air quality monitoring system using PMS7003 sensor

Introduction


Low-cost (US$19) Air Quality Monitoring System




Purpose


The aim of this project is to use PMS7003 sensor without 3rd party library. Additionally, it allows delay function in the loop and demonstrates how to communicate with sensor via software serial.

Features


- delay function : Some example codes on Internet do not work with delay in loop and generate endless checksum error. That is caused by serial buffer overflow between PMS7003 and Wemos. To avoid the issue, this project incorporates preamble searching mechanism to locate exact data stream in the serial buffer. Therefore, we are able to use various value in delay function without checksum error.

Prerequisites


- Arduino IDE
ESP8266 package for Arduino IDE

Requirements


Hardware
-Wemos D1 mini : US$1.77 on Aliexpress
-PMS7003 air quality sensor : US$16.80 on Aliexpress

Instructions


Step 1. Setup hardware

PMS7003 sensor comes with a small breakout board, which has TX, RX, VCC, GND pins. Connect TX of PMS7003 to D5 of Wemos, RX to D6, VCC to 5V, and GND to G. Finally, connect micro usb to Wemos for uploading firmware, and check serial monitor and serial plotter in Android IDE to make sure the sensor works correctly.




Step 2. Upload sketch to Wemos D1 mini

/**
* Air quality monitoring system using PMS7003 sensor
*
* Features: 1 Run without 3rd party library
* 2 Allow delay function
*
* Hardware : Wemos D1 mini, PMS7003
* Software : Arduino IDE
*
* January 2020. Brian Kim
*/
#include <SoftwareSerial.h>
/**
* PMS7003 sensor pin map and packet header
*/
#define PMS7003_TX D5 // GPIO12
#define PMS7003_RX D6 // GPIO14
#define PMS7003_PREAMBLE_1 0x42 // From PMS7003 datasheet
#define PMS7003_PREAMBLE_2 0x4D
#define PMS7003_DATA_LENGTH 31
/**
* Wemos serial RX - TX PMS7003
* TX - RX
*/
SoftwareSerial _serial(PMS7003_TX, PMS7003_RX); // RX, TX
int _pm1, _pm25, _pm10;
void readSensor() {
int checksum = 0;
unsigned char pms[32] = {0,};
/**
* Search preamble for Packet
* Solve trouble caused by delay function
*/
while( _serial.available() &&
_serial.read() != PMS7003_PREAMBLE_1 &&
_serial.peek() != PMS7003_PREAMBLE_2 ) {
}
if( _serial.available() >= PMS7003_DATA_LENGTH ){
pms[0] = PMS7003_PREAMBLE_1;
checksum += pms[0];
for(int j=1; j<32 ; j++){
pms[j] = _serial.read();
// Serial.print(pms[j],HEX);Serial.print(" ");
if(j < 30)
checksum += pms[j];
}
// Serial.println(" ");
_serial.flush();
if( pms[30] != (unsigned char)(checksum>>8)
|| pms[31]!= (unsigned char)(checksum) ){
Serial.println("Checksum error");
return;
}
if( pms[0]!=0x42 || pms[1]!=0x4d ) {
Serial.println("Packet error");
return;
}
_pm1 = makeWord(pms[10],pms[11]);
_pm25 = makeWord(pms[12],pms[13]);
_pm10 = makeWord(pms[14],pms[15]);
}
}
void setup()
{
Serial.begin(115200); // For debugging
_serial.begin(9600); // For communicating with PMS7003 sensor
Serial.printf("\nAir quality monitoring system using PMS7003 sensor\n");
}
void loop()
{
readSensor();
Serial.printf("PM1.0:%d PM2.5:%d PM10.0:%d\n", _pm1, _pm25, _pm10);
delay(2000);
}


Results


After uploading firmware, Wemos restarts itself automatically. Once Wemos D1 mini has restarted, serial monitor shows air quality data from PMS7003 every 2 seconds. On the output, each line consists of PM1.0, PM2.5, and PM10 measurement. For example, the last line of the output says PM1.0 is 15 μg/m³, PM2.5 is 20 μg/m³, and PM10.0 is 22 μg/m³.


Using serial plotter of Arduino IDE we can see a graph of these three values in a single plot. In the graph, Green line represents PM1.0, Red line represents PM2.5, and Green line represents PM10.0.



References


Source codes at github

No comments:

Post a Comment