pimoroni / scd4x-python

MIT License
9 stars 2 forks source link

How to set ambient pressure #2

Closed leonahess closed 2 years ago

leonahess commented 2 years ago

I am trying to set the ambient pressure via the set_ambient_pressure method. From the datasheet I took that the value needs to be in hectopascal if I am not mistaken. So I am trying the following:

from scd4x import SCD4X

pres = pressure_data_from_some_sensor_in_hectopascal

scd41 = SCD4X(quiet=False)
scd41.start_periodic_measurement()

scd41.set_ambient_pressure(pres)

But it doesn't seem to be working. I have tried giving it an int and a float but both throw errors:

pres is an int:

Traceback (most recent call last):
   File "/home/pi/homelab/smarthome/breakout_garden/src/breakout.py", line 170, in <module>
     process_request()
   File "<decorator-gen-1>", line 2, in process_request
   File "/home/pi/.local/lib/python3.7/site-packages/prometheus_client/context_managers.py", line 66, in wrapped
     return func(*args, **kwargs)
   File "/home/pi/homelab/smarthome/breakout_garden/src/breakout.py", line 159, in process_request
     scd41.set_ambient_pressure(int(pres))
   File "/home/pi/.local/lib/python3.7/site-packages/scd4x/__init__.py", line 132, in set_ambient_pressure
     self.rdwr(SET_PRESSURE, value=ambient_pressure)
   File "/home/pi/.local/lib/python3.7/site-packages/scd4x/__init__.py", line 52, in rdwr
     msg_w = i2c_msg.write(self.address, struct.pack(">HHb", command, value, self.crc8(value)))
 struct.error: byte format requires -128 <= number <= 127

pres is a float:

Traceback (most recent call last):
   File "/home/pi/homelab/smarthome/breakout_garden/src/breakout.py", line 170, in <module>
     process_request()
   File "<decorator-gen-1>", line 2, in process_request
   File "/home/pi/.local/lib/python3.7/site-packages/prometheus_client/context_managers.py", line 66, in wrapped
     return func(*args, **kwargs)
   File "/home/pi/homelab/smarthome/breakout_garden/src/breakout.py", line 159, in process_request
     scd41.set_ambient_pressure(float(pres))
  File "/home/pi/.local/lib/python3.7/site-packages/scd4x/__init__.py", line 132, in set_ambient_pressure
     self.rdwr(SET_PRESSURE, value=ambient_pressure)
   File "/home/pi/.local/lib/python3.7/site-packages/scd4x/__init__.py", line 52, in rdwr
     msg_w = i2c_msg.write(self.address, struct.pack(">HHb", command, value, self.crc8(value)))
   File "/home/pi/.local/lib/python3.7/site-packages/scd4x/__init__.py", line 157, in crc8
     for byte in data:
 TypeError: 'float' object is not iterable

In what form does the pressure value have to be provided to the set_ambient_pressure method?

Marcello-Venlo commented 2 years ago

This is an error in the Pimoroni library and occurs with several functions for sending settings to the SCD4X, like setting the pressure or altitude. If you change the format of the struct from ">HHb" to ">HHB" the command works. The original format string interprets the checksum as a signed byte instead of an unsinged byte.

     msg_w = i2c_msg.write(self.address, struct.pack(">HHb", command, value, self.crc8(value)))

So simply edit line 52 of the file: /home/pi/.local/lib/python3.7/site-packages/scd4x/scd4x/__init__.py

(note that the .local folder is hidden)

Marcello-Venlo commented 2 years ago

O, and another important thing:

The SCD4X has to be idle for changing settings, so don't start the measurement BEFORE changing the settings. You can find that in the Sensiron datasheet (link)

If you change your code (and the init.py in the library, as I mentioned earlier) it should work fine. So:

# from scd4x import SCD4X import time

pres = pressure_data_from_some_sensor_in_hectopascal

scd41 = SCD4X(quiet=False)

scd41.set_ambient_pressure(pres)

time.sleep(3)

scd41.start_periodic_measurement()

leonahess commented 2 years ago

Thanks for the solution.

But if I read the data sheet correctly the set_ambient_pressure can actually be sent during periodic measurements.

From the data sheet:

3.6.5 set_ambient_pressure
Description: The set_ambient_pressure command can be sent during periodic measurements to enable continuous pressure
compensation.

But the other functions like set_sensor_altitude must be set while the sensor is idle as you have described.

Marcello-Venlo commented 2 years ago

But if I read the data sheet correctly the set_ambient_pressure can actually be sent during periodic measurements.

Yes, you are right about that, I see now. Strange, it is one of the few things allowed during execution. I did not check the data sheet when I reacted yesterday. I found your issue and I ran into the same problem while trying to set the altitude earlier, but I had a workaround for that. So it had no priority for me 😉.