註:這裡再簡單說明一下程式內容,程式裡頭有用到兩個串列埠,一個是Serial,另一個是Serial1,真正跟PMS3003連接的是Serial1,Serial是用來輸出感測數據用的,即是 ...
Searchthissite01-G3+Uno1.改裝PMS3003的接線2.與ArduinoUno連接3.到ArduinoIDE寫程式以下程式碼取自:https://github.com/neojou/arduino-ameba/tree/master/example/pms3003-test先不接上圖的LCD顯示器增加上面兩行,將Serial1設為(2,3),也就是G3的TX接到D2(RX)、RX接到D3(TX)#includeSoftwareSerialSerial1(2,3);//RX,TXlongpmcf10=0;longpmcf25=0;longpmcf100=0;longpmat10=0;longpmat25=0;longpmat100=0;charbuf[50];voidsetup(){//putyoursetupcodehere,torunonce:Serial.begin(9600);Serial1.begin(9600);}voidloop(){//putyourmaincodehere,torunrepeatedly:intcount=0;unsignedcharc;unsignedcharhigh;while(Serial1.available()){c=Serial1.read();if((count==0&&c!=0x42)||(count==1&&c!=0x4d)){Serial.println("checkfailed");break;}if(count>15){Serial.println("complete");break;}elseif(count==4||count==6||count==8||count==10||count==12||count==14)high=c;elseif(count==5){pmcf10=256*high+c;Serial.print("CF=1,PM1.0=");Serial.print(pmcf10);Serial.println("ug/m3");}elseif(count==7){pmcf25=256*high+c;Serial.print("CF=1,PM2.5=");Serial.print(pmcf25);Serial.println("ug/m3");}elseif(count==9){pmcf100=256*high+c;Serial.print("CF=1,PM10=");Serial.print(pmcf100);Serial.println("ug/m3");}elseif(count==11){pmat10=256*high+c;Serial.print("atmosphere,PM1.0=");Serial.print(pmat10);Serial.println("ug/m3");}elseif(count==13){pmat25=256*high+c;Serial.print("atmosphere,PM2.5=");Serial.print(pmat25);Serial.println("ug/m3");}elseif(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是用來輸出感測數據用的,即是用ArduinoIDE程式開發工具中的串列埠監視器來觀看自Arduino回傳的數值。
而更具體來說,PMS3003不只是偵測PM2.5,比PM2.5顆粒大的PM10,以及比PM2.5顆粒小的PM1,也都有偵測數據。
另外,為何串列埠的鮑率(BaudRate)設的很慢,只有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空氣懸浮粒子感測器傳送的資料,如何要確定資料內容的正確性,第二十三個位元組到二十四個位元組則是使用CheckSum的方法來檢核。
(表2)PMS3003資料傳輸格式表:(公式1)PMS3003資料檢核公式參照附錄中PMS3003規格與上表內容,我們得到上面PMS3003資料檢核公式,得知必須將第三個位元組到二十二個位元組累加內容之後,與第二十三位元組到二十四位元雙位園進行比較,如果相等,則為正確的資料內容傳輸,不是的話,就是錯誤的資料,我們則捨棄不用。
加上LCD顯示器註:有關LCD顯示器的程式,採用Motoblockly的積木來產生(紅色字為增加的地方)#include#include#includeLiquidCrystal_I2Cmylcd(0x3F,16,2);SoftwareSerialSerial1(2,3);//RX,TXlongpmcf10=0;longpmcf25=0;longpmcf100=0;longpmat10=0;longpmat25=0;longpmat100=0;charbuf[50];voidsetup(){//putyoursetupcodehere,torunonce:mylcd.init();mylcd.backlight();Serial.begin(9600);Serial1.begin(9600);}voidloop(){//putyourmaincodehere,torunrepeatedly:intcount=0;unsignedcharc;unsignedcharhigh;while(Serial1.available()){c=Serial1.read();if((count==0&&c!=0x42)||(count==1&&c!=0x4d)){Serial.println("checkfailed");break;}if(count>15){Serial.println("complete");break;}elseif(count==4||count==6||count==8||count==10||count==12||count==14)high=c;elseif(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(","));}elseif(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(","));}elseif(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);}elseif(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(","));}elseif(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(","));}elseif(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:ReadvalueofPM1,PM2.5andPM10ofairquality////*Version:V3.1//*Author:Zuyang@HUST//*ModifiedbyCainforArduinoHardwareSerialportcompatibility//*Date:March.25.2016//******************************#include#defineLENG31//0x42+31bytesequalto32bytesunsignedcharbuf[LENG];intPM01Value=0;//definePM1.0valueoftheairdetectormoduleintPM2_5Value=0;//definePM2.5valueoftheairdetectormoduleintPM10Value=0;//definePM10valueoftheairdetectormodulevoidsetup(){Serial.begin(9600);//useserial0Serial.setTimeout(1500);//settheTimeoutto1500ms,longerthanthedatatransmissionperiodictimeofthesensor}voidloop(){if(Serial.find(0x42)){//starttoreadwhendetect0x42Serial.readBytes(buf,LENG);if(buf[0]==0x4d){if(checkValue(buf,LENG)){PM01Value=transmitPM01(buf);//countPM1.0valueoftheairdetectormodulePM2_5Value=transmitPM2_5(buf);//countPM2.5valueoftheairdetectormodulePM10Value=transmitPM10(buf);//countPM10valueoftheairdetectormodule}}}staticunsignedlongOledTimer=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("PM10:");Serial.print(PM10Value);Serial.println("ug/m3");Serial.println();}}charcheckValue(unsignedchar*thebuf,charleng){charreceiveflag=0;intreceiveSum=0;for(inti=0;i