diff --git a/README.rst b/README.rst index b3c46b6..f9fb794 100644 --- a/README.rst +++ b/README.rst @@ -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 ============ diff --git a/adafruit_dps310.py b/adafruit_dps310.py index 6dd6a19..222506f 100644 --- a/adafruit_dps310.py +++ b/adafruit_dps310.py @@ -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) @@ -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 @@ -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): @@ -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""" diff --git a/examples/dps310_low_power_weather_station.py b/examples/dps310_low_power_weather_station.py new file mode 100644 index 0000000..41ca3b3 --- /dev/null +++ b/examples/dps310_low_power_weather_station.py @@ -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)