@@ -87,36 +87,43 @@ def _read24(arr):
87
87
88
88
89
89
class Adafruit_BME680 :
90
- """Driver from BME680 air quality sensor"""
91
- def __init__ (self ):
90
+ """Driver from BME680 air quality sensor
91
+
92
+ :param int refresh_rate: Maximum number of readings per second. Faster property reads
93
+ will be from the previous reading."""
94
+ def __init__ (self , * , refresh_rate = 10 ):
92
95
"""Check the BME680 was found, read the coefficients and enable the sensor for continuous
93
- reads"""
96
+ reads. """
94
97
self ._write (_BME680_REG_SOFTRESET , [0xB6 ])
95
- time .sleep (0.5 )
98
+ time .sleep (0.005 )
96
99
97
100
# Check device ID.
98
101
chip_id = self ._read_byte (_BME680_REG_CHIPID )
99
- if _BME680_CHIPID != chip_id :
100
- raise RuntimeError ('Failed to find BME680! Chip ID 0x%x' % id )
102
+ if chip_id != _BME680_CHIPID :
103
+ raise RuntimeError ('Failed to find BME680! Chip ID 0x%x' % chip_id )
101
104
102
105
self ._read_calibration ()
103
106
104
107
# set up heater
105
108
self ._write (_BME680_BME680_RES_WAIT_0 , [0x73 , 0x64 , 0x65 ])
106
109
self .sea_level_pressure = 1013.25
107
110
"""Pressure in hectoPascals at sea level. Used to calibrate ``altitude``."""
108
- self ._pressure_oversample = 4
109
- self ._temp_oversample = 8
110
- self ._humidity_oversample = 2
111
- self ._filter = 3
111
+
112
+ # Default oversampling and filter register values.
113
+ self ._pressure_oversample = 0b011
114
+ self ._temp_oversample = 0b100
115
+ self ._humidity_oversample = 0b010
116
+ self ._filter = 0b010
112
117
113
118
self ._adc_pres = None
114
119
self ._adc_temp = None
115
120
self ._adc_hum = None
116
121
self ._adc_gas = None
117
122
self ._gas_range = None
118
123
self ._t_fine = None
119
- self ._status = 0
124
+
125
+ self ._last_reading = 0
126
+ self ._min_refresh_time = 1 / refresh_rate
120
127
121
128
@property
122
129
def pressure_oversample (self ):
@@ -241,6 +248,8 @@ def gas(self):
241
248
def _perform_reading (self ):
242
249
"""Perform a single-shot reading from the sensor and fill internal data structure for
243
250
calculations"""
251
+ if time .monotonic () - self ._last_reading < self ._min_refresh_time :
252
+ return
244
253
245
254
# set filter
246
255
self ._write (_BME680_REG_CONFIG , [self ._filter << 2 ])
@@ -252,25 +261,21 @@ def _perform_reading(self):
252
261
# gas measurements enabled
253
262
self ._write (_BME680_REG_CTRL_GAS , [_BME680_RUNGAS ])
254
263
255
- ctrl = self ._read (_BME680_REG_CTRL_MEAS , 1 )[ 0 ]
264
+ ctrl = self ._read_byte (_BME680_REG_CTRL_MEAS )
256
265
ctrl = (ctrl & 0xFC ) | 0x01 # enable single shot!
257
266
self ._write (_BME680_REG_CTRL_MEAS , [ctrl ])
258
- time .sleep (0.5 )
259
- data = self ._read (_BME680_REG_STATUS , 15 )
260
- self ._status = data [0 ] & 0x80
261
- #gas_idx = data[0] & 0x0F
262
- #meas_idx = data[1]
263
- #print("status 0x%x gas_idx %d meas_idx %d" % (self._status, gas_idx, meas_idx))
264
-
265
- #print([hex(i) for i in data])
267
+ new_data = False
268
+ while not new_data :
269
+ data = self ._read (_BME680_REG_STATUS , 15 )
270
+ new_data = data [0 ] & 0x80 != 0
271
+ time .sleep (0.005 )
272
+ self ._last_reading = time .monotonic ()
273
+
266
274
self ._adc_pres = _read24 (data [2 :5 ]) / 16
267
275
self ._adc_temp = _read24 (data [5 :8 ]) / 16
268
276
self ._adc_hum = struct .unpack ('>H' , bytes (data [8 :10 ]))[0 ]
269
277
self ._adc_gas = int (struct .unpack ('>H' , bytes (data [13 :15 ]))[0 ] / 64 )
270
278
self ._gas_range = data [14 ] & 0x0F
271
- #print(self._adc_hum)
272
- #print(self._adc_gas)
273
- self ._status |= data [14 ] & 0x30 # VALID + STABILITY mask
274
279
275
280
var1 = (self ._adc_temp / 8 ) - (self ._temp_calibration [0 ] * 2 )
276
281
var2 = (var1 * self ._temp_calibration [1 ]) / 2048
@@ -296,9 +301,9 @@ def _read_calibration(self):
296
301
self ._humidity_calibration [1 ] += self ._humidity_calibration [0 ] % 16
297
302
self ._humidity_calibration [0 ] /= 16
298
303
299
- self ._heat_range = (self ._read (0x02 , 1 )[ 0 ] & 0x30 ) / 16
300
- self ._heat_val = self ._read (0x00 , 1 )[ 0 ]
301
- self ._sw_err = (self ._read (0x04 , 1 )[ 0 ] & 0xF0 ) / 16
304
+ self ._heat_range = (self ._read_byte (0x02 ) & 0x30 ) / 16
305
+ self ._heat_val = self ._read_byte (0x00 )
306
+ self ._sw_err = (self ._read_byte (0x04 ) & 0xF0 ) / 16
302
307
303
308
def _read_byte (self , register ):
304
309
"""Read a byte register value and return it"""
@@ -311,13 +316,18 @@ def _write(self, register, values):
311
316
raise NotImplementedError ()
312
317
313
318
class Adafruit_BME680_I2C (Adafruit_BME680 ):
314
- """Driver for I2C connected BME680."""
315
- def __init__ (self , i2c , address = 0x77 , debug = False ):
319
+ """Driver for I2C connected BME680.
320
+
321
+ :param int address: I2C device address
322
+ :param bool debug: Print debug statements when True.
323
+ :param int refresh_rate: Maximum number of readings per second. Faster property reads
324
+ will be from the previous reading."""
325
+ def __init__ (self , i2c , address = 0x77 , debug = False , * , refresh_rate = 10 ):
316
326
"""Initialize the I2C device at the 'address' given"""
317
327
import adafruit_bus_device .i2c_device as i2c_device
318
328
self ._i2c = i2c_device .I2CDevice (i2c , address )
319
329
self ._debug = debug
320
- super ().__init__ ()
330
+ super ().__init__ (refresh_rate = refresh_rate )
321
331
322
332
def _read (self , register , length ):
323
333
"""Returns an array of 'length' bytes from the 'register'"""
@@ -332,7 +342,10 @@ def _read(self, register, length):
332
342
def _write (self , register , values ):
333
343
"""Writes an array of 'length' bytes to the 'register'"""
334
344
with self ._i2c as i2c :
335
- values = [(v & 0xFF ) for v in [register ]+ values ]
336
- i2c .write (bytes (values ))
345
+ buffer = bytearray (2 * len (values ))
346
+ for i in range (len (values )):
347
+ buffer [2 * i ] = register + i
348
+ buffer [2 * i + 1 ] = values [i ]
349
+ i2c .write (buffer )
337
350
if self ._debug :
338
351
print ("\t $%02X <= %s" % (values [0 ], [hex (i ) for i in values [1 :]]))
0 commit comments