We will build a particulate matter detector using PM2.5 Air Quality Sensor, ESP32, UNO and LoRa Module.
Particle pollution, also known as Particulate Matter is a mixture of wide-ranging size of solids and liquids found in the air. Some of these particles (especially the small ones) can be harmful to our health because it is tiny enough to enter our lungs when we breathe.
To measure this we need a particle pollution detector that can measure the air quality of the air that we breathe.
Difficulty LevelHelpful ResourcesWe have a separate post on our development board guides on our website. Check them out below:
You can also check other Zio Qwiic Start guides related to this project below:
Installing LibrariesYou need to install the following libraries to your Arduino IDE. Download the following libraries and save it on your local Arduino IDE libraries folder:
To install the libraries open your Arduino IDE, go to Sketch tab, select Include Library -> Add.Zip Library. Select the above libraries to be included on your IDE. You can also check out this complete guide here.
Connection SetupWe need two Lora modules in order to send and receive data from our PM2.5 Sensor. We will call this as LoRa Receiver and LoRa Sender respectively. A Lora receiver will receive data collected by the PM2.5 Sensor and will output this on the OLED Display. A LoRa sender is where the PM2.5 will be connected.
Setting Up LoRa SenderBelow are the modules needed for the Lora sender. You need to attach the PM2.5 Sensor with adapter on the sender side inorder to detect Particle matter and measure the air quality.
Step 1: Attach the Pm2.5 Sensor and adapter together
Below is what it looks like after attaching the sensor and adapter together
Step 2: Attach the Antennae to the LoRa module
Step 3: Daisy chain all the components using Qwiic cables
Step 4: Download code and upload to PsyFi32
You can download the code from our GitHub page here.
/* *************************************************************
* Demo code for Zio Qwiic PM2.5 Air Quality Sensor with Adapter.
*
* Download the module here : https://www.smart-prototyping.com/Zio-Qwiic-PM-Air-Quality-Sensor-and-Adapter-Board
*
*
*************************************************************** */
#include <Wire.h>
#define address 0x12
#define HEADER_H 0x42
#define HEADER_L 0x4D
#define FRAME_LENGTH 0x1C
uint8_t COMMAND = 0x00;
uint8_t Sensor_Databufer[32];
unsigned char cur_rx_data;
unsigned char pre_rx/_data;
unsigned char main_status=0;
unsigned char recv_buff[256]={0};
unsigned char recv_buff_index=0;
unsigned char incomingByte;
int pm1_0_cf_1=0;
int pm2_5_cf_1=0;
int pm10_cf_1=0;
int pm1_0=0;
int pm2_5=0;
int pm10=0;
unsigned short check_sum;
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
pinMode(13,OUTPUT);
}
void loop() {
digitalWrite(13,HIGH);
Wire.requestFrom(address, 32);
while(Wire.available())
{
cur_rx_data = Wire.read();
switch(main_status)
{
case 0:
if( cur_rx_data == HEADER_L )
{
if( pre_rx_data == HEADER_H )
{
main_status++;
check_sum += pre_rx_data;
check_sum += cur_rx_data;
cur_rx_data = 0;
pre_rx_data = 0;
}
}else
{
pre_rx_data = cur_rx_data;
}
break;
case 1:
if( cur_rx_data == FRAME_LENGTH )
{
if( pre_rx_data == 0x00 )
{
main_status++;
check_sum += pre_rx_data;
check_sum += cur_rx_data;
cur_rx_data = 0;
pre_rx_data = 0;
}
}else
{
pre_rx_data = cur_rx_data;
}
break;
case 2:
recv_buff[recv_buff_index++] = cur_rx_data;
check_sum += cur_rx_data;
if( recv_buff_index == 26)
{
main_status++;
cur_rx_data = 0;
pre_rx_data = 0;
}
break;
case 3:
recv_buff[recv_buff_index++] = cur_rx_data;
if( recv_buff_index == 28)
{
if( check_sum == ( (recv_buff[26]<<8) + recv_buff[27]) )
{
recv_buff_index = 0;
pm1_0_cf_1 = (recv_buff[recv_buff_index] << 8) + recv_buff[recv_buff_index+1];
recv_buff_index += 2;
pm2_5_cf_1 = (recv_buff[recv_buff_index] << 8) + recv_buff[recv_buff_index+1];
recv_buff_index += 2;
pm10_cf_1 = (recv_buff[recv_buff_index] << 8) + recv_buff[recv_buff_index+1];
recv_buff_index += 2;
pm1_0 = (recv_buff[recv_buff_index] << 8) + recv_buff[recv_buff_index+1];
recv_buff_index += 2;
pm2_5 = (recv_buff[recv_buff_index] << 8) + recv_buff[recv_buff_index+1];
recv_buff_index += 2;
pm10 = (recv_buff[recv_buff_index] << 8) + recv_buff[recv_buff_index+1];
Serial.print("PMSA003I: ");
// Serial.print("pm1.0_cf_1:");Serial.print(pm1_0_cf_1,DEC);Serial.print("ug/m3");Serial.print(" ");
// Serial.print("pm2.5_cf_1:"); Serial.print(pm2_5_cf_1,DEC);Serial.print("ug/m3");Serial.print(" ");
// Serial.print("pm10_cf_1:");Serial.print(pm10_cf_1,DEC);Serial.print("ug/m3");Serial.print(" ");
Serial.print("pm1.0: ");Serial.print(pm1_0,DEC);Serial.print("ug/m3");Serial.print(" ");
Serial.print("pm2.5: ");Serial.print(pm2_5,DEC);Serial.print("ug/m3");Serial.print(" ");
Serial.print("pm10: ");Serial.print(pm10,DEC);Serial.println("ug/m3");
}
main_status = 0;
cur_rx_data = 0;
pre_rx_data = 0;
check_sum = 0;
for(int i=0;i< 256; i++)
{
recv_buff[i] = 0x00;
}
recv_buff_index = 0x00;
}
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
}
}
// Read_Sensordata();
delay(500);
digitalWrite(13,LOW);
delay(500);
}
void Read_Sensordata()
{
uint8_t i=0;
Wire.requestFrom(address, 32);
while (Wire.available()) { // slave may send less than requested
Sensor_Databufer[i++] = Wire.read(); // receive a byte as character
}
Serial.println("Sensor_Data: ");
for(i=0;i<32;i++)
{
Serial.print(i);
Serial.print(": ");
Serial.println(Sensor_Databufer[i],HEX);
}
}
Step 5 Connect to a power source
Setting Up LoRa ReceiverAfter setting up your Lora Sender, we need to set up the Lora Receiver. The data we have collected from the Lora Sender for the Particle Matter will be sent over to our receiver and displayed on the OLED.
Below are the modules needed for the Lora receiver.
Step 1: Attach Antennae to LoRa module
Step 2: Daisy chain all the components together using Qwiic cables
Step 3: Download the code below and upload to Uno
You can download the code from our GitHub page here.
#include <QwiicRF.h>
#include "U8glib.h"
String incoming = "";
String PM1_0,PM2_5,PM10;
String data_buffer[]={"pm1.0:","","pm2.5:","","pm10:",""};
uint8_t save_flag =0,k=0;
QwiicRF Radio;
U8GLIB_SSD1327_96X96_2X_GR u8g(U8G_I2C_OPT_NONE); // I2C OLED
void setup() {
Serial.begin(9600);
Radio.begin(0x35); //Default I2C Address for QwiicRF
u8g.firstPage();
do {
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0, 20);
u8g.print("PMSA003I:");
u8g.setPrintPos(0, 40);
u8g.print("pm1.0:");
u8g.setPrintPos(0, 60);
u8g.print("pm2.5:");
u8g.setPrintPos(0, 80);
u8g.print("pm10:");
} while( u8g.nextPage() );
}
void loop() {
while ( Radio.hasPayload() == false ) {
delay(1000);
}
incoming=Radio.read();
if(incoming=="#")
{
save_flag=0;
k=0;
for(uint8_t j=0;j<6;j++)
{Serial.println(data_buffer[j]);}
u8g.firstPage();
do {
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0, 20);
u8g.print("PMSA003I:");
u8g.setPrintPos(0, 40);
u8g.print(data_buffer[0]);u8g.setPrintPos(50, 40);u8g.print(data_buffer[1]);u8g.print("ug/m3");
u8g.setPrintPos(0, 60);
u8g.print(data_buffer[2]);u8g.setPrintPos(50, 60);u8g.print(data_buffer[3]);u8g.print("ug/m3");
u8g.setPrintPos(0, 80);
u8g.print(data_buffer[4]);u8g.setPrintPos(50, 80);u8g.print(data_buffer[5]);u8g.print("ug/m3");
} while( u8g.nextPage() );
}
if(save_flag==1)
{
data_buffer[k++]=incoming;
}
if(incoming=="@")
{
save_flag=1;
}
}
Step 4: Connect to a power source
After connecting to a power source (we use a powerbank for this example), your Lora Receiver will receive data sent from your Lora Sender.
There you have it! Your very own Particle Pollution detector all set up! You can record your data by connecting to an IOT platform dashboard and have it monitored in real time!
Do check out our other projects and tutorial blogs on our website to give you that qwiic inspiration!
Comments