/ adafruit_mprls.py
adafruit_mprls.py
  1  # The MIT License (MIT)
  2  #
  3  # Copyright (c) 2018 ladyada for Adafruit Industries
  4  #
  5  # Permission is hereby granted, free of charge, to any person obtaining a copy
  6  # of this software and associated documentation files (the "Software"), to deal
  7  # in the Software without restriction, including without limitation the rights
  8  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9  # copies of the Software, and to permit persons to whom the Software is
 10  # furnished to do so, subject to the following conditions:
 11  #
 12  # The above copyright notice and this permission notice shall be included in
 13  # all copies or substantial portions of the Software.
 14  #
 15  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 21  # THE SOFTWARE.
 22  """
 23  `adafruit_mprls`
 24  ====================================================
 25  
 26  CircuitPython library to support Honeywell MPRLS digital pressure sensors
 27  
 28  * Author(s): ladyada
 29  
 30  Implementation Notes
 31  --------------------
 32  
 33  **Hardware:**
 34  
 35  **Software and Dependencies:**
 36  
 37  * Adafruit CircuitPython firmware for the supported boards:
 38    https://github.com/adafruit/circuitpython/releases
 39  
 40  * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
 41  
 42  """
 43  
 44  # imports
 45  
 46  __version__ = "0.0.0-auto.0"
 47  __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MPRLS.git"
 48  
 49  
 50  import time
 51  from adafruit_bus_device.i2c_device import I2CDevice
 52  from digitalio import Direction
 53  from micropython import const
 54  
 55  # pylint: disable=bad-whitespace
 56  _MPRLS_DEFAULT_ADDR = const(0x18)
 57  # pylint: enable=bad-whitespace
 58  
 59  
 60  class MPRLS:
 61      """
 62      Driver base for the MPRLS pressure sensor
 63      :param i2c_bus: The `busio.I2C` object to use. This is the only required parameter.
 64      :param int addr: The optional I2C address, defaults to 0x18
 65      :param microcontroller.Pin reset_pin: Optional digitalio pin for hardware resetting
 66      :param microcontroller.Pin eoc_pin: Optional digitalio pin for getting End Of Conversion signal
 67      :param float psi_min: The minimum pressure in PSI, defaults to 0
 68      :param float psi_max: The maximum pressure in PSI, defaults to 25
 69      """
 70  
 71      def __init__(
 72          self,
 73          i2c_bus,
 74          *,
 75          addr=_MPRLS_DEFAULT_ADDR,
 76          reset_pin=None,
 77          eoc_pin=None,
 78          psi_min=0,
 79          psi_max=25
 80      ):
 81          # Init I2C
 82          self._i2c = I2CDevice(i2c_bus, addr)
 83          self._buffer = bytearray(4)
 84  
 85          # Optional hardware reset pin
 86          if reset_pin is not None:
 87              reset_pin.direction = Direction.OUTPUT
 88              reset_pin.value = True
 89              reset_pin.value = False
 90              time.sleep(0.01)
 91              reset_pin.value = True
 92          time.sleep(0.005)  # Start up timing
 93  
 94          # Optional end-of-conversion pin
 95          self._eoc = eoc_pin
 96          if eoc_pin is not None:
 97              self._eoc.direction = Direction.INPUT
 98  
 99          if psi_min >= psi_max:
100              raise ValueError("Min PSI must be < max!")
101          self._psimax = psi_max
102          self._psimin = psi_min
103          # That's pretty much it, there's no ID register :(
104  
105      @property
106      def pressure(self):
107          """The measured pressure, in hPa"""
108          return self._read_data()
109  
110      def _read_data(self):
111          """Read the status & 24-bit data reading"""
112          self._buffer[0] = 0xAA
113          self._buffer[1] = 0
114          self._buffer[2] = 0
115          with self._i2c as i2c:
116              # send command
117              i2c.write(self._buffer, end=3)
118              # ready busy flag/status
119              while True:
120                  # check End of Convert pin first, if we can
121                  if self._eoc is not None:
122                      if self._eoc.value:
123                          break
124                  # or you can read the status byte
125                  i2c.readinto(self._buffer, end=1)
126                  if not self._buffer[0] & 0x20:
127                      break
128              # no longer busy!
129              i2c.readinto(self._buffer, end=4)
130  
131          # check other status bits
132          if self._buffer[0] & 0x01:
133              raise RuntimeError("Internal math saturation")
134          if self._buffer[0] & 0x04:
135              raise RuntimeError("Integrity failure")
136  
137          # All is good, calculate the PSI and convert to hPA
138          raw_psi = (self._buffer[1] << 16) | (self._buffer[2] << 8) | self._buffer[3]
139          # use the 10-90 calibration curve
140          psi = (raw_psi - 0x19999A) * (self._psimax - self._psimin)
141          psi /= 0xE66666 - 0x19999A
142          psi += self._psimin
143          # convert PSI to hPA
144          return psi * 68.947572932