Arduino: PMS5003 Air Quality Sensor library. Contribute to jbanaszczyk/pms5003 development by creating an account on GitHub.
Skiptocontent
{{message}}
jbanaszczyk
/
pms5003
Public
Notifications
Fork
27
Star
77
Arduino:PMS5003AirQualitySensorlibrary.
BSL-1.0License
77
stars
27
forks
Star
Notifications
Code
Issues
16
Pullrequests
1
Actions
Projects
0
Security
Insights
More
Code
Issues
Pullrequests
Actions
Projects
Security
Insights
master
Branches
Tags
Couldnotloadbranches
Nothingtoshow
{{refName}}
default
Couldnotloadtags
Nothingtoshow
{{refName}}
default
1
branch
2
tags
Code
Latestcommit
Gitstats
124
commits
Files
Permalink
Failedtoloadlatestcommitinformation.
Type
Name
Latestcommitmessage
Committime
Examples
VisualStudio
doc
src
.gitattributes
.gitignore
API.md
Compatibility.md
LICENSE
README.md
library.properties
Viewcode
pms5003
License
Status
Currentrevision:2.1
Whatisnew?
Good,stablerevision:1.0
Othersensors
Features
API
TODO
Preparation
IDE&OS
Dependencies
Library
Connections
Applications
Hello.TheBasicscenario.
Moreabouttheexample
Before
setup()
loop()
views
views:Cstyle
Initialization:C++style
initialization:begin()
C/Arduinoway
C++way
Whichoneisbetter?
ISOcleanlinesslevels
Finalnotes
API
Operationsonserialport
namespacepmsx{}
README.md
pms5003
I'mproudtopresentmyArduinolibrarysupportingPMS5003AirQualitySensor.
License
pms5003libraryisdistributedunderBoostSoftwareLicense1.0(BSL-1.0).
Status
Currentrevision:2.1
release:2.1
TherearesomeTODOsfornextrevisions
Whatisnew?
Release2.1bringsalotofchangesandimprovements:
APIcontract(classnamesandmethods)iscompletelyrewritten.Itisnotcompatiblewithv1.0.Sorry:(
Minorbugsarefixed(nothingimportant,release1.0shouldbeassumedasstable).
Addedsupportforsensorhardwarepins(pin3-SET,pin6-RESET).
Addedsupportformoreserialportlibraries(inversionofcontrol).
Addedsupportforunittests(soon).
AddedsupportforISO14644-1:Classificationofaircleanliness.
Addedmorediagnosticchecks
Addedsupportfor"views"(willbedescribedlater)-themostexcitingnewfeature.
Good,stablerevision:1.0
Previousrelease:1.0isstillavailable.
ThereisoneinterestingforksupportingESP8266:https://github.com/riverscn/pmsx003
Othersensors
MylibrarysupportsPMS5003(checked)
FormostPlantoversensorsprobablyitisaneasytasktoaddsupport.
listofcompatiblesensorsisavailableasaseparatedocument.
Features
LibrarysupportsallPlantoverPMS5003features(sleep&wakeup,passive/activemodes,hardwarepins),
Highlycustomizable:
Itusesalmostanyserialcommunicationlibrary,
Youhaveachoicetouseornottouse:(Cstyle)globalvariablesor(C++style)classinstances.
Writtenfromscratch,
WritteninmodernC++11(pleasedonotafraid-worksfinewithArduinoIDE).
Itis"headersonly"library.
Themaingoal:Readingdatafromthesensordoesnotblock.YourprocessreceivesthestatusOKorNO_DATAorsomekindsoferrorsbutyourprocessneverwaitsforthedata.
Serialportisnotmanagedbythelibrary,itispossibletoshutserialdriverdown,entersleepmodeandsoonindependentlyonthePMS5003sensor.
ProvidessupportforISO14644-1classificationofaircleanlinesslevels.
API
pms5003APIdescriptionisavailableasaseparatedocument.
TODO
Newmethods:somemorechecks
#14checkResetPin()-checkifdeclaredresetpinworksfine(checkifitresetsthesensor)
#15checkSleepPin()-checkifdeclaredsleep/wakeuppinisproperlyconnected
#16write()willreturnPmsStatusinsteadofbool
#17additeratorsbegin()andend()forviews
#18isWorking()shouldreturntribool
#19write(CMD_WAKEUP)shouldnotdelayifalreadyawoken
#20write()multiplecommandssequentially
Supportforplatforms
#22PlatformIO
#23CLion
Supportforboards:
#24ESP8266
#25Addunittests
Preparation
IDE&OS
pms5003libraryisdevelopedusing:
VisualStudioCommunity2017(Windows)
ArduinoIDEforVisualStudio
pms5003librarywassuccessfullycheckedusing:
Arduino1.8.5(Windows)
Dependencies
CurrentversionusesDrDiettrich'forkofAltSoftSerialLibrary.Installit.
pms5003willnotcompileusingoriginalAltSoftSeriallib.
pms5003willnotcompileusingveryoldArduinoIDE.Pleaseupgrade.
Library
Installpms5003library.
Connections
PMS5003Pin1(violet):VCC+5V
PMS5003Pin2(brown):GND
Important:PMS5003sensoruses3.3Vlogic.UseconvertersifrequiredormakesureyourArduinoboarduses3.3Vlogictoo.
PMS5003Pin4(blue):Arduinopin9(thereisnochoice,itisforcedbyAltSerial)
PMS5003Pin5(green):Arduinopin8(thereisnochoice,itisforcedbyAltSerial)
Optional
PMS5003Pin3(white):Arduinopin7(canbechangedornotconnectedatall)
PMS5003Pin6(yellow):Arduinopin6(canbechangedornotconnectedatall)
PMS5003pin7(black)andpin7(red)leavenotconnected
Applications
Hello.TheBasicscenario.
Usethecode:examples\p01basic\p01basic.ino
#include
PmsAltSerialpmsSerial;
pmsx::Pmspms(&pmsSerial);
////////////////////////////////////////
voidsetup(void){
Serial.begin(115200);
while(!Serial){}
Serial.println(pmsx::pmsxApiVersion);
if(!pms.begin()){
Serial.println("PMSsensor:communicationfailed");
return;
}
pms.setPinReset(6);
pms.setPinSleepMode(7);
if(!pms.write(pmsx::PmsCmd::CMD_RESET)){
pms.write(pmsx::PmsCmd::CMD_SLEEP);
pms.write(pmsx::PmsCmd::CMD_WAKEUP);
}
pms.write(pmsx::PmsCmd::CMD_MODE_PASSIVE);
pms.write(pmsx::PmsCmd::CMD_READ_DATA);
pms.waitForData(pmsx::Pms::TIMEOUT_PASSIVE,pmsx::PmsData::FRAME_SIZE);
pmsx::PmsDatadata;
autostatus=pms.read(data);
if(status!=pmsx::PmsStatus::OK){
Serial.print("PMSsensor:");
Serial.println(status.getErrorMsg());
}
pms.write(pmsx::PmsCmd::CMD_MODE_ACTIVE);
if(!pms.isWorking()){
Serial.println("PMSsensorfailed");
}
Serial.print("Timeofsetup():");
Serial.println(millis());
}
////////////////////////////////////////
voidloop(void){
staticautolastRead=millis();
pmsx::PmsDatadata;
autostatus=pms.read(data);
switch(status){
casepmsx::PmsStatus::OK:{
Serial.println("_________________");
constautonewRead=millis();
Serial.print("Waittime");
Serial.println(newRead-lastRead);
lastRead=newRead;
autoview=data.particles;
for(autoi=0;i0.3micron[/0.1L]|diameter:0.30
1780 Particles>0.5micron[/0.1L]|diameter:0.50
70 Particles>1.0micron[/0.1L]|diameter:1.00
18 Particles>2.5micron[/0.1L]|diameter:2.50
1 Particles>5.0micron[/0.1L]|diameter:5.00
1 Particles>10.micron[/0.1L]|diameter:10.00
37120 Reserved_0[???]|diameter:0.00
Moreabouttheexample
Before
Tousethelibrary:
install(downloadand"Add.ZIPlibrary")DrDiettrich'forkofAltSoftSerialLibrary
install(downloadand"Add.ZIPlibrary")pms5003library
includepms.hinyourcode:
#include
Createinstanceofserialdriver
PmsAltSerialpmsSerial;
Createinstanceofpmsx::Pmsobject:
librarynamespacenameispmsx
classnameoftheobjectisPms
objectisnamedpms
objectusespreviouslycreateddriverpmsSerial
pmsx::Pmspms(&pmsSerial);
setup()
Initializeseriallibrary.IfArduinocan'tcommunicatewithPMS5003-thereisnosensetoperformthenextsteps.
pms5003takescareonprotocoldetails(speed,datalength,parityandsoon).
if(!pms.begin()){
Serial.println("PMSsensor:communicationfailed");
return;
}
ThenextstepistodefineArduinopinsconnectedtopms5003:
SET(pms5003pin3,white)(sleep/wakeup)
RESET(pms5003pin6,violet)(sensorreset)
Thisstepisoptional.
IfSETpinisnotconnected-sleep/wakeupcommandsareexecutedusingserialconnection
IfRESETpinisnotconnected-sleepandthenwakeupworkslikereset
Ifpinsarenotconnected-justremoveappropriatesetPinReset/setPinSleepModelines.
pms.setPinReset(6);
pms.setPinSleepMode(7);
Thenexttaskistoputsensorinawellknownstate.
TherearetwoaspectsofPMS5003state:
sleeping/awoken
passive/active
BothcanbeexaminedusingisModeActive()/isModeSleep().Pleasenote,thatresultvalueisatristatelogictribool:Yes/No/Idon'tknow.
PleaserefertomyArduinoLibrary.ItisArduinoportofboost.triboollibrarydescription
Pleasenote,thatitispossible,thatArduinowasrestartedforanyreason,butPMS5003wassetinastrangestateanditwasnotrestarted.Itisthereason,thatinitialstatesofPMS5003is"Idon'tknow"
Wellknownstate(awokenandactive)canbeachievedaftersensorhardwareresetorsleep+wakeupsequence
if(!pms.write(pmsx::PmsCmd::CMD_RESET)){
pms.write(pmsx::PmsCmd::CMD_SLEEP);
pms.write(pmsx::PmsCmd::CMD_WAKEUP);
}
Thenexttaskistomakesure,thatArduinocancommunicatewithPMS5003.Toaccomplishthetaskweare:
forcingpassivemode(PMS5003sendsdataonlyifasked),
askfordata,
waitfortheresponse
andchecktheresponse
pms.write(pmsx::PmsCmd::CMD_MODE_PASSIVE);
pms.write(pmsx::PmsCmd::CMD_READ_DATA);
pms.waitForData(pmsx::Pms::TIMEOUT_PASSIVE,pmsx::PmsData::FRAME_SIZE);
pmsx::PmsDatadata;
autostatus=pms.read(data);
if(status!=pmsx::PmsStatus::OK){
Serial.print("PMSsensor:");
Serial.println(status.getErrorMsg());
}
if(!pms.isWorking()){
Serial.println("PMSsensorfailed");
}
FinallyweputbackPMS5003inactivemode-itsendsdataperiodicallyandautomatically.
pms.write(pmsx::PmsCmd::CMD_MODE_ACTIVE);
loop()
Firstofall:pms5003doesnotblockondataread
Trytoreadthedata:
pmsx::PmsDatadata;
autostatus=pms.read(data);
switch(status){
Ifthereissomethinginteresting:displayit:
casepmsx::PmsStatus::OK:{
....
Iftherearenodata:dosomethingelse:
casepmsx::PmsStatus::NO_DATA:
break;
Incaseoferror:showtheerrormessage:
default:
Serial.print("!!!Pmserror:");
Serial.println(status.getErrorMsg());
}
Letsgobacktothesituationwherethereissomethinginteresting:
casepmsx::PmsStatus::OK:{
views
DatareceivedfromPMS5003(seeAppendixI)maybeworthattention:
asawhole(13pmsx::pmsData_tnumbers,thatis13unsignedintnumbers)
ingroups:
(3numbers)PM1.0/2.5/10.0concentrationunitµg/m3,standardparticle,(CompensationFactory)CF=1,(TSI:TechnicalSpecificationsforInteroperability))
(3numbers)PM1.0/2.5/10.0concentrationunitµg/m3(underatmosphericenvironment)(looksgoodforeverydayuse)
(6numbers)thenumberofparticleswithdiameterbeyond0.3/0.5/1.0/2.5/5.0/10.0umin0.1Lofair(verytastydata,itfitsintoISO14644-1classificationofaircleanlinesslevels)
(1number)reserveddata,withoutanyrealmeaning
Togetaccesstothem:
autoview=data.raw;
or
autoview=data.concentrationCf;
or
autoview=data.concentration;
or
autoview=data.particles;
Each"view"providessimilarinterface:
usegetSize()togetcounterofdatainaview:
for(autoi=0;i1.0micron"
Serial.print(view.getName(i));
use.getMetric()togetunitofmeasureforparticulardata;forexample"/0.1L"
Serial.print(view.getMetric(i));
use.getDiameter()togetparticlediametercorrespondingtoparticulardata;forexample1.0F
Serial.print(view.getDiameter(i));
additionally:particles"view"provides.getLevel()-ISOclassificationofaircleanliness
Serial.print(view.getLevel(i));
Sucha"views"(datapartitions)areimplementedwithnoexecutiontimenormemoryoverhead.
autoview=data.particles;
for(autoi=0;i1.0micron"
Serial.print(view.names[i]);
use.metrics[]arraytogetunitofmeasureforparticulardata;forexample"/0.1L"
Serial.print(view.metrics[i]);
use.diameters[]togetparticlediametercorrespondingtoparticulardata;forexample1.0F
Serial.print(view.diameters[i]);
additionally:particles"view"provides.getLevel()-ISOclassificationofaircleanliness.Itisnotimplementedasarray-itisafunction(amethod)
Serial.print(view.getLevel(i));
Whichoneisbetter?Itdoesn'tmatter-codesize,memoryusageandresultingcodeisexactlythesameusingbothapproaches.
Initialization:C++style
CommonpatterninC++is"initializationinconstructor".UnfortunatelyArduinobreaksthatrule.
Thereisacodefrom:hardware\arduino\avr\cores\arduino\main.cppmodifiedforsimplicity
//globalvariablesconstructorsareexecutedbeforemain()
intmain(void){
init();
initVariant();
setup();//oursetup()procedure
for(;;){
loop();//ourloop()procedure
}
return0;
}
Letsimagine:
IftherewouldbeisaglobalvariablepmsoftypePms.
Itwouldbeagoodplacetoinitializeserialcommunicationpms.begin()withinpmsconstructor
Globalvariablesconstructorsareexecutedbeforemain()
AfterthatArduinoinitializesallthehardware
Andthanoursetup()isexecuted.
Ourserialconnectionstartedinstep3)isdestroyedduringArduinoinitializationinstep4.
Thereareatleasttwopossiblesolutions:
initialization:begin()
Bytheway:ifyouarenotsureifeverythingwasproperlyinitialized-executebegin()manuallyandchecktheresult.
C/Arduinoway
examples\p01basic\p01basic.ino
CreatestaticvariableoftypePms,donothinginconstructor
Initializeitduringsetup():callpms.begin()
Useit:callpms.methods
PmsAltSerialpmsSerial;
pmsx::Pmspms(&pmsSerial);
voidsetup(void){
if(!pms.begin()){
C++way
EditpmsConfig.hfile,uncommentline#definePMS_DYNAMIC
examples\p03cppStyle\p03cppStyle.ino
Createstaticvariableoftype*Pms(referencetoPms)
Donothingpriortomain()
Duringsetup()createnewobjectoftypePms,assigncreatedobjecttothereferencefrompreviousstep
Pms()constructorisexecutedautomatically
Pms()constructorexecutesbegin()
Itexecutesbegin()oftheserialportdriver
Useit:callpms->methods
Thisapproachaddssomecodesize-compileraddsdynamicmemorymanagement.
PmsAltSerialpmsSerial;
pmsx::Pms*pms=nullptr;
voidsetup(void){
pms=newpmsx::Pms(&pmsSerial);
if(!pms->initialized()){
Whichoneisbetter?
C/Arduinowayusingbegin()isclosertoArduinoprogrammingstyle.
Inmyopinion:C++wayisclosertomodernprogrammingstyle.
ISOcleanlinesslevels
particlesviewprovidessupportforISO14644-1classificationofaircleanlinesslevels.
Pleaserefertop03cppStyle.ino
Thecode(loop()functiononly):
voidloop(void){
staticautolastRead=millis();
pmsx::PmsDatadata;
autostatus=pms->read(data);
switch(status){
casepmsx::PmsStatus::OK:{
Serial.println("_________________");
constautonewRead=millis();
Serial.print("Waittime");
Serial.println(newRead-lastRead);
lastRead=newRead;
autoview=data.particles;
for(autoi=decltype(view.SIZE){0};i0.3micron[/0.1L]Level:8.27|diameter:0.30
505 Particles>0.5micron[/0.1L]Level:8.16|diameter:0.50
62 Particles>1.0micron[/0.1L]Level:7.87|diameter:1.00
7 Particles>2.5micron[/0.1L]Level:7.75|diameter:2.50
1 Particles>5.0micron[/0.1L]Level:7.53|diameter:5.00
0 Particles>10.micron[/0.1L]Level:0.00|diameter:10.00
Finalnotes
API
pms5003APIdescriptionisavailableasaseparatedocument.
Operationsonserialport
SerialinterfaceisnotmanagedbyPms.Youcansuspenddatatransfer,entersleepmode,evenreplaceserialport.Justremembertoexecutepms.begin()toreinitializetheconnection.
namespacepmsx{}
pms5003libraryisdesignedtoavoidnamespacepollution.Allclassesarelocatedinthenamespacepmsx.
Examplesusethefullyqualifiednameslikepmsx::Pmspms(&pmsSerial);
ToreducetypingitisOKtoaddusingnamespacepmsx;atthebeginningandnottotypepmsx::anymoreasinexamples\p04usingPmsx\p04usingPmsx.ino
Itdoesnotchangeresultingcodesize.
About
Arduino:PMS5003AirQualitySensorlibrary.
Topics
arduino
library
sensor
dust
pms5003
pms7003
air-cleanliness
Resources
Readme
License
BSL-1.0License
Stars
77
stars
Watchers
16
watching
Forks
27
forks
Releases
2
Version2.0
Latest
May11,2018
+1release
Packages0
Nopackagespublished
Contributors2
jbanaszczyk
JacekBanaszczyk
per1234
Languages
C++
94.7%
C
5.3%
Youcan’tperformthatactionatthistime.
Yousignedinwithanothertaborwindow.Reloadtorefreshyoursession.
Yousignedoutinanothertaborwindow.Reloadtorefreshyoursession.