Arduino Uno: PM2.5 sensing revisited


Arduino Uno code

The code is a variation of the code in the original blog post, but now it uses Software Serial.

One might observe the change in the flush_portOne routine, which now expects an array of 32 bytes. As the sensor doesn’t issue any string terminator. A 10-second timeout was also implemented, unlike in the original code. This routine is required as the sensor starts in auto-send mode, and we want to put in in manual mode.

Even with those changes, there are some minor quirks and unsolved things. In particular, when the reset button of the Arduino Uno is pressed, the sensor becomes unresponsive. I assume this has something to do with the way SoftwareSerial initializes, as this won’t happen with hardware serial. The only way to make the sensor work is to briefly remove 5V power from the sensor and reapply it before the timeout expires.

1 2


  1. Hello,

    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. Greetings,

    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.

      • 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. 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. 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. Hello,
    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:

Leave A Reply

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