adafruit / Adafruit_CircuitPython_PM25

CircuitPython library for PM2.5 sensors
MIT License
28 stars 16 forks source link

In serial, recover poorly from glitch/error/... #4

Closed dglaude closed 4 years ago

dglaude commented 4 years ago

I tested this library with a serial sensor like this: https://www.adafruit.com/product/3686

Within one or two minutes, the code fail (mostly on if b != 0x42:) and does not seems to recover. Some tricks to empty the buffer, re-read or reset should be implemented for more reliability.

The code from the learn guide ( https://learn.adafruit.com/pm25-air-quality-sensor/python-and-circuitpython ) of the product behave much better, even when temporary removing the cable.

Here is the way it fail (and never seems to recover):

Concentration Units (standard)

PM 1.0: 10 PM2.5: 13 PM10: 13 Concentration Units (environmental)

PM 1.0: 10 PM2.5: 13 PM10: 13

Particles > 0.3um / 0.1L air: 1938 Particles > 0.5um / 0.1L air: 518 Particles > 1.0um / 0.1L air: 62 Particles > 2.5um / 0.1L air: 4 Particles > 5.0um / 0.1L air: 0 Particles > 10 um / 0.1L air: 0

Unable to read from sensor, retrying... Unable to read from sensor, retrying... Unable to read from sensor, retrying...

ladyada commented 4 years ago

@dglaude please try and submit a PR if you have some techniques that could be used!

dglaude commented 4 years ago

I proposed #6 and it does improve greatly the stability for me, and this can be tested by plugging and unplugging the cable.

My test code is based on the example but more verbose on exception. I run it on EnviroPlus FeatherWing and would live to see this tested on some other hardware.

import time
import board
import busio
from digitalio import DigitalInOut, Direction, Pull
import adafruit_pm25

reset_pin = None
uart = busio.UART(board.TX, board.RX, baudrate=9600)
pm25 = adafruit_pm25.PM25_UART(uart, reset_pin)

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

while True:
    time.sleep(1)

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

    print(
        "PM 1.0: %d\tPM2.5: %d\tPM10: %d"
        % (aqdata["pm10 standard"], aqdata["pm25 standard"], aqdata["pm100 standard"])
    )

And give this kind of result for various error.

main.py output: Found PM2.5 sensor, reading data... PM 1.0: 17 PM2.5: 26 PM10: 28 PM 1.0: 17 PM2.5: 26 PM10: 28 PM 1.0: 17 PM2.5: 24 PM10: 28 ... PM 1.0: 17 PM2.5: 26 PM10: 29 Unable to read from sensor, retrying... Invalid PM2.5 checksum PM 1.0: 17 PM2.5: 26 PM10: 28 PM 1.0: 17 PM2.5: 26 PM10: 28 ... PM 1.0: 18 PM2.5: 25 PM10: 27 PM 1.0: 17 PM2.5: 22 PM10: 25 Unable to read from sensor, retrying... Unable to read from PM2.5 (no start of frame) PM 1.0: 3 PM2.5: 3 PM10: 3 PM 1.0: 1 PM2.5: 1 PM10: 1 PM 1.0: 4 PM2.5: 7 PM10: 7

dglaude commented 4 years ago

Maybe @Gadgetoid will want to have a look to see if enhancement from https://github.com/pimoroni/pms5003-circuitpython can be introduced here. But #6 solve the issue for me.