Issue with i2c setup
Hello
I am trying to use this cool library on a raspberrypi 4b with circuitpython. I have two other sensors connected on the i2c working ok. My circuitpython i2c interface is setup like so:
import json
import socket
import time
import adafruit_scd30
import adafruit_sht4x
import board
i2c = board.I2C()
sht = adafruit_sht4x.SHT4x(i2c)
scd = adafruit_scd30.SCD30(i2c)
So adding the code for sps30 looks like this:
import json
import socket
import time
import adafruit_scd30
import adafruit_sht4x
import board
import sys # this is not working - greyed out
from sps30 import SPS30
i2c = board.I2C()
sht = adafruit_sht4x.SHT4x(i2c)
scd = adafruit_scd30.SCD30(i2c)
# sps dust sensor setup
if __name__ == "__main__":
pm_sensor = SPS30(i2c)
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")
print(f"Set auto cleaning interval: {pm_sensor.write_auto_cleaning_interval_days(2)}s")
pm_sensor.start_measurement()
This throws an error, because I guess its referencing a different I2C setup in your files?
Traceback (most recent call last):
File "/opt/piMonitor_env/airmonitor.py", line 111, in <module>
pm_sensor = SPS30(i2c)
File "/opt/piMonitor_env/sps30.py", line 50, in __init__
self.i2c = I2C(bus, address)
File "/opt/piMonitor_env/i2c/i2c.py", line 11, in __init__
self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-<busio.I2C object at 0x7f86cf22b0>'
Any ideas how to use circuitpythons i2c setup?
It seems both adafruit_sht4x.SHT4x and adafruit_scd30.SCD30 require I2C object while the SPS30 requires optional I2C bus number as input. Assuming the SPS30 sensor is connected on bus 1, you may leave the SPS30 argument blank, i.e. SPS30(). If it is connected to an I2C bus other than bus 1, let say bus 2, pass the bus number as an argument when you initialize the SPS30, e.g. SPS30(2)
if __name__ == "__main__":
pm_sensor = SPS30() # leave the argument blank if the sensor is connected to bus 1
print(f"Firmware version: {pm_sensor.firmware_version()}")
Please give it a try and see whether it fixes the problem.
Leaving the argument blank got it working!
Here is the output of the initial checks:
Firmware version: 1.0
Product type: 00080000
Serial number: 11B4159G94F68YY5
Status register: CRC mismatched
Auto cleaning interval: 172800s
Set auto cleaning interval: 172800s
What do you make of the CRC mismatch message? Also wondering how easy it will be to update the firmware to v2.
Here is a print out of the measurements:
{
"sensor_data": {
"mass_density": {
"pm1.0": 12305.812,
"pm2.5": 12675.612,
"pm4.0": 12675.62,
"pm10": 12845.53
},
"particle_count": {
"pm0.5": 87593.781,
"pm1.0": 100500.352,
"pm2.5": 100772.867,
"pm4.0": 100778.344,
"pm10": 100783.086
},
"particle_size": 0.28,
"mass_density_unit": "ug/m3",
"particle_count_unit": "#/cm3",
"particle_size_unit": "um"
},
"timestamp": 1678884159
}
The values seem very high! This is in a very clean office environment.
Now getting this ...
'__mass_density_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__particle_count_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__particle_size_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__mass_density_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__particle_count_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__particle_size_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__mass_density_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__particle_count_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
'__particle_size_measurement' CRC mismatched! Data: [255, 255] Calculated CRC: 172 Expected: 255
and this:
Traceback (most recent call last):
File "/opt/piMonitor_env/airmonitor.py", line 112, in <module>
print(f"Firmware version: {pm_sensor.firmware_version()}")
File "/opt/piMonitor_env/sps30.py", line 74, in firmware_version
self.i2c.write(CMD_FIRMWARE_VERSION)
File "/opt/piMonitor_env/i2c/i2c.py", line 19, in write
self.fw.write(bytearray(data))
OSError: [Errno 121] Remote I/O error
Your sensor still functions well, but it seems there is data conversion or perhaps a wiring issue that may cause this problem. About the firmware version upgrade, I have never tried it, but if I recall it correctly, my firmware should be >1.0. I will compare it with my sensor, gather more info, and keep you posted once I get a possible fix.
I am going over the wiring today - to make sure its not flakey. However do you think the values are ok? They seem so high. And I confirmed from another source the firmware is not upgradable.
The values are not okay, but I still believe the sensor functions properly. I encountered a similar issue when I converted raw to actual values. I guess that data conversion may be the cause, though in my case, there was no CRC mismatch; a pure conversion issue. This time, however, was a slightly different scenario, so I have to check the other possibilities. Not sure if it is conflicting with the Adafruit library...
I think you are right it is a wiring issue. Let me redo everything and get back to you. Don't spend too much time on this. Many thanks for your help! Will report back shortly!
I got it to work. Now getting this:
mass_density: {'pm1.0': 0.0, 'pm2.5': 2.254, 'pm4.0': 2.254, 'pm10': 2.284}
particle_count: {'pm0.5': 15.577, 'pm1.0': 17.872, 'pm2.5': 17.92, 'pm4.0': 17.921, 'pm10': 17.922}
particle_size: 0.498
mass_density_unit: ug/m3
particle_count_unit: #/cm3
particle_size_unit: um
But still having CRC mismatch
Firmware version: 1.0
Product type: 00080000
Serial number: 11B4159FF94F68D5
Status register: CRC mismatched
Auto cleaning interval: 172800s
Set auto cleaning interval: 172800s
Glad to hear it works now. The result also seems correct if the sensor data reading does not return CRC mismatch. Regarding the status register, it is caused by the firmware version. I check the datasheet and confirm the status register reading requires minimum firmware version 2.2.
Please go to page 18 table 8 for details. SPS30 datasheet
You can still use the sensor for measurement, but you may want to ignore the status register reading for now. I may add the version-checking logic later to resolve the compatibility issue.
Hi there - sorry to come back to this. Just wanted to check if this will work with circuitpython ? I got it to work on a raspberrypi but now looking at some of the boards that support circuitpython.
Hi, I think it won't work because some built-in libraries/ modules used in this code are Python libraries. I'm not quite sure if MicroPython built-in libraries exist in CircuitPython. If they do, I have an example of I2C communication using machine library in MicroPython.
Next, you may have to rewrite the I2C-related codes in the MicroPython way.