Arduino Uno: PM2.5 sensing revisited


Today it’s finally the time to revisit the blog post on using the Honeywell HPMA115S0 particle sensor with an Arduino Uno board. The basics of the operation of the HPMA115S0 and a preliminary version of this code that works with Arduino Due are published in this blog post, so please take a few minutes and read it.

After publishing that blog post, so many of you have asked me to come with a way to make this sensor work with an Arduino Uno. It’s relatively easy to do it, but one must overcome two minor issues:

  • Albeit the HPMA115S0 is powered from a 5V supply, it uses 3.3V logic. To make it work with an Arduino Uno, one must use a logic level converter. In this blog post, I used one BOB-12009 from Sparkfun.
  • The Arduino Uno has a single serial port, which is commonly used to communicate with the PC. The only way to make the PM2.5 sensor work with the Arduino Uno is to use SoftwareSerial, with some minor changes in the code and some quirks that are explained below.

Connections and schematic

The wires used in the blog post to connect the sensor were all red colored.  Getting the right way to connect things was a bit difficult for some people, so I tried to make things a bit easier this time.

HPM Series Particle Sensor pinout

HPM Series Particle Sensor pinout

In the above picture, we can see the sensor with its connector. The pin numbering is a bit odd, with PIN1 near the fan and PIN8 to the edge of the sensor. Only four pins are used in this project: Vcc, RX, TX, and GND.

HPM Series Particle Sensor - connection detail

HPM Series Particle Sensor – connection detail

The wires are still all red, but I’ve put some colored heat shrink tubing on some wires to increase visibility:

  • red is Vcc
  • yellow is TX – this goes to SoftwareSerial RX pin
  • blue is RX – this goes to SoftwareSerial TX pin
  • black is GND

The sensor is connected as follows:

Honeywell PM2.5 sensor Arduino Uno connections

Honeywell PM2.5 sensor Arduino Uno connections

We can see that the logic level converter receives both 5V (red wire) and 3.3V (orange wire) from the Arduino board. GND is connected both to the PM2.5 sensor and to the logic level converter. The sensor is powered from 5V (red wire going to pin2 of the sensor).

Pin11 of the Arduino Uno is SoftwareSerial TX pin and will go to the HV4 pin of the logic level converter. The opposite LV4 pin goes to pin7 of the HPMA115S0 sensor,

Pin10 of the Arduino Uno is SoftwareSerial RX pin and will go to the HV3 pin of the logic level converter. The opposite LV3 pin goes to pin6 (TX) of the HPMA115S0 sensor.

Beloe there are some pictures of the sensor connected to an Arduino Uno:

1 2


  1. Avatar


    I’d really like to try and do this, but I can’t see the code referred to on this or the other post – would you be able to send to me? Also – how long does this take to put together?


  2. Avatar


    I’ve been trying to use this schematic, but after combining all the parts, I get this output:
    Waiting for the first autosend.
    Stopping autosend…

    When I try to change the plugins a bit, it gives me a “waiting for cmd” output, which usually means there’s something wrong with RX and TX pins.

    Any idea what might be causing this?
    Feel free to contact me by Email, as this is an ongoing project.

    Thank you!

    • Teodor Costachioiu
      Teodor Costachioiu on

      I assume you have connected something wrong. I cannot replicate your situation.
      You can try to change the SerialPassthrough sketch to work with Software serial, see what the sensor is sending.

      • Avatar

        Hey, thanks for the reply.

        I’ve been trying to use that sketch, as well as switching the RX and TX pins to 2 and 3 as to not interfere with the ethernet shield’s SD capacity (I’ve changed the code accordingly), to no avail. Still no output.

        I used a different schematic previously, with a direct connection from the sensor to the board, which gave me an output, although it wasn’t reliable or steady.
        Do you think there’s a way to skip the level shifter and connect the sensor straight to the Uno (Trying to build a compact, small system), or would the best course of action be to get a different board? the Due, for instance?

        Appreciate it!

  3. Avatar

    I’m sure someone would eventually catch this, but in the interest of accuracy, I point out the following error in a wiring diagram.

    In the paragraph that begins “Below there are some pictures of the sensor connected to an Arduino Uno”, the top right picture (×140.jpg), has the orange wire connected to Arduino RESET and red wire connected to Arduino 3.3V. Instead it should be: orange wire connected to Arduino 3.3V and red wire connected to Arduino 5V.

    • Teodor Costachioiu
      Teodor Costachioiu on

      Hi Mark,
      You are right. I must have misplaced the wires when I did the photo session.
      For now, I have removed the images with the wrong connections, and I will reshoot them as soon as possible.

  4. Avatar

    Found a typo in the code. In read_measurement(), the line that says:
    if (((0x10000 – HEAD – LEN – COMD – DF1 – DF2 – DF3 – DF4) % 0XFF) != CS){
    should instead be:
    if (((0x10000 – HEAD – LEN – COMD – DF1 – DF2 – DF3 – DF4) & 0XFF) != CS){

    • Teodor Costachioiu
      Teodor Costachioiu on

      Hi Mark,

      In the datasheet, the checksum is computed as:
      CS = MOD ((65536-(HEAD+LEN+CMD+DATA)), 256)
      65536 is 0x10000
      256 is 0xFF
      In Arduino IDE the modulo operator is %

      Thus, we have
      if (((0x10000 – HEAD – LEN – COMD – DF1 – DF2 – DF3 – DF4) % 0XFF) != CS){

  5. Avatar

    Thanks for the code, but I’m working with a mkrwan 1300 and it only has 1 uart port (and software serial is not available)
    I changed your code to use the regular uart, to know if the code works, I let a led go on before your func (start, stop, …)
    But the led never switches of. The code passes flush, but gets stuck at stop_autosend
    Any idea why?

    This is the code:

  6. Avatar


    I copy pasted your code and tried to upload it to my Arduino Uno but I am getting the following error:

    “Sketch uses 5044 bytes (15%) of program storage space. Maximum is 32256 bytes.

    Global variables use 570 bytes (27%) of dynamic memory, leaving 1478 bytes for local variables. Maximum is 2048 bytes.”

    the code complied, but the orange error message is prompting up when im trying to upload/

    This is my first project with Arduino, your help would be much appreciated

    Best Regards

  7. Avatar

    Great article, it made my project so much easier. But i have a question and a remark.
    The question:
    – The PM2.5 value is always 1 lower than the PM10 value (ex PM10: 15, PM2.5: 14) is this normal?
    – What are “normal” values you are measuring?
    The remark:
    – it is better to put in a timeout in every Serial.available in case something goes wrong

  8. Avatar

    good friend, very good your blog has been a great help I have a question when you say that the arduino mega requires a logical converter: bone mega serial port would not serve me as you announced in another part of your blog? that explains with a serial port and the same in some parts of your program thanks.
    “The HPMA115S0 sensor requires a power of 5 V, but uses logic levels of 3.3 V on TX and RX lines, as such, a logic level converter such as BOB-12009 is required when using the sensor with 5 V tables As Arduino Uno and Mega, as I did in this blog post, on 3.3V plates like Arduino Due, the TX and RX lines can be connected directly to the board. “

    • Teodor Costachioiu
      Teodor Costachioiu on

      Arduino Mega is a 5V device, while the sensor requires 3.3V logic levels. This is why you need an logic level converter.
      On the other hand, with the Mega you have four hardware serial ports, so you don’t need SoftwareSerial.

  9. Avatar

    Hi Teodor,
    Great tutorial!
    I was using your code with Arduino Mega, with a level shifter, and encountered some problem. My sensor is hooked up with serial1 (pin 18,19) instead. I replace all portOne in your code with Serial1. I keep getting error messages saying Checksum fail. Do you happen to know what I may have done wrong? I’m new to Arduino, and some “common sense” staff may just trip me over. Any suggestion helps.

    • Teodor Costachioiu
      Teodor Costachioiu on

      Have you wired the sensor correctly?
      – 5v power to the sensor
      – 5v and 3.3v power to the level shifter
      – TX of Arduino to RX of the sensor
      – RX of Arduino to TX of the sensor

      • Avatar

        Yes. I have 5v–>5v, GND–>GND, TX –>level shifter –> RX (pin 19), RX –>level shifter –> TX (pin 18). Fan is working. TX LED is blinking, but RX LED is not.


        • Avatar

          I replugged everything. Now that it’s reading most of the time. The output seems a bit odd though. My pm2.5 and pm10 reads around 60. I have other sensors read around 4 right beside the honeywell. Is this a reading you normally get indoors? If not, do you know what may be the problem?

          • Teodor Costachioiu
            Teodor Costachioiu on

            From the sensor’s point of view, getting a PM10 of 60 indoor is OK. But it’s over the recommended limits
            I would expect the PM2.5 to be much smaller than PM10, as the mass of those particles is also smaller. Also, I have compared the Honeywell sensor against one SDS011, and Honeywell sensor always outputs a bit higher values than SDS011.
            You can also run the SerialPassthrough sketch and communicate directly with the sensor. Put it in continuous mode and see what its output look like.

        • Teodor Costachioiu
          Teodor Costachioiu on

          Don’t forget to provide 3.3V to the level shifter, too. Otherwise, it’s unstable.

          • Avatar

            Hi Teodor,
            I tried running SerialPassThrough as you suggested, and my serial prints nothing at all… I don’t know what I did wrong. I used the sketch example from the Communication library.
            My PM2.5 reading is now half time checksum fail, and the other at absurd values, ~300.
            Do you think there is something wrong with the sensor? I do have 3.3v for the level shifter.
            Any suggestion helps. I’m new at Arduino, and a detailed explanation really helps.
            Thank you so much.

  10. Avatar

    Good evening teodor, thank you very much for sharing your knowledge I have been working with the program and with the logic converter and it has a better response, but I still have a measurement error and I did all the above to this comment wiring and level converter reviewed. 1- change the programming since I am using the Arduino mega Long by float unit_8 by byte since in these conditions the bone sensor can work, I obtain values. 2- I am measuring voltage in the input of the sensor and level exchanger I get readings of 4.88 volts since I energize with the same Arduino connected to the pc. I am aware that this may be my fault but I still wanted to ask about the program if I modified it well or I am having a programming flaw, the tests of the sensor I do them at temperature of 30 ° and sources of pm with the burning of cigarette or papers thanks

    bool my_status;
    float PM25;
    float PM10;
    HPMA115S0 my_hpm(Serial3);
    void setup() {
    while (!Serial);
    byte read1 =;
    byte read2 =;

    Waiting for the first autosend.
    Flushing buffer…
    Stopping autosend…
    Stop autosend status is 1
    Starting measurements…
    Start measurement status is 1

    Take some measurements and then
    “Checksum fail”

    • Teodor Costachioiu
      Teodor Costachioiu on

      Hi Andes,

      Please check page 6 in the sensor’s datasheet.
      When first started, the sensor should respond with a 32-byte data frame, which you receive. But the content you receive from your sensor is wrong – bytes 6 to 9 should contain the PM2.5 and PM10 values, but you read 0.
      As a comparison, my sensor responds with 424D001C0000000A000B00000000000000000000000000000000000051000111

      That makes me think you have a defective sensor!!!

      • Avatar

        Thanks for answering Teodor, I had not taken into account the answer of the 32 bytes of start of equal I wanted to ask if the change of programming could be affecting something, tomorrow I will try with an external source for the 5v required for the sensor, the changer level and change the serial port, is there any other way to be able to test the sensor and check the status of it? Thank you I’ll be on the lookout

  11. Avatar

    hi Teodor,
    I have a problem with the cabling, in the fourth photo I can’t see how the circuit is ended. I’m probably doing something wrong because the rest of the circuit is the same as your’s but the output I get from the PM2.5 and PM10 are 0.

    • Teodor Costachioiu
      Teodor Costachioiu on

      Gnd (black color) is provided to the sensor and to GND pin of the logic level converter
      5V (red) goes to the sensor and the HV pin of the level converter
      3.3v (orange) goes to LV pin of the level converter
      Note: The logic level converter needs both 5V and 3.3V to work.
      TX of the sensor (yellow) goes to LV3. The opposite pin HV3 (also yellow) goes to Arduino pin 10
      RX of the sensor (blue) goes to LV4. The opposite pin HV4 goes to Arduino pin 11

      You could try to swap TX and RX lines in the code. Also, you can modify the SerialPassthrough sketch to work with SoftwareSerial and try to communicate directly with the sensor.

  12. Avatar

    Hi Teodor,
    Thank you very much for your tutorial, I have a question regarding the sensor used. The density used by the sensor and the flow rate of air withdraw from it are not specified in the datasheet.
    Do you know these values?

    • Teodor Costachioiu
      Teodor Costachioiu on

      Unfortunately no. However, the sensor is given to operate between -20°C to 50°C, and 0 to 99% humidity, so it should withstand some significant changes in air density. I wasn’t able to find anything related to the airflow.

  13. Avatar

    I am using Honeywell HPMA115S0-XXX sensor.
    My PM2.5 and PM10 values difference is not more than 1 and 2.
    My output example is – PM2.5=13 then PM 10 = 14 .
    Is this Honeywell sensor will give output in the diffrence of 1’s and 2’s only or Will I have to do some changes in coding.
    Help me from those errors.

Leave A Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.