It's easy to use the PM2.5 and the Adafruit CircuitPython PM25 module. This library allows you to easily write Python code that reads particle concentrations, and particle diameter and the number of particles with different diameters per unit volume.

You can use this sensor with any CircuitPython microcontroller board or with a computer that has GPIO and Python thanks to Adafruit_Blinka, our CircuitPython-for-Python compatibility library.

CircuitPython Microcontroller Wiring

First, connect the sensor to your microcontroller board using UART (a serial port).

Here is an example of it connected to a Feather M0 using UART:

  • Sensor VCC to board 5V
  • Sensor GND to board GND
  • Sensor TX to board RX

Remember: RX does not connect to RX!

Python Computer Wiring

Since there's dozens of Linux computers/boards you can use we will show wiring for Raspberry Pi. For other platforms, please visit the guide for CircuitPython on Linux to see whether your platform is supported

Here you have two options: An external USB-to-serial converter, or the built-in UART on the Pi's RX pin. Here's an example of wiring up the USB-to-serial converter:

  • Sensor VCC to USB 5V
  • Sensor GND to USB GND
  • Sensor TX to USB RX (white wire)

Remember: RX does not connect to RX!

For single board computers other than the Raspberry Pi, the serial port may be tied to the console or not be available to the user. Please see the board documentation to see how the serial port may be used

Here's an example using the Pi's built-in UART:

  • Sensor VCC to Pi 5V
  • Sensor GND to Pi GND
  • Sensor TX to Pi RX

Remember: RX does not connect to RX!

If you want to use the built-in UART, you'll need to disable the serial console and enable the serial port hardware in raspi-config. See the UART/Serial section of the CircuitPython on Raspberry Pi guide for detailed instructions on how to do this.

To use the pm25_simpletest.py with the PM2.5 sensor, you'll have to make some changes.

CircuitPython & Python Usage

To demonstrate the PM2.5 in CircuitPython and Python, let's look at a complete program example.

CircuitPython Microcontroller

With a CircuitPython microcontroller, save this file as code.py on your board. Then comment out the following lines by inserting a '#' before each one:

Download: file
i2c = busio.I2C(board.SCL, board.SDA, frequency=100000)

pm25 = adafruit_pm25.PM25_I2C(i2c, reset_pin)

And uncomment the following lines by removing the '' (hash and space both!) before each one:

Download: file
# uart = busio.UART(board.TX, board.RX, baudrate=9600)

# pm25 = adafruit_pm25.PM25_UART(uart, reset_pin)

Then,  open up the serial console to see its output.

Linux/Computer/Raspberry Pi with Python

When using a USB to serial cable or a Raspberry Pi, comment out the following lines by inserting a '#' before each one:

Download: file
i2c = busio.I2C(board.SCL, board.SDA, frequency=100000)

pm25 = adafruit_pm25.PM25_I2C(i2c, reset_pin)

For Raspberry Pi, uncomment the following lines by removing the '' (hash and space both!) before each one:

Download: file
# import serial
# uart = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=0.25)

For a USB to serial cable, uncomment the following lines by removing the '' (hash and space both!) before each one:

Download: file
# import serial
# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=0.25)

Install the python serial with library with

pip3 install pyserial

Now you're ready to run the program with the following command:

Download: file
python3 pm25_simpletest.py
"""
Example sketch to connect to PM2.5 sensor with either I2C or UART.
"""

# pylint: disable=unused-import
import time
import board
import busio
from digitalio import DigitalInOut, Direction, Pull
import adafruit_pm25

reset_pin = None
# If you have a GPIO, its not a bad idea to connect it to the RESET pin
# reset_pin = DigitalInOut(board.G0)
# reset_pin.direction = Direction.OUTPUT
# reset_pin.value = False


# For use with a computer running Windows:
# import serial
# uart = serial.Serial("COM30", baudrate=9600, timeout=1)

# For use with microcontroller board:
# (Connect the sensor TX pin to the board/computer RX pin)
# uart = busio.UART(board.TX, board.RX, baudrate=9600)

# For use with Raspberry Pi/Linux:
# import serial
# uart = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=0.25)

# For use with USB-to-serial cable:
# import serial
# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=0.25)

# Connect to a PM2.5 sensor over UART
# pm25 = adafruit_pm25.PM25_UART(uart, reset_pin)

# Create library object, use 'slow' 100KHz frequency!
i2c = busio.I2C(board.SCL, board.SDA, frequency=100000)
# Connect to a PM2.5 sensor over I2C
pm25 = adafruit_pm25.PM25_I2C(i2c, reset_pin)

print("Found PM2.5 sensor, reading data...")

while True:
    time.sleep(1)

    try:
        aqdata = pm25.read()
        # print(aqdata)
    except RuntimeError:
        print("Unable to read from sensor, retrying...")
        continue

    print()
    print("Concentration Units (standard)")
    print("---------------------------------------")
    print(
        "PM 1.0: %d\tPM2.5: %d\tPM10: %d"
        % (aqdata["pm10 standard"], aqdata["pm25 standard"], aqdata["pm100 standard"])
    )
    print("Concentration Units (environmental)")
    print("---------------------------------------")
    print(
        "PM 1.0: %d\tPM2.5: %d\tPM10: %d"
        % (aqdata["pm10 env"], aqdata["pm25 env"], aqdata["pm100 env"])
    )
    print("---------------------------------------")
    print("Particles > 0.3um / 0.1L air:", aqdata["particles 03um"])
    print("Particles > 0.5um / 0.1L air:", aqdata["particles 05um"])
    print("Particles > 1.0um / 0.1L air:", aqdata["particles 10um"])
    print("Particles > 2.5um / 0.1L air:", aqdata["particles 25um"])
    print("Particles > 5.0um / 0.1L air:", aqdata["particles 50um"])
    print("Particles > 10 um / 0.1L air:", aqdata["particles 100um"])
    print("---------------------------------------")

You should see output looking something like the following:

That's all there is to using the PM2.5 air quality sensor with CircuitPython!

This guide was first published on Dec 27, 2017. It was last updated on Dec 27, 2017.
This page (Python & CircuitPython) was last updated on Sep 30, 2020.