From 2b9a219fa085869709d5ac4b05f56ef6005a0253 Mon Sep 17 00:00:00 2001 From: Jeff Raber Date: Tue, 12 Mar 2019 08:11:27 -0500 Subject: [PATCH 1/5] Implement SPI interface Mostly copied from the BME280 python library. --- adafruit_bme680.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/adafruit_bme680.py b/adafruit_bme680.py index d69a786..bc9ae65 100644 --- a/adafruit_bme680.py +++ b/adafruit_bme680.py @@ -349,3 +349,28 @@ def _write(self, register, values): i2c.write(buffer) if self._debug: print("\t$%02X <= %s" % (values[0], [hex(i) for i in values[1:]])) + +class Adafruit_BME680_SPI(Adafruit_BME680): + """Driver for BME680 connected over SPI. Default clock rate is 100000 but can be changed with + 'baudrate'""" + def __init__(self, spi, cs, baudrate=100000): + from adafruit_bus_device import spi_device + self._spi = spi_device.SPIDevice(spi, cs, baudrate=baudrate) + super().__init__() + + def _read(self, register, length): + register = (register | 0x80) & 0xFF # Read single, bit 7 high. + with self._spi as spi: + spi.write(bytearray([register])) #pylint: disable=no-member + result = bytearray(length) + spi.readinto(result) #pylint: disable=no-member + return result + + def _write(self, register, values): + register &= 0x7F # Write, bit 7 low. + with self._spi as spi: + buffer = bytearray(2 * len(values)) + for i, value in enumerate(values): + buffer[2 * i] = register + i + buffer[2 * i + 1] = value & 0xFF + spi.write(buffer) #pylint: disable=no-member From 0dad9a2a6cbaf869b7613b7fe8b4537a8a49681b Mon Sep 17 00:00:00 2001 From: Jeff Raber Date: Tue, 12 Mar 2019 08:12:39 -0500 Subject: [PATCH 2/5] Fix-up i2c_device import to make pylint happy --- adafruit_bme680.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_bme680.py b/adafruit_bme680.py index bc9ae65..463b073 100644 --- a/adafruit_bme680.py +++ b/adafruit_bme680.py @@ -324,7 +324,7 @@ class Adafruit_BME680_I2C(Adafruit_BME680): will be from the previous reading.""" def __init__(self, i2c, address=0x77, debug=False, *, refresh_rate=10): """Initialize the I2C device at the 'address' given""" - import adafruit_bus_device.i2c_device as i2c_device + from adafruit_bus_device import i2c_device self._i2c = i2c_device.I2CDevice(i2c, address) self._debug = debug super().__init__(refresh_rate=refresh_rate) From e71564208f77607ef2164f9f4aa97e6f1aad9523 Mon Sep 17 00:00:00 2001 From: Jeff Raber Date: Tue, 12 Mar 2019 22:35:28 -0500 Subject: [PATCH 3/5] Improve SPI class, mirror the i2c class init and debug Added the debug init parameter and copied the debug functionality from the i2c class Added the refresh_rate initi parameter Improved the SPI class docstring --- adafruit_bme680.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/adafruit_bme680.py b/adafruit_bme680.py index 463b073..2e2bae7 100644 --- a/adafruit_bme680.py +++ b/adafruit_bme680.py @@ -351,12 +351,21 @@ def _write(self, register, values): print("\t$%02X <= %s" % (values[0], [hex(i) for i in values[1:]])) class Adafruit_BME680_SPI(Adafruit_BME680): - """Driver for BME680 connected over SPI. Default clock rate is 100000 but can be changed with - 'baudrate'""" - def __init__(self, spi, cs, baudrate=100000): + """Driver for SPI connected BME680. + + :param busio.SPI spi: SPI device + :param digitalio.DigitalInOut cs: Chip Select + :param bool debug: Print debug statements when True. + :param int baudrate: Clock rate, default is 100000 + :param int refresh_rate: Maximum number of readings per second. Faster property reads + will be from the previous reading. + """ + + def __init__(self, spi, cs, baudrate=100000, debug=False, *, refresh_rate=10): from adafruit_bus_device import spi_device self._spi = spi_device.SPIDevice(spi, cs, baudrate=baudrate) - super().__init__() + self._debug = debug + super().__init__(refresh_rate=refresh_rate) def _read(self, register, length): register = (register | 0x80) & 0xFF # Read single, bit 7 high. @@ -364,6 +373,8 @@ def _read(self, register, length): spi.write(bytearray([register])) #pylint: disable=no-member result = bytearray(length) spi.readinto(result) #pylint: disable=no-member + if self._debug: + print("\t$%02X => %s" % (register, [hex(i) for i in result])) return result def _write(self, register, values): @@ -374,3 +385,5 @@ def _write(self, register, values): buffer[2 * i] = register + i buffer[2 * i + 1] = value & 0xFF spi.write(buffer) #pylint: disable=no-member + if self._debug: + print("\t$%02X <= %s" % (values[0], [hex(i) for i in values[1:]])) From aa97a7a5a62090a9db954ef28d7bb3a537f13e88 Mon Sep 17 00:00:00 2001 From: Jeff Raber Date: Wed, 13 Mar 2019 01:52:39 -0500 Subject: [PATCH 4/5] Change SPI memory page as needed when reading/writing through SPI In SPI mode, we must change the memory page depending on which register is being read/written. Renamed const _BME680_REG_STATUS to _BME680_REG_MEAS_STATUS to more closely match the name in the datasheet. --- adafruit_bme680.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/adafruit_bme680.py b/adafruit_bme680.py index 2e2bae7..f504d35 100644 --- a/adafruit_bme680.py +++ b/adafruit_bme680.py @@ -52,11 +52,11 @@ _BME680_REG_SOFTRESET = const(0xE0) _BME680_REG_CTRL_GAS = const(0x71) _BME680_REG_CTRL_HUM = const(0x72) -_BME280_REG_STATUS = const(0xF3) +_BME680_REG_STATUS = const(0x73) _BME680_REG_CTRL_MEAS = const(0x74) _BME680_REG_CONFIG = const(0x75) -_BME680_REG_STATUS = const(0x1D) +_BME680_REG_MEAS_STATUS = const(0x1D) _BME680_REG_PDATA = const(0x1F) _BME680_REG_TDATA = const(0x22) _BME680_REG_HDATA = const(0x25) @@ -266,7 +266,7 @@ def _perform_reading(self): self._write(_BME680_REG_CTRL_MEAS, [ctrl]) new_data = False while not new_data: - data = self._read(_BME680_REG_STATUS, 15) + data = self._read(_BME680_REG_MEAS_STATUS, 15) new_data = data[0] & 0x80 != 0 time.sleep(0.005) self._last_reading = time.monotonic() @@ -368,6 +368,11 @@ def __init__(self, spi, cs, baudrate=100000, debug=False, *, refresh_rate=10): super().__init__(refresh_rate=refresh_rate) def _read(self, register, length): + if register != _BME680_REG_STATUS: + #_BME680_REG_STATUS exists in both SPI memory pages + #For all other registers, we must set the correct memory page + self._set_spi_mem_page(register) + register = (register | 0x80) & 0xFF # Read single, bit 7 high. with self._spi as spi: spi.write(bytearray([register])) #pylint: disable=no-member @@ -378,6 +383,10 @@ def _read(self, register, length): return result def _write(self, register, values): + if register != _BME680_REG_STATUS: + #_BME680_REG_STATUS exists in both SPI memory pages + #For all other registers, we must set the correct memory page + self._set_spi_mem_page(register) register &= 0x7F # Write, bit 7 low. with self._spi as spi: buffer = bytearray(2 * len(values)) @@ -387,3 +396,9 @@ def _write(self, register, values): spi.write(buffer) #pylint: disable=no-member if self._debug: print("\t$%02X <= %s" % (values[0], [hex(i) for i in values[1:]])) + + def _set_spi_mem_page(self, register): + spi_mem_page = 0x00 + if register < 0x80: + spi_mem_page = 0x10 + self._write(_BME680_REG_STATUS, spi_mem_page) From 0d25996200bd774389848310ff88cf31eb4d60d7 Mon Sep 17 00:00:00 2001 From: Jeff Raber Date: Wed, 13 Mar 2019 20:59:49 -0500 Subject: [PATCH 5/5] values parameter for _write() must be a list --- adafruit_bme680.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_bme680.py b/adafruit_bme680.py index f504d35..6541c4d 100644 --- a/adafruit_bme680.py +++ b/adafruit_bme680.py @@ -401,4 +401,4 @@ def _set_spi_mem_page(self, register): spi_mem_page = 0x00 if register < 0x80: spi_mem_page = 0x10 - self._write(_BME680_REG_STATUS, spi_mem_page) + self._write(_BME680_REG_STATUS, [spi_mem_page])