1.改裝PMS3003的接線
2.與Arduino Uno連接
3.到Arduino IDE 寫程式
以下程式碼取自:https://github.com/neojou/arduino-ameba/tree/master/example/pms3003-test
先不接上圖的LCD顯示器
增加上面兩行,將Serial1設為(2,3),也就是G3的TX接到D2(RX)、RX接到D3(TX)
#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3); // RX, TX
long pmcf10=0;
long pmcf25=0;
long pmcf100=0;
long pmat10=0;
long pmat25=0;
long pmat100=0;
char buf[50];
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial1.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int count = 0;
unsigned char c;
unsigned char high;
while (Serial1.available()) {
c = Serial1.read();
if((count==0 && c!=0x42) || (count==1 && c!=0x4d)){
Serial.println("check failed");
break;
}
if(count > 15){
Serial.println("complete");
break;
}
else if(count == 4 || count == 6 || count == 8 || count == 10 || count == 12 || count == 14) high = c;
else if(count == 5){
pmcf10 = 256*high + c;
Serial.print("CF=1, PM1.0=");
Serial.print(pmcf10);
Serial.println(" ug/m3");
}
else if(count == 7){
pmcf25 = 256*high + c;
Serial.print("CF=1, PM2.5=");
Serial.print(pmcf25);
Serial.println(" ug/m3");
}
else if(count == 9){
pmcf100 = 256*high + c;
Serial.print("CF=1, PM10=");
Serial.print(pmcf100);
Serial.println(" ug/m3");
}
else if(count == 11){
pmat10 = 256*high + c;
Serial.print("atmosphere, PM1.0=");
Serial.print(pmat10);
Serial.println(" ug/m3");
}
else if(count == 13){
pmat25 = 256*high + c;
Serial.print("atmosphere, PM2.5=");
Serial.print(pmat25);
Serial.println(" ug/m3");
}
else if(count == 15){
pmat100 = 256*high + c;
Serial.print("atmosphere, PM10=");
Serial.print(pmat100);
Serial.println(" ug/m3");
}
count++;
}
while(Serial1.available()) Serial1.read();
Serial.println();
delay(5000);
}
註:這裡再簡單說明一下程式內容,程式裡頭有用到兩個串列埠,一個是Serial,另一個是Serial1,真正跟PMS3003連接的是Serial1,Serial是用來輸出感測數據用的,即是用Arduino IDE程式開發工具中的串列埠監視器來觀看自Arduino回傳的數值。
而更具體來說,PMS3003不只是偵測PM 2.5,比PM 2.5顆粒大的PM 10,以及比PM 2.5顆粒小的PM 1,也都有偵測數據。
另外,為何串列埠的鮑率(Baud Rate)設的很慢,只有9600,因為PMS3003感測器本身的感測反應也是慢的,只保證10秒鐘內回傳一次數值,所以鮑率設快也沒用,瓶頸在感測器上。
以上程式的執行結果,可利用序列埠監控視窗來觀看,如下
利用以上程式可以得到PM1.0、PM2.5、PM10分別在CF=1為標準顆粒物、atmosphere為大氣環境下
我也不知這兩種值所代表的不同,查了資料知道,如下。那台灣要用那一組呢??
CF=1 根据美国TSI公司的仪器校准
大气环境下 根据中国气象局的数据校准
從下面這資料,好像用大氣環境下的為主
首先,它可以採樣測定的空氣懸浮微粒有三種規格 0.3-1.0um/1.0-2.5um/2.5-10um,也就是說我們可以拿到 PM1.0/PM2.5/PM10 的測定資料(ug/m3)。而且PMS3003 的 datasheet 寫到他有兩套檢定空氣品質濃度的方法,分別是可以獲得「大氣環境下」和「標準顆粒物」兩組資料值,所以程式裡面每一次從 sensor 那邊得到的資料就會有2組,6個測定值。(這裡我會在意的是「大氣環境下」測得的這組)
這裡我要補充說明的是,範例裡面使用程式去讀取 PMS3003 資料那段邏輯在網路上有多種不同的實作(讀到的資料值都相同啦),我是參考一個程式寫的很簡潔的網友的(雖然他的方法也偷懶少做了checksum),如果看不懂建議您直接看一下 PMS3003 的 datasheet。或是參考下面這另一個出處的邏輯:https://www.dfrobot.com/wiki/index.php?title=PM2.5_laser_dust_sensor_SKU:SEN0177
以上程式是根據下表來寫的
由 PMS3003 資料傳輸規格所知,正確資料的開頭,一定是由下列資料『0x42、0x4D』所開頭的資料(第一個位元組到二個位元組),才有可能是正確的資料,資料內容則是由第三個位元組到二十二個位元組則是 PMS3003 空氣懸浮粒子感測器傳送的資料,如何要確定資料內容的正確性,第二十三個位元組到二十四個位元組則是使用 Check Sum 的方法來檢核。
(表 2)PMS3003 資料傳輸格式表:
(公式 1)PMS3003資料檢核公式
參照附錄中 PMS3003 規格與上表內容,我們得到上面 PMS3003 資料檢核公式,得知必須將第三個位元組到二十二個位元組累加內容之後,與第二十三位元組到二十四位元雙位園進行比較,如果相等,則為正確的資料內容傳輸,不是的話,就是錯誤的資料,我們則捨棄不用。
加上 LCD 顯示器
註:有關LCD顯示器的程式,採用Motoblockly的積木來產生(紅色字為增加的地方)
#include <SoftwareSerial.h>
#include <Wire.h>
#include <motoLiquidCrystal_I2C.h>
LiquidCrystal_I2C mylcd(0x3F,16,2);
SoftwareSerial Serial1(2, 3); // RX, TX
long pmcf10=0;
long pmcf25=0;
long pmcf100=0;
long pmat10=0;
long pmat25=0;
long pmat100=0;
char buf[50];
void setup() {
// put your setup code here, to run once:
mylcd.init();
mylcd.backlight();
Serial.begin(9600);
Serial1.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int count = 0;
unsigned char c;
unsigned char high;
while (Serial1.available()) {
c = Serial1.read();
if((count==0 && c!=0x42) || (count==1 && c!=0x4d)){
Serial.println("check failed");
break;
}
if(count > 15){
Serial.println("complete");
break;
}
else if(count == 4 || count == 6 || count == 8 || count == 10 || count == 12 || count == 14) high = c;
else if(count == 5){
pmcf10 = 256*high + c;
Serial.print("CF=1, PM1.0=");
Serial.print(pmcf10);
Serial.println(" ug/m3");
mylcd.setCursor(0,0);
mylcd.print(String("CF ")+pmcf10 + String(","));
}
else if(count == 7){
pmcf25 = 256*high + c;
Serial.print("CF=1, PM2.5=");
Serial.print(pmcf25);
Serial.println(" ug/m3");
mylcd.setCursor(8,0);
mylcd.print(pmcf25 + String(","));
}
else if(count == 9){
pmcf100 = 256*high + c;
Serial.print("CF=1, PM10=");
Serial.print(pmcf100);
Serial.println(" ug/m3");
mylcd.setCursor(12,0);
mylcd.print(pmcf100);
}
else if(count == 11){
pmat10 = 256*high + c;
Serial.print("atmosphere, PM1.0=");
Serial.print(pmat10);
Serial.println(" ug/m3");
mylcd.setCursor(0,1);
mylcd.print(String("At ")+pmat10 + String(","));
}
else if(count == 13){
pmat25 = 256*high + c;
Serial.print("atmosphere, PM2.5=");
Serial.print(pmat25);
Serial.println(" ug/m3");
mylcd.setCursor(8,1);
mylcd.print(pmat25 + String(","));
}
else if(count == 15){
pmat100 = 256*high + c;
Serial.print("atmosphere, PM10=");
Serial.print(pmat100);
Serial.println(" ug/m3");
mylcd.setCursor(12,1);
mylcd.print(pmat100);
}
count++;
}
while(Serial1.available()) Serial1.read();
Serial.println();
delay(5000);
}
那六組資料會顯示在序列埠及LCD顯示器上
==================================================
除了上面程式外,網路上還有找到其他程式,但我好像都沒有成功!!所以以上面的程式為主
以下:G3的TX接Arduino的D0(RX)、
G3的RX接Arduino的D1(TX)(這條線也可不接)
程式碼2: https://www.dfrobot.com/wiki/index.php/PM2.5_laser_dust_sensor_SKU:SEN0177
//****************************** //*Abstract: Read value of PM1,PM2.5 and PM10 of air quality // //*Version:V3.1 //*Author:Zuyang @ HUST //*Modified by Cain for Arduino Hardware Serial port compatibility //*Date:March.25.2016 //******************************#include <Arduino.h>#define LENG 31 //0x42 + 31 bytes equal to 32 bytesunsigned char buf[LENG];int PM01Value=0; //define PM1.0 value of the air detector moduleint PM2_5Value=0; //define PM2.5 value of the air detector moduleint PM10Value=0; //define PM10 value of the air detector modulevoid setup(){ Serial.begin(9600); //use serial0 Serial.setTimeout(1500); //set the Timeout to 1500ms, longer than the data transmission periodic time of the sensor}void loop(){ if(Serial.find(0x42)){ //start to read when detect 0x42 Serial.readBytes(buf,LENG); if(buf[0] == 0x4d){ if(checkValue(buf,LENG)){ PM01Value=transmitPM01(buf); //count PM1.0 value of the air detector module PM2_5Value=transmitPM2_5(buf);//count PM2.5 value of the air detector module PM10Value=transmitPM10(buf); //count PM10 value of the air detector module } } } static unsigned long OledTimer=millis(); if (millis() - OledTimer >=1000) { OledTimer=millis(); Serial.print("PM1.0: "); Serial.print(PM01Value); Serial.println(" ug/m3"); Serial.print("PM2.5: "); Serial.print(PM2_5Value); Serial.println(" ug/m3"); Serial.print("PM1 0: "); Serial.print(PM10Value); Serial.println(" ug/m3"); Serial.println(); } }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 PCint 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 PCint transmitPM10(unsigned char *thebuf){ int PM10Val; PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module return PM10Val;}
呈現結果都是0 ,因此沒有成功!
PM1.0: 0 ug/m3
PM2.5: 0 ug/m3
PM1 0: 0 ug/m3
程式碼3:https://github.com/brucetsao/makerdiwo/tree/master/201602
資料來源:https://www.dfrobot.com/wiki/index.php?title=PM2.5_laser_dust_sensor_SKU:SEN017
呈現結果都是一樣, 不會變,應該還是不成功!
PM1.0: 65 ug/m3
PM2.5: 94 ug/m3
PM10: 106 ug/m3
PM1.0: 65 ug/m3
PM2.5: 94 ug/m3
PM10: 106 ug/m3
==================================
Arduino+ESP8266
參考 https://github.com/miaoski/pm25/blob/master/pm25/pm25.ino
要將serialReadPMValue資料夾複製到arduino/libraries下
如下表所示,為 PMS3003 G3 PM2.5 粉塵感測器透過串列埠,定時會回傳給單晶片或其他處理器的資料之通訊格式。
(表 4)PMS3003 G3 PM2.5 粉塵感測器通訊資料格式
Serial port baudrate: 9600; Parity: None; Stop Bits: 1; packet length is fixed at 32 bytes.