Dust Sensor - PMS 5003/6003/7003


i have dust sensor SDS011 + USB adapter
I connect the sensor to raspberry pi, basic to read a sensor I use command:

od --endian=big -x -N10 < /dev/ttyUSB0

so it is giving me for example:
0000000 aac0 8c00 9400 bcf9 d5ab

every packet of data begins “aac0” and rest of the data are converted to useful values (in bash script), basically everything work ok (for graphic representation of data I use RRDtool). But I want compare data from SDS011 with PMS7003. I don’t have any USB adapter so I connect PMS703 to raspberry pi pins.
In PMS7003 datasheet I see that start of the packet of data should be “424d”. First I tryed this command:

sudo od –endian=big -x -N10 < /dev/serial0

but this give me that kind of data:
3500 8200 0a54 008c 000a (first try)
8100 9f00 0a78 0094 000a (second try)
2900 6400 2900 6400 2900 (third try)
I don’t see beginning the data packet “424d”

I tried Python script:

import serial
from time import gmtime, strftime
port = serial.Serial("/dev/serial0", baudrate=9600, timeout=1.5)
data = port.read(32);
PM01 = str(ord(data[5])*256+ord(data[6]))
PM25 = str(ord(data[7])*256+ord(data[8]))
PM10 = str(ord(data[9])*256+ord(data[10]))

but this also give me strange no real value. Why data packet never start from “424d”?


I ordered a PMS7003 and already wrote some software for it.

The approach in the code is that it’s purely a state machine for interpreting the incoming serial bytes. So it will automatically sync to the start of a frame with measurement data, even if you start receiving data halfway inside a frame. It should be buffer-overflow-proof. The parsing code is also stand-alone, with no Arduino dependencies. This makes it easier to test.

My code can be found at: https://github.com/bertrik/pms7003 in modules pms7003.cpp/.h
I haven’t received the module yet, so I haven’t been able to test it with actual hardware, but I did write some unit tests.


Hi folk, I use of Plantower pms 3003 with Teensy 3.2. It’s my code: https://github.com/AndriyHz/Teensy-3.2-and-Thingspeak/blob/master/PM2_with_S8_BME280_WiFi-For-Teensy3.ino
But I see that I receive sometimes incorrect data. For example,
PM2.5 — 50
PM10 — 65
PM2.5 — 50
PM10 — 65

PM2.5 — 170 (once)
PM10 — 500
… again
PM2.5 — 50
PM10 — 65

PM2.5 — 170 (once)
PM10 — 500

Please help me.


This forum is dedicated to Particle devices and not Teensy, maybe you may find better suitable help in a dedicated forum.


Also note that SerialEvent1 should be serialEvent1 otherwise it won’t execute…learned that the hard way…


Hello Martty,

I tried your GitHub code with particle photon and got it working however the Data I am seeing is
PMS7003 [42 4d] (001c) CF1=[000d 0011 0011] amb=[000d 0011 0011] raw=[088b 0292 0052 0005 0001 0000] ver=97 err=00 csum=031f == xsum=031f

in the above test run particle photon is powered by MacBook USB 3, so I am not sure if its serving correct volts. I want to know what value I should be interested in and how should I read it.

EDIT: I believe looking at below chart the data I am getting for PM2.5 is 42μg/m3
correct me if I am wrong !


Wow! I haven’t been here in a while… first of all, here’s a more recent datasheet:


The data is presented above in hexadecimal. [42 4d] are the start characters, nothing more (they and the checksum tell you you’re reading the data accurately.

We then get the CF1 (factory test?) and amb (ambient atmosphere, e.g., what you normally use) datasets, both of which are [PM1.0, PM2.5 and PM10] in ug/m^3.

(They also give raw counts per bin, but that’s beyond the scope of this.)

So, this tells me 13 ug/m3 PM1.0, 17 ug/m3 PM2.5 and 17 ug/m3 of PM10.

As for voltages, though, you should be running a PMS7003 at the full 5vdc for Vcc (the Particle devices typically provide 5v straight from the normal 5v USB lines, typically on the VIN or the VBUS line when powered by USB but please verify this for yourself). The I/O for the device appears to be a nice 3.3V per the spec.

So, wherever you are measuring this, it appears it’s not too bad in terms of air quality. Contrast with the SF Bay area where I am (and where coincidentally Particle’s based) that’s dealing with historic levels of pollution due to wildfires. I’m now curious to see what my device reports for this present environment… the PurpleAir site gives some data - you can select other data there, including PM1.0/PM2.5/PM10 data. I expect my readings to be 5-10x higher than yours.



I dont understand based on what logic given in the data sheet you concluded that ? can you please shed some light ?


On page 14 they specify that CF1 is the factory environment (versus ambient or general usage). Not that it matters here because you have the same exact data for both of them (they can differ but use the ambient one). Pretty sure CF1 is for factory calibration purposes only.

amb=[000d 0011 0011] (hex values) = [PM1.0, PM2.5, PM10] = [13, 17, 17] ug/m^3 respectively in your example above and per the table on page 13.

Finally, see my repo for a more current example that may or may not be interesting.


I see ,

Is below code correct to convert hex value to decimal

#include <string>
#include "math.h"
using namespace std;
unsigned long hex2dec(string hex)
    unsigned long result = 0;
    for (int i=0; i<hex.length(); i++) {
        if (hex[i]>=48 && hex[i]<=57)
            result += (hex[i]-48)*pow(16,hex.length()-i-1);
        } else if (hex[i]>=65 && hex[i]<=70) {
            result += (hex[i]-55)*pow(16,hex.length( )-i-1);
        } else if (hex[i]>=97 && hex[i]<=102) {
            result += (hex[i]-87)*pow(16,hex.length()-i-1);
    return result;

So I just get result like this hex2dec(hex_str)

Thanks (y)


Please look at my most current example. You can just take the uint16_t values and use them directly. You don’t need to convert from hex - I just did that originally as a space-saving convenience for logged output.


Hey guys. Thought you may be interested in this new high quality dust sensor that was just released from Sensirion which has a excellent line of temp, humidity, and VOC chips that I use.

Their chips are very stable so I’ve been waiting for this new dust sensor to be released and now its avaliable.

Your thread here reminded me to check on its avaliability.

You can read the status over I2C which is nice.




Interesting - it also does PM4, and allows I2C as well (at address 0x69). And it’s got a much longer lifespan than the Plantower devices are rated at (8 vs 3 years). Idle current is higher, but it’s not clear how long this new one takes to go from idle to measurement mode.

The trick is finding a cable to plug into it (it doesn’t come with one). It needs a JST ZHR 5-position female connector… which apparently isn’t very easy to find unless you want mass quantities - I’d rather get an assortment of them than a dozen of the same thing if I’m doing that.

Anyway, might just have to buy me one of these sometime - thanks for the tip!



Awesome! I ordered it from there last night (and there’s a sale on right now.)


Sweet discount!

I’m ordering one also.


Please share the library you put together once you receive the sensor.

I see they have links to both the UART & I2C libraries, but supposedly the I2C library does not supply as much data as you can get via the UART option for some reason.


@MartyMacGyver Did you receive that new dust sensor yet?

Mine arrives tomorrow, just wondering if you had it up and running yet or not.


I will also try out the sensirion sensor, so please post updates. Btw has any of you tried the HPMA sensor from Honeywell? If so, any experiences you would like to share?


It Arrived!

I’ll try the libraries on a P1 later and report back if they work or need modification.