adafruit / Adafruit_CircuitPython_MPL3115A2

CircuitPython module for the MPL3115A2 barometric pressure & temperature sensor.
MIT License
5 stars 8 forks source link

Incorrect pressure readings #24

Closed caternuson closed 1 year ago

caternuson commented 1 year ago

Re this thread: https://forums.adafruit.com/viewtopic.php?t=199326

Recreated with:

Running simpletest example from library:

pi@raspberrypi:~ $ python3 mpl3115a2_simpletest.py 
Pressure: 1002.505 pascals
Altitude: 165.253 meters
Temperature: 19.625 degrees Celsius
Pressure: 6.610 pascals
Altitude: 25063.445 meters
Temperature: 19.688 degrees Celsius
Pressure: 6.603 pascals
Altitude: 25065.507 meters
Temperature: 19.625 degrees Celsius
Pressure: 6.580 pascals
Altitude: 25066.445 meters
Temperature: 19.688 degrees Celsius
caternuson commented 1 year ago

Hmm....same thing is happening with CircuitPython on a QT Py:

Adafruit CircuitPython 7.3.3 on 2022-08-29; Adafruit QT Py RP2040 with rp2040
>>> 
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
Pressure: 1002.958 pascals
Altitude: 161.877 meters
Temperature: 19.938 degrees Celsius
Pressure: 6.465 pascals
Altitude: 25073.874 meters
Temperature: 19.938 degrees Celsius
Pressure: 6.472 pascals
Altitude: 25073.812 meters
Temperature: 20.000 degrees Celsius
Pressure: 6.475 pascals
Altitude: 25073.438 meters
Temperature: 20.000 degrees Celsius
caternuson commented 1 year ago

Seems like maybe the register writing isn't being handled properly between the various measurements.

Adafruit CircuitPython 7.3.3 on 2022-08-29; Adafruit QT Py RP2040 with rp2040
>>> import board, adafruit_mpl3115a2
>>> mpl = adafruit_mpl3115a2.MPL3115A2(board.I2C())
>>> print(mpl.pressure, mpl.altitude, mpl.temperature)
1001.29 99.0015 18.5625
>>> print(mpl.pressure, mpl.altitude, mpl.temperature)
3.96 25033.1 18.5625
>>> print(mpl.pressure, mpl.altitude, mpl.temperature)
3.9625 25032.7 18.5625
>>> print(mpl.pressure, mpl.altitude)
3.96 25032.2
>>> print(mpl.pressure, mpl.altitude)
3.955 25032.9
>>> print(mpl.pressure)
3.965
>>> print(mpl.pressure)
1001.3
>>> print(mpl.altitude)
25032.8
>>> print(mpl.altitude)
100.001
>>>  

The pressure and altitude values are coming from two different modes of the MPL3115A2, with the data being put in the same register locations.

caternuson commented 1 year ago

Just for the comparison, the Arduino library does not show this behavior:

Running library example:

Adafruit_MPL3115A2 test!
-----------------
pressure = 990.18 hPa
altitude = 192.81 m
temperature = 22.62 C
-----------------
pressure = 990.22 hPa
altitude = 192.56 m
temperature = 22.62 C
-----------------
pressure = 990.28 hPa
altitude = 192.62 m
temperature = 22.69 C
-----------------
pressure = 990.21 hPa
altitude = 192.50 m
temperature = 22.69 C
-----------------
pressure = 990.27 hPa
altitude = 192.50 m
temperature = 22.69 C
-----------------
pressure = 990.27 hPa
altitude = 192.37 m
temperature = 22.69 C
jposada202020 commented 1 year ago

@caternuson I guess we wake up with the same thing in mind, just fyi, the following change in this line same to fix the problem

self._ctrl_reg1 &= ~0b10000000 

https://github.com/adafruit/Adafruit_CircuitPython_MPL3115A2/blob/b32af7d72e016762632f656a891e847058ae41ae/adafruit_mpl3115a2.py#L231

Tested

Adafruit CircuitPython 8.0.2 on 2023-02-14; Adafruit Feather RP2040 with rp2040
>>> import board, adafruit_mpl3115a2
>>> mpl = adafruit_mpl3115a2.MPL3115A2(board.I2C())
>>> print(mpl.pressure, mpl.altitude, mpl.temperature)
1003.26 25085.6 19.8125
>>> print(mpl.pressure, mpl.altitude, mpl.temperature)
1003.4 25081.1 19.8125
>>> print(mpl.altitude)
25085.1
>>> print(mpl.altitude)
25082.9
>>> print(mpl.pressure)
1003.32
>>> print(mpl.pressure)
1003.33
>>> print(mpl.temperature)
19.6875
>>> print(mpl.pressure)
1003.36
>>> 

That is why, the measure returns to normal when we ask for the pressure, it would tun off the barometric mode. or on the altimeter mode, is the same at the end image

You could see the behaviour using the following code, before and after the change. Did not read in deep the datasheet, so I am not sure if we need the barometric mode.


import board, adafruit_mpl3115a2
mpl = adafruit_mpl3115a2.MPL3115A2(board.I2C())

print("_ctrl_reg1 :", bin(mpl._ctrl_reg1))
print(mpl.pressure, mpl.altitude, mpl.temperature)
print("_ctrl_reg1 :", bin(mpl._ctrl_reg1))
print(mpl.pressure, mpl.altitude, mpl.temperature)
caternuson commented 1 year ago

I think that's just keeping it in barometric mode all the time. Pressure will be OK, but the altitude readings will never be correct. Note the values you are seeing:

>>> print(mpl.altitude)
25085.1
>>> print(mpl.altitude)
25082.9

These should be much lower - closer to sea level (0).

jposada202020 commented 1 year ago

Got it, so maybe changing between modes when measuring altitude and pressure

caternuson commented 1 year ago

Changing modes for pressure and altitude is what the library is trying to do. But not fully working for some reason.

I think a general library re-write will help. The way the current library is manually bit manip'ing the _ctrl_reg1 data member is a bit klunky. For example, the OST bit never gets de-asserted. So after the first call to:

        self._ctrl_reg1 |= 0b00000010  # Set OST to 1 to start measurement.

the OST bit is always set and every write out to CTRL_REG1 will attempt to initiate a one-shot.

jposada202020 commented 1 year ago

Yes Agreed :)

caternuson commented 1 year ago

This could be playing into things as well: image

jposada202020 commented 1 year ago

Guessing that is library is using at the start of the measurements https://github.com/adafruit/Adafruit_CircuitPython_MPL3115A2/blob/b32af7d72e016762632f656a891e847058ae41ae/adafruit_mpl3115a2.py#L192

jposada202020 commented 1 year ago

well. very interesting, so included my "modified" version of the library, a lot of "fuzzy logic" around it, https://gist.github.com/jposada202020/a9f5967c430a4e6e2f85b0ec6eb46a4d

The "write" in the temperature covers the change in the Pressure, so now we get the correct value every time.

Needed to put the hole sensor initialization code in the Altitude property, but even with that, it does not like to get inquired alone, needs to be pressure, the altitude to give the correct value. guess is because they share the same date register.

Everything is good and well until you read the altitude, then nothing works again. Maybe a library rewrite is needed, or maybe there is something very obvious, but at this moment I could not see it :(.

just for the fun tested with this script

import board, adafruit_mpl3115a2
mpl = adafruit_mpl3115a2.MPL3115A2(board.I2C())

print(mpl.pressure, mpl.altitude, mpl.temperature)
print(mpl.pressure, mpl.temperature)
print(mpl.pressure)
print(mpl.temperature)
print(mpl.pressure, mpl.temperature)
print(mpl.altitude)
print(mpl.temperature)
print(mpl.pressure)
print(mpl.altitude)
print(mpl.temperature)
print(mpl.pressure, mpl.altitude, mpl.temperature)
print(mpl.pressure, mpl.altitude, mpl.temperature)
print(mpl.pressure, mpl.altitude, mpl.temperature)
print(mpl.pressure, mpl.altitude, mpl.temperature)