Pms5003
Arduino: PMS5003 Air Quality Sensor library.
Install / Use
/learn @jbanaszczyk/Pms5003README
pms5003
I'm proud to present my Arduino library supporting PMS5003 Air Quality Sensor.
License
pms5003 library is distributed under Boost Software License 1.0 (BSL-1.0).
Status
Current revision: 2.1
- There are some TODOs for next revisions
What is new?
Release 2.1 brings a lot of changes and improvements:
- API contract (class names and methods) is completely rewritten. It is not compatible with v1.0. Sorry :(
- Minor bugs are fixed (nothing important, release 1.0 should be assumed as stable).
- Added support for sensor hardware pins (pin 3 - SET, pin 6 - RESET).
- Added support for more serial port libraries (inversion of control).
- Added support for unit tests (soon).
- Added support for ISO 14644-1: Classification of air cleanliness.
- Added more diagnostic checks
- Added support for "views" (will be described later) - the most exciting new feature.
Good, stable revision: 1.0
Previous release: 1.0 is still available.
There is one interesting fork supporting ESP8266: https://github.com/riverscn/pmsx003
Other sensors
My library supports PMS5003 (checked)
For most Plantover sensors probably it is an easy task to add support.
list of compatible sensors is available as a separate document.
Features
- Library supports all Plantover PMS5003 features (sleep & wake up, passive / active modes, hardware pins),
- Highly customizable:
- It uses almost any serial communication library,
- You have a choice to use or not to use: (C style) global variables or (C++ style) class instances.
- Written from scratch,
- Written in modern C++11 (please do not afraid - works fine with Arduino IDE).
- It is "headers only" library.
- The main goal: Reading data from the sensor does not block. Your process receives the status
OKorNO_DATAor some kinds of errors but your process never waits for the data. - Serial port is not managed by the library, it is possible to shut serial driver down, enter sleep mode and so on independently on the PMS5003 sensor.
- Provides support for ISO 14644-1 classification of air cleanliness levels.
API
pms5003 API description is available as a separate document.
TODO
- New methods: some more checks
- #16
write()will returnPmsStatusinstead ofbool - #17 add iterators
begin()andend()for views - #18
isWorking()should returntribool - #19
write(CMD_WAKEUP)should not delay if already awoken - #20
write()multiple commands sequentially - Support for platforms
- Support for boards:
- #24 ESP8266
- #25 Add unit tests
Preparation
IDE & OS
pms5003 library is developed using:
- Visual Studio Community 2017 (Windows)
- Arduino IDE for Visual Studio
pms5003 library was successfully checked using:
- Arduino 1.8.5 (Windows)
Dependencies
- Current version uses DrDiettrich' fork of AltSoftSerial Library. Install it.
- pms5003 will not compile using original AltSoftSerial lib.
- pms5003 will not compile using very old Arduino IDE. Please upgrade.
Library
Install pms5003 library.
Connections
- PMS5003 Pin 1 (violet): VCC +5V
- PMS5003 Pin 2 (brown): GND
Important: PMS5003 sensor uses 3.3V logic. Use converters if required or make sure your Arduino board uses 3.3V logic too.
- PMS5003 Pin 4 (blue): Arduino pin 9 (there is no choice, it is forced by AltSerial)
- PMS5003 Pin 5 (green): Arduino pin 8 (there is no choice, it is forced by AltSerial)
- Optional
- PMS5003 Pin 3 (white): Arduino pin 7 (can be changed or not connected at all)
- PMS5003 Pin 6 (yellow): Arduino pin 6 (can be changed or not connected at all)
- PMS5003 pin 7 (black) and pin 7 (red) leave not connected
Applications
Hello. The Basic scenario.<a name="Hello"></a>
Use the code: examples\p01basic\p01basic.ino
#include <pms.h>
PmsAltSerial pmsSerial;
pmsx::Pms pms(&pmsSerial);
////////////////////////////////////////
void setup(void) {
Serial.begin(115200);
while (!Serial) {}
Serial.println(pmsx::pmsxApiVersion);
if (!pms.begin()) {
Serial.println("PMS sensor: communication failed");
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::PmsData data;
auto status = pms.read(data);
if (status != pmsx::PmsStatus::OK) {
Serial.print("PMS sensor: ");
Serial.println(status.getErrorMsg());
}
pms.write(pmsx::PmsCmd::CMD_MODE_ACTIVE);
if (!pms.isWorking()) {
Serial.println("PMS sensor failed");
}
Serial.print("Time of setup(): ");
Serial.println(millis());
}
////////////////////////////////////////
void loop(void) {
static auto lastRead = millis();
pmsx::PmsData data;
auto status = pms.read(data);
switch (status) {
case pmsx::PmsStatus::OK: {
Serial.println("_________________");
const auto newRead = millis();
Serial.print("Wait time ");
Serial.println(newRead - lastRead);
lastRead = newRead;
auto view = data.particles;
for (auto i = 0; i < view.getSize(); ++i) {
Serial.print(view.getValue(i));
Serial.print("\t");
Serial.print(view.getName(i));
Serial.print(" [");
Serial.print(view.getMetric(i));
Serial.print("] ");
// Serial.print(" Level: ");
// Serial.print(view.getLevel(i));
Serial.print(" | diameter: ");
Serial.print(view.getDiameter(i));
Serial.println();
}
break;
}
case pmsx::PmsStatus::NO_DATA:
break;
default:
Serial.print("!!! Pms error: ");
Serial.println(status.getErrorMsg());
}
}
And the result is (something like this):
Port open
pms5003 2.1
Time of setup(): 2589
_________________
Wait time 906
27 PM1.0, CF=1 [micro g/m3] | diameter: 1.00
34 PM2.5, CF=1 [micro g/m3] | diameter: 2.50
35 PM10. CF=1 [micro g/m3] | diameter: 10.00
23 PM1.0 [micro g/m3] | diameter: 1.00
31 PM2.5 [micro g/m3] | diameter: 2.50
35 PM10. [micro g/m3] | diameter: 10.00
8760 Particles > 0.3 micron [/0.1L] | diameter: 0.30
1780 Particles > 0.5 micron [/0.1L] | diameter: 0.50
70 Particles > 1.0 micron [/0.1L] | diameter: 1.00
18 Particles > 2.5 micron [/0.1L] | diameter: 2.50
1 Particles > 5.0 micron [/0.1L] | diameter: 5.00
1 Particles > 10. micron [/0.1L] | diameter: 10.00
37120 Reserved_0 [???] | diameter: 0.00
More about the example
Before
To use the library:
- install (download and "Add .ZIP library") DrDiettrich' fork of AltSoftSerial Library
- install (download and "Add .ZIP library") pms5003 library
- include
pms.hin your code:
#include <pms.h>
Create instance of serial driver
PmsAltSerial pmsSerial;
Create instance of pmsx::Pms object:
- library namespace name is
pmsx - class name of the object is
Pms - object is named
pms - object uses previously created driver
pmsSerial
pmsx::Pms pms(&pmsSerial);
setup()
Initialize serial library. If Arduino can't communicate with PMS5003 - there is no sense to perform the next steps.
pms5003 takes care on protocol details (speed, data length, parity and so on).
if (!pms.begin()) {
Serial.println("PMS sensor: communication failed");
return;
}
The next step is to define Arduino pins connected to pms5003:
- SET (pms5003 pin 3, white) (sleep/wakeup)
- RESET (pms5003 pin 6, violet) (sensor reset)
This step is optional.
- If SET pin is not connected - sleep/wakeup commands are executed using serial connection
- If RESET pin is not connected - sleep and then wakeup works like reset
If pins are not connected - just remove appropriate setPinReset/setPinSleepMode lines.
pms.setPinReset(6);
pms.setPinSleepMode(7);
The next task is to put sensor in a well known state. There are two aspects of PMS5003 state:
- sleeping/awoken
- passive/active
Both can be examined using isModeActive()/isModeSleep(). Please note, that result value is a tristate logic
Related Skills
node-connect
338.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
338.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.4kCommit, push, and open a PR
