Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

correct temperature readings for defective ICs + misc. improvements #6

Merged
merged 13 commits into from May 13, 2020
Merged
10 changes: 10 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ Usage Example
print("")
time.sleep(1.0)

Caveat: by default the library initializes the IC with constant temperature and pressure measurements at 64Hz with 64 samples. It is not possible to change the IC's mode, temperature_oversample_count or pressure_oversample_count on-the-fly so resetting the IC and operation parameteres is required. For instance, to set the mode to continuous pressure measurement at 1Hz with 2 samples:

.. code-block:: python3

dps310.reset()
dps310.pressure_oversample_count = adafruit_dps310.SampleCount.COUNT_2
dps310.pressure_rate = adafruit_dps310.Rate.RATE_1_HZ
dps310.mode = adafruit_dps310.Mode.CONT_PRESSURE
dps310.wait_pressure_ready()


Contributing
============
Expand Down
82 changes: 70 additions & 12 deletions adafruit_dps310.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ class DPS310:

_calib_coeff_temp_src_bit = ROBit(_DPS310_TMPCOEFSRCE, 7)

_reg0e = RWBits(8, 0x0E, 0)
_reg0f = RWBits(8, 0x0F, 0)
_reg62 = RWBits(8, 0x62, 0)

def __init__(self, i2c_bus, address=_DPS310_DEFAULT_ADDRESS):
self.i2c_device = i2c_device.I2CDevice(i2c_bus, address)

Expand Down Expand Up @@ -234,13 +238,9 @@ def __init__(self, i2c_bus, address=_DPS310_DEFAULT_ADDRESS):
self.initialize()

def initialize(self):
"""Reset the sensor to the default state"""

self._reset()
self._read_calibration()
"""Initialize the sensor to continuous measurement"""

# make sure we're using the temperature source used for calibration
self._temp_measurement_src_bit = self._calib_coeff_temp_src_bit
self.reset()

self.pressure_rate = Rate.RATE_64_HZ
self.pressure_oversample_count = SampleCount.COUNT_64
Expand All @@ -249,17 +249,35 @@ def initialize(self):
self.mode = Mode.CONT_PRESTEMP

# wait until we have at least one good measurement

while (self._temp_ready is False) or (self._pressure_ready is False):
sleep(0.001)

def _reset(self):
"""Perform a soft-reset on the sensor"""
self.wait_temperature_ready()
self.wait_pressure_ready()

# (https://github.com/Infineon/DPS310-Pressure-Sensor#temperature-measurement-issue)
# similar to DpsClass::correctTemp(void) from infineon's c++ library
def _correct_temp(self):
"""Correct temperature readings on ICs with a fuse bit problem"""
self._reg0e = 0xA5
self._reg0f = 0x96
self._reg62 = 0x02
self._reg0e = 0
self._reg0f = 0

# perform a temperature measurement
# the most recent temperature will be saved internally
# and used for compensation when calculating pressure
_unused = self._raw_temperature

def reset(self):
"""Reset the sensor"""
self._reset_register = 0x89
# wait for hardware reset to finish
sleep(0.010)
while not self._sensor_ready:
sleep(0.001)
self._correct_temp()
self._read_calibration()
# make sure we're using the temperature source used for calibration
self._temp_measurement_src_bit = self._calib_coeff_temp_src_bit

@property
def pressure(self):
Expand Down Expand Up @@ -296,11 +314,51 @@ def temperature_ready(self):
"""Returns true if there is a temperature reading ready"""
return self._temp_ready

def wait_temperature_ready(self):
"""Wait until a temperature measurement is available.

To avoid waiting indefinitely this function raises an
error if the sensor isn't configured for temperate measurements,
ie. ``Mode.ONE_TEMPERATURE``, ``Mode.CONT_TEMP`` or ``Mode.CONT_PRESTEMP``.
See the `Mode` documentation for details.
"""
if (
self._mode_bits == Mode.IDLE
or self._mode_bits == Mode.ONE_PRESSURE
or self._mode_bits == Mode.CONT_PRESSURE
):
raise RuntimeError(
"Sensor mode is set to idle or pressure measurement,\
can't wait for a temperature measurement"
)
while self._temp_ready is False:
sleep(0.001)

@property
def pressure_ready(self):
"""Returns true if pressure readings are ready"""
return self._pressure_ready

def wait_pressure_ready(self):
"""Wait until a pressure measurement is available

To avoid waiting indefinitely this function raises an
error if the sensor isn't configured for pressure measurements,
ie. ``Mode.ONE_PRESSURE``, ``Mode.CONT_PRESSURE`` or ``Mode.CONT_PRESTEMP``
See the `Mode` documentation for details.
"""
if (
self._mode_bits == Mode.IDLE
or self._mode_bits == Mode.ONE_TEMPERATURE
or self._mode_bits == Mode.CONT_TEMP
):
raise RuntimeError(
"Sensor mode is set to idle or temperature measurement,\
can't wait for a pressure measurement"
)
while self._pressure_ready is False:
sleep(0.001)

@property
def mode(self):
"""The measurement mode. Must be a `Mode`. See the `Mode` documentation for details"""
Expand Down
34 changes: 34 additions & 0 deletions examples/dps310_low_power_weather_station.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
Configure the sensor for continuous measurement with rates,
sampling counts and mode optmized for low power, as recommended
in Infineon's datasheet:
https://www.infineon.com/dgdl/Infineon-DPS310-DS-v01_00-EN.pdf
"""

# (disable pylint warnings for adafruit_dps310.{SampleCount,Rate,Mode}.*
# as they are generated dynamically)
# pylint: disable=no-member

import time
import board
import busio
import adafruit_dps310

i2c = busio.I2C(board.SCL, board.SDA)

dps310 = adafruit_dps310.DPS310(i2c)

dps310.reset()
dps310.pressure_oversample_count = adafruit_dps310.SampleCount.COUNT_2
dps310.pressure_rate = adafruit_dps310.Rate.RATE_1_HZ
dps310.temperature_oversample_count = adafruit_dps310.SampleCount.COUNT_16
dps310.temperature_rate = adafruit_dps310.Rate.RATE_1_HZ
dps310.mode = adafruit_dps310.Mode.CONT_PRESTEMP
dps310.wait_temperature_ready()
dps310.wait_pressure_ready()

while True:
print("Temperature = %.2f *C" % dps310.temperature)
print("Pressure = %.2f hPa" % dps310.pressure)
print("")
time.sleep(10.0)