Arduino: measuring PM2.5 and PM10 with Honeywell HPMA115S0

Nov 23, 2017 0 comments

An essential aspect of measuring air quality is to determine the number of small particles. That is, things smaller than 10µm and 2.5µm. Such tiny particles are roughly the size of a microbe and can penetrate the lungs,  causing many health issues.

But how we can measure such small things? Most often, this is done via laser scattering: a laser light source illuminates small particles as they are pulled through the detection chamber. As these particles pass through the laser beam, the variations in light intensity are recorded by a photodetector. Those variations can be further analyzed to determine number and size of particles.

Amongst other sensors that use this technology lies the Honeywell HPMA115S0-XXX, a calibrated sensor with digital output via UART protocol. The sensor can determine PM2.5 and PM10 in concentrations up to 1000µg/m3, with an accuracy of ±15%.

When measuring, the fan draws the air in through the air inlet. Particles in the air go through the detection chamber, where they pass through the laser beam. The light reflected off the particles is captured and analyzed by a proprietary algorithm, and the amount of particles in the air is determined. The sensor is internally calibrated, so all we have to do is read the results on the UART interface,

The sensor can operate in the -10°C to 50°C interval, with humidity up to 95%RH, non-condensing, Its lifespan is about 20,000 hr in continuous mode.

The sensor has a very small connector. The datasheet specifies the mating connector as Molex 51021-0800. Be warned, that part no. is only for the plastic housing, it comes without pins.

I deeply hate crimping such smaller connectors, so I tried to find an easier alternative. And I have found some pre-crimped PicoBlade, Molex 06-66-0015 cables.

You might notice I haven’t populated the whole connector as some pins are not connected internally.

Wiring of the sensor requires only four pins:

Pin 2 (Vcc) goes to the 5V pin on the Arduino board.
Pin 6 (UART TX) goes to the RX pin of the Arduino board. This pin uses 3.3V logic level.
Pin 7 (UART RX) goes to the TX pin of the Arduino board. This pin uses 3.3V logic level.
PIN 8 (GND) goes to GND pin of the Arduino Board.

Pin 1 (3.3V output) is left unused.  The wire is in not connected, as the Arduino board provides its own 3.3V power supply.

Please observe the pin numbering, with the rightmost pin being pin #1 (close to the fan), and the leftmost pin being pin #8.

Measuring PM2.5 and PM10 with Arduino Due

The sensor needs 5V power input but relies on a 3.3V logic level interface. This makes things a bit complicated.

Of all the Arduino boards, my choice went to an Arduino Due, more exactly in the shape of the Flip&Click SAM3X by MikroElektronika. The main reason for this choice is that I already have one proto click with screw terminals for UART communication, so it’s easy to make all the required connections.

The 5V power is taken from the Flip & Click board. The Arduino Due works with 3.3V logic, so everything is OK. All I had to do is write the code:

Some explanations regarding the code

The Honeywell HPMA115S0-XXX particle sensor uses a proprietary communication protocol. A command has the following structure: HEAD, LEN, CMD, and CS. HEAD is always 0x68. LEN is the length of the command (can be 0x01 or 0x02). CMD is one or two bytes and contains the command code. Finally, the checksum byte is determined as CS = 0x10000 — HEAD — LEN — COMD — DF1 — DF2 — DF3 — DF4) % 0XFF. Note that in the datasheet there’s a mixture of decimal and hex values. It’s quite difficult to read and understand it.

The sensor will respond with either 0x9696 for NACK or will respond with 0xA5A5 for positive ACK. As an exception, the command to read particle data will have as a positive response a string starting with HEAD = 0x40, LEN = 0x05, CMD = 0x04, followed by four bytes of PM measurement data and the CS byte.

In the continuous mode, after responding with 0xA5A5 as positive ACK, the sensor will return a 32-byte string now and then. Parsing of this string is not performed in the above code, but one can easily make the required changes to work with the sensor in the continuous mode.

Right now, the code does the following:

    Serial is used to communicate with the PC, Serial3 is used to communicate with the sensor.
    After initializing the two interfaces, the command to stop auto sendingAlbeit io data is issued.
    After a short delay, the start measurement command is sent. This will turn on the fan, and the sensor is ready to perform measurements
    in the main loop, the command to read data is issued every minute. Then, the response is read and parsed, the PM2.5 and PM10 data being sent to the PC.
    Albeit implemented, the stop measurement command is not used. That command turns off the fan, thus prolonging the sensor’s life. One can use that command to stop the sensor if the temperature and humidity are outside the operating range, for example.

As a final verdict, this is a nice sensor. I’ve got the sensor for 23,86 € + VAT. Even considering the price of the Molex connector and pre-crimped cables, which add some other 10€, this sensor is relatively cheap.

[Update March 19, 2019] I wrote a code library for the sensor, you can download it from

Related Posts


{{posts[0].date}} {{posts[0].commentsNum}} {{messages_comments}}


{{posts[1].date}} {{posts[1].commentsNum}} {{messages_comments}}


{{posts[2].date}} {{posts[2].commentsNum}} {{messages_comments}}

Contact Form


Email *

Message *

Recent Comments