dvsu / sps30

Python-based driver for Sensirion SPS30 particulate matter sensor. Tested on Raspberry Pi Zero/Zero W/3B+/4B.
MIT License
20 stars 8 forks source link

I'm using your code for the SPS30 which is really cool but I have a problem. #1

Open jbasemvd opened 2 years ago

jbasemvd commented 2 years ago

I'm hoping you can help me with an error running example.py. I get this error:

Serial number: CCC69E8DCEAD8B5F Status register: {'speed_status': 'ok', 'laser_status': 'ok', 'fan_status': 'ok'} Traceback (most recent call last): File "/home/pi/Source/SPS30/example.py", line 13, in print(f"Auto cleaning interval: {pm_sensor.read_auto_cleaning_interval()}s") File "/home/pi/Source/SPS30/sps30.py", line 167, in read_auto_cleaning_interval data = self.i2c.read(NBYTES_AUTO_CLEANING_INTERVAL) File "/home/pi/Source/SPS30/i2c/i2c.py", line 21, in read return list(self.fr.read(nbytes)) OSError: [Errno 121] Remote I/O error

If I remove/comment the line print(f"Auto cleaning interval: {pm_sensor.read_auto_cleaning_interval()}s")line I get readings as expected:

Do you have any thoughts on what might be happening?

Here is the code I'm using which is the example.py file included in the download:

import sys import json from time import sleep from sps30 import SPS30

if name == "main": pm_sensor = SPS30() print(f"Firmware version: {pm_sensor.firmware_version()}") print(f"Product type: {pm_sensor.product_type()}") print(f"Serial number: {pm_sensor.serial_number()}") print(f"Status register: {pm_sensor.read_status_register()}")

print(f"Auto cleaning interval: {pm_sensor.read_auto_cleaning_interval()}s")

pm_sensor.start_measurement()

while True:
    try:
        print(json.dumps(pm_sensor.get_measurement(), indent=2))
        sleep(2)

    except KeyboardInterrupt:
        print("Stopping measurement...")
        pm_sensor.stop_measurement()
        sys.exit()

Thanks advance, Walt

dvsu commented 2 years ago

Hi Walt,

OSError: [Errno 121] Remote I/O error relates to I2C device connection. It can be either caused by loose wiring or R/W timing. At first, I thought it might be caused by loose wiring. But judging from the output, it might not be the case. serial_number() and read_status_register() methods share the same I2C class and it seems to function properly. Then the cause may be the latter.

I scan through the latest Sensirion SPS30 datasheet (page 18), and discover that there is command execution time difference between firmware version 1.0 and 2.2. Could you check your SPS30 FW version once again and confirm whether this is the cause? If it is, try to introduce some delay and see whether it solves the problem.

def read_auto_cleaning_interval(self) -> int:
        # sleep(0.05) # this delay may not be required, but feel free to try
        self.i2c.write(CMD_AUTO_CLEANING_INTERVAL)
        sleep(0.05) # try adding this delay
        data = self.i2c.read(NBYTES_AUTO_CLEANING_INTERVAL)

At the same, I will check it on my side when I get the RasPi board and sensor ready. I will keep you updated.

Dave

jbasemvd commented 2 years ago

Hello Dave,

I really appreciate you taking the time to trouble shoot this and respond.

Before you spend a lot of time getting your device hooked up again I’ve switched my hardware to a M5Stack which is an ESP32 device. I’m using the code provided by Sensirion which I was able to get working with I2C. I haven’t been able to get the UART version running but I can live with the I2C for my purpose. I was able to write some code to obtain the following information:

Serial number : CCC69E8DCEAD8B5F

Product name : 00080000

Version: Firmware level: 2.1

Library level : 1.4

I wrote to Sensirion to inquire as to how I can update the Firmware to version 2.2 but haven’t received a response just yet.

I’ll let you know what I learn regarding the firmware.

Once again thank you,

Walt

From: Dave @.> Sent: Monday, December 27, 2021 10:24 PM To: dvsu/sps30 @.> Cc: Walt White @.>; Author @.> Subject: Re: [dvsu/sps30] I'm using your code for the SPS30 which is really cool but I have a problem. (Issue #1)

Hi Walt,

OSError: [Errno 121] Remote I/O error relates to I2C device connection. It can be either caused by loose wiring or R/W timing. At first, I thought it might be caused by loose wiring. But judging from the output, it might not be the case. serial_number() and read_status_register() methods share the same I2C class and it seems to function properly. Then the cause may be the latter.

I scan through the latest Sensirion SPS30 datasheet https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/9.6_Particulate_Matter/Datasheets/Sensirion_PM_Sensors_Datasheet_SPS30.pdf (page 18), and discover that there is command execution time difference between firmware version 1.0 and 2.2. Could you check your SPS30 FW version once again and confirm whether this is the cause? If it is, try to introduce some delay and see whether it solves the problem.

def read_auto_cleaning_interval(self) -> int:

sleep(0.05) # this delay may not be required, but feel free to try

    self.i2c.write(CMD_AUTO_CLEANING_INTERVAL)
    sleep(0.05) # try adding this delay
    data = self.i2c.read(NBYTES_AUTO_CLEANING_INTERVAL)

At the same, I will check it on my side when I get the RasPi board and sensor ready. I will keep you updated.

Dave

— Reply to this email directly, view it on GitHub https://github.com/dvsu/sps30/issues/1#issuecomment-1001848949 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJWPNGDQQRRGLLAHJYEN5TUTEUUTANCNFSM5KXDBKUQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub . You are receiving this because you authored the thread. https://github.com/notifications/beacon/AAJWPNGPSUOSJA3EZR4EHKDUTEUUTA5CNFSM5KXDBKU2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOHO3QA5I.gif Message ID: @. @.> >

drevil75 commented 1 year ago

Hello Dave,

i had the same problem like walt. I've tried the sleep commands and it's working. My SPS30 has the FW-Version: 2.3

But i've an additional Question. In the response below is a key/value for "particle_count" pm0.5: 1234.. But there is no similar key/value under "mass density". I've tried to add the key/value pair in the sds30.py, but i still get no density for pm0.5.

Do you know why?

BR Mirko

drevil75 commented 1 year ago

...and here the response.. { "sensor_data": { "mass_density": { "pm1.0": 8.004, "pm2.5": 10.587, "pm4.0": 12.279, "pm10": 13.211 }, "particle_count": { "pm0.5": 49.857, "pm1.0": 61.257, "pm2.5": 63.669, "pm4.0": 64.11, "pm10": 64.223 }, "particle_size": 0.704, "mass_density_unit": "ug/m3", "particle_count_unit": "#/cm3", "particle_size_unit": "um" }, "timestamp": 1672603643 }

dvsu commented 1 year ago

Hi Mirko,

Regarding your second question, it is in fact the limitation of the sensor. If you refer to the latest datasheet, specifically on page 2 and 6, it states that the supported measurements are

Mass concentration: PM1.0-PM10 (measured in µg/m³) Number concentration: PM0.5-PM10 (measured in counts/cm³)

Also, the specification on page 2 says that the condition for particle to be considered as PM1.0 is by having mass concentration size, ranging from 0.3 to 1.0 μm. So, theoretically, the sensor is able to detect mass density between the range, but it is difficult to differentiate whether the measured mass density is of particle size ranging from 0.3 to 0.5 μm, or 0.5 to 1.0 μm. In other words, the sensor may be able to measure the mass density of PM0.5, but with the trade-off of low precision. I guess, Sensirion chose to combine the measurement as mass density of PM1.0 instead to ensure the measurement precision stay within targeted range.

Dave

Reference

SPS30 Datasheet