Particulate sensor interface to any Picaxe

I'm currently updating my old Picaxe based environmental data logger, that up until now has only measured temperature, relative humidity and carbon dioxide concentration. There are now some affordable particulate sensors that can measure the three main particulate sizes of concern as fair as air pollution is concerned, PM1.0, PM2.5 and PM10 (1µ, 2.5µ and 10µ respectively). I've purchased a Plantower PMS5003, for around £18 from Ebay (search for PMS5003 and you should find a current price).

These unit have a small sampling fan and use a laser to measure the size and concentration of particulates within a measurement chamber, and output data via a serial port. Although they run from 5V, the serial port runs at 3.3V, but this isn't an issue as you don't need to connect the serial input and a Picaxe running on 5V will happily read serial data at 3.3V.

There are a few gotcha's to watch, though. If using a software serial port on the Picaxe, then you need to run the Picaxe at a high clock speed, in order to capture the long sequence of bytes at 9600 baud that the thing squirts out. It outputs 16 bit data words in the form high byte followed by low byte, so the bytes used to store the data need to be in reverse order if you then just want to use the word variables for the 16 bit data values.

The unit also outputs data in different formats, and for measuring atmospheric particulate concentration you only need to capture data words 4, 5 and 6, as these give the particulate concentration in µg/m³ for each category.

Below is my rough and ready test code for reading the serial data in through port C.3 on a Picaxe 08M2. For the finished project I'll use a bigger Picaxe, as I want to add quite a few sensors, including a GPS module to record position, date and time data, with the data either being stored on a µSD card or possible a USB stick, using a Vdrive2 module. I'll probably have a local LCD display too, so that measurements can be read off directly.

In case anyone else wants to play with one of these, then you can connect it with just three wires, +5V, 0V and serial data out. This is the test code I used to just echo the received data back to the terminal:

;Test code for Plantower PMS5003 particulate monitor

;Baud rate is 9600, no check bit 1 stop bit, at 3.3V 

;No need for serial input connection, as the module outputs a 32 data byte stream continuously

;No need for level conversion as a Picaxe running on 5V is OK receiving serial data at 3.3V
;Works OK with Picaxe running from 3.3V or 5V

;Picaxe needs to run fast (32MHz) in order for the software serial port to respond quickly enough

;for atmospheric environment measurements use bytes 10 to 15 (words data4 to data6)

;bytes 1 and 2 are start characters (66 & 77, or ASCII "BM")
;bytes 3 and 4 are frame length characters
;bytes 4 and 5 are data1 characters
;bytes 6 and 7 are data2 characters
;bytes 8 and 9 are data3 characters
;bytes 10 and 11 are data4 characters
;bytes 12 and 13 are data5 characters
;bytes 14 and 15 are data6 characters
;bytes 16 and 17 are data7 characters
;bytes 18 and 19 are data8 characters
;bytes 20 and 21 are data9 characters
;bytes 22 and 23 are data10 characters
;bytes 24 and 25 are data11 characters
;bytes 26 and 27 are data12 characters
;bytes 28 and 29 are data13 characters
;bytes 30 and 31 are data and check characters

;Data acquisition is triggered by detecting the two start bytes, 66 and 77 (ASCII "B" and "M"), that are
;a unique combination that does not occur anywhere in the normal data stream

#picaxe 08M2

#terminal 38400

symbol particulate_data_rx = c.3

symbol sparebyte1 = b0	;w0	only kept spare in case I need to use b0 for bit addressing for a display
symbol sparebyte2 = b1	;w0

;data byte reference numbers below are as given in the Plantower data sheet.  Note that they are transmitted
;high byte first;the byte order is reversed to allow the 16 bit word variable to concatenate the 2 bytes correctly

symbol data4h = b3	;w1
symbol data4l = b2	;w1

symbol data5h = b5	;w2
symbol data5l = b4	;w2

symbol data6h = b7	;w3
symbol data6l = b6	;w3

symbol data4 = w1		;b2 + b3	PM 1.0 data, expressed in µg/m³ (for atmospheric measurements)
symbol data5 = w2		;b4 + b5	PM 2.5 data, expressed in µg/m³ (for atmospheric measurements)
symbol data6 = w3		;b6 + b7	PM 10 data, expressed in µg/m³ (for atmospheric measurements)

setfreq m32


	;first 8 bytes are ignored by over-writing byte data4h
	serin particulate_data_rx, T9600_32, ("BM"),  data4h, data4h, data4h, data4h, data4h, data4h, data4h, data4h, data4h, data4l, data5h, data5l, data6h, data6l
	sertxd ("PM1.0 = ", #data4, "  PM2.5 = ", #data5, "  PM10 = ", #data6, cr, lf, cr, lf)
	goto main
These devices don't look like they're weatherproof; are you only interested in inside air pollution ... or do you have a cunning plan? :)
I have a cunning plan!

The idea is to make a housing a bit like a weather station, with rain screening and mesh that is fine enough to keep bugs out but not so fine as to interfere with the particulate measurement. The current plan is to try and do this using plastic duct fittings, with a 100mm bit of duct as the main housing, with some fairly large holes drilled in it and stainless mesh glued inside that, then with some 125mm to 100mm reducers (like these: glued on the outside plus some form of lid over the top.


Senior Member
The PurpleAir sensor aimed at the enthusiast market uses two PMS5003 sensors, my understanding is that they compare readings from the two units as a sanity check before publishing the data. Their assembly does not have much environmental protection. Basically the two sensors are mounted side by side in what appears to be a large PVC pipe cap pointing downwards. There is no insect screen or other protection except that the sensors are 1/4 inch or so above the lower edge of the cap - see the picture in this evaluation report.

I also have a PMS5003 running. Mine is connected directly to a PC with a 2.4 GHz serial wireless link and a Python program to collect and upload the data to my websever. For reliable operation I found it was necessary to pull pins 3 and 6 to 3.3 volts (I used 10K's). I also implemented checking the check code in my program, I think that's worthwhile and should be easy to do in the picaxe too.