Skip to content

Commit 67b1714

Browse files
committed
its slow...but it works! you *must* mpy this as its massive
1 parent 33d2992 commit 67b1714

File tree

1 file changed

+117
-50
lines changed

1 file changed

+117
-50
lines changed

adafruit_bme680.py

Lines changed: 117 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@
2727
_BME680_REG_TDATA = const(0x22)
2828
_BME680_REG_HDATA = const(0x25)
2929

30-
_BME280_PRESSURE_MIN_HPA = const(300)
31-
_BME280_PRESSURE_MAX_HPA = const(1100)
32-
_BME280_HUMIDITY_MIN = const(0)
33-
_BME280_HUMIDITY_MAX = const(100)
3430
_BME680_SAMPLERATES = (0, 1, 2, 4, 8, 16)
31+
_BME680_FILTERSIZES = (0, 1, 3, 7, 15, 31, 63, 127)
3532

3633
_BME680_RUNGAS = const(0x10)
3734

35+
lookupTable1 = (2147483647.0, 2147483647.0, 2147483647.0, 2147483647.0, 2147483647.0, 2126008810.0, 2147483647.0, 2130303777.0, 2147483647.0, 2147483647.0, 2143188679.0, 2136746228.0, 2147483647.0, 2126008810.0, 2147483647.0, 2147483647.0)
36+
37+
lookupTable2 = (4096000000.0, 2048000000.0, 1024000000.0, 512000000.0, 255744255.0, 127110228.0, 64000000.0, 32258064.0, 16016016.0, 8000000.0, 4000000.0, 2000000.0, 1000000.0, 500000.0, 250000.0, 125000.0)
38+
39+
3840
class Adafruit_BME680:
3941
def __init__(self):
4042
"""Check the BME680 was found, read the coefficients and enable the sensor for continuous reads"""
@@ -51,51 +53,63 @@ def __init__(self):
5153
# set up heater
5254
self._write(_BME680_BME680_RES_WAIT_0, [0x73, 0x64, 0x65])
5355
self.seaLevelhPa = 1013.25
54-
#self.pressure_oversample = 16
55-
#self.temp_oversample = 2
56-
#self.hum_oversample = 1
57-
self.osrs_h = 2
58-
self.osrs_t = 4
59-
self.osrs_p = 3
56+
self.pres_oversample = 4
57+
self.temp_oversample = 8
58+
self.hum_oversample = 2
6059
self.filter = 2
6160

62-
# set filter
63-
self._write(_BME680_REG_CONFIG, [self.filter << 2])
64-
# turn on temp oversample & pressure oversample
65-
self._write(_BME680_REG_CTRL_MEAS, [(self.osrs_t << 5)|(self.osrs_p << 2)])
66-
# turn on humidity oversample
67-
self._write(_BME680_REG_CTRL_HUM, [self.osrs_h])
68-
# gas measurements enabled
69-
self._write(_BME680_REG_CTRL_GAS, [_BME680_RUNGAS])
61+
@property
62+
def pres_oversample(self):
63+
return _BME680_SAMPLERATES[self.osrs_p]
64+
65+
@pres_oversample.setter
66+
def pres_oversample(self, os):
67+
"""Set the oversampling for pressure sensor"""
68+
if os in _BME680_SAMPLERATES:
69+
self.osrs_p = _BME680_SAMPLERATES.index(os)
70+
else:
71+
raise RuntimeError("Invalid oversample")
7072

71-
def reading(self):
72-
print("\n\nReading data");
73-
v = self._read(_BME680_REG_CTRL_MEAS, 1)[0]
74-
v = (v & 0xFC) | 0x01 # enable single shot!
75-
self._write(_BME680_REG_CTRL_MEAS, [v])
76-
77-
time.sleep(0.5)
73+
@property
74+
def hum_oversample(self):
75+
return _BME680_SAMPLERATES[self.osrs_h]
76+
77+
@hum_oversample.setter
78+
def hum_oversample(self, os):
79+
"""Set the oversampling for humidity sensor"""
80+
if os in _BME680_SAMPLERATES:
81+
self.osrs_h = _BME680_SAMPLERATES.index(os)
82+
else:
83+
raise RuntimeError("Invalid oversample")
7884

79-
data = self._read(_BME680_REG_STATUS, 15)
80-
print([hex(i) for i in data])
81-
print("")
82-
self._status = data[0] & 0x80
83-
gas_idx = data[0] & 0x0F
84-
meas_idx = data[1]
85-
#print("status 0x%x gas_idx %d meas_idx %d" % (status, gas_idx, meas_idx))
86-
87-
self._adc_pres = self._read24(data[2:5]) / 16
88-
self._adc_temp = self._read24(data[5:8]) / 16
89-
self._adc_hum = struct.unpack('>H', bytes(data[8:10]))[0]
90-
self._adc_gas = int(struct.unpack('>H', bytes(data[13:15]))[0] / 64)
91-
#print(self._adc_hum)
92-
#print(self._adc_gas)
93-
self._status |= data[14] & 0x30 # VALID + STABILITY mask
85+
@property
86+
def temp_oversample(self):
87+
return _BME680_SAMPLERATES[self.osrs_p]
88+
89+
@temp_oversample.setter
90+
def temp_oversample(self, os):
91+
"""Set the oversampling for temperature sensor"""
92+
if os in _BME680_SAMPLERATES:
93+
self.osrs_t = _BME680_SAMPLERATES.index(os)
94+
else:
95+
raise RuntimeError("Invalid oversample")
96+
97+
@property
98+
def filter_size(self):
99+
return _BME680_FILTERSIZES[self.filter]
100+
101+
@filter_size.setter
102+
def filter_size(self, fs):
103+
"""Set the filter size for the built in IIR filter"""
104+
if fs in _BME680_FILTERSIZES:
105+
self.filter = _BME680_FILTERSIZES(fs)
106+
else:
107+
raise RuntimeError("Invalid size")
94108

95109
@property
96110
def temperature(self):
97-
"""Gets the compensated temperature in degrees celsius."""
98-
self.reading()
111+
"""The compensated temperature in degrees celsius."""
112+
self._perform_reading()
99113
var1 = (self._adc_temp / 8) - (self._T1 * 2)
100114
var2 = (var1 * self._T2) / 2048
101115
var3 = ((var1 / 2) * (var1 / 2)) / 4096
@@ -106,6 +120,7 @@ def temperature(self):
106120

107121
@property
108122
def pressure(self):
123+
"""The barometric pressure in hectoPascals"""
109124
self.temperature
110125
var1 = (self.t_fine / 2) - 64000
111126
var2 = ((var1 / 4) * (var1 / 4)) / 2048
@@ -127,6 +142,7 @@ def pressure(self):
127142

128143
@property
129144
def humidity(self):
145+
"""The relative humidity in RH %"""
130146
self.temperature
131147
temp_scaled = ((self.t_fine * 5) + 128) / 256
132148
var1 = (self._adc_hum - (self._H1 * 16)) - ((temp_scaled * self._H3) / 200)
@@ -137,15 +153,60 @@ def humidity(self):
137153
var5 = ((var3 / 16384) * (var3 / 16384)) / 1024
138154
var6 = (var4 * var5) / 2
139155
calc_hum = (((var3 + var6) / 1024) * 1000) / 4096
140-
print(calc_hum)
141156
calc_hum /= 1000 # get back to RH
142157

143158
if calc_hum > 100: calc_hum = 100
144159
if calc_hum < 0: calc_hum = 0
145160
return calc_hum
146161

162+
@property
163+
def altitude(self):
164+
"""calculate the altitude based on the sea level pressure (seaLevelhPa) - which you must enter ahead of time)"""
165+
p = self.pressure # in Si units for hPascal
166+
return 44330 * (1.0 - math.pow(p / self.seaLevelhPa, 0.1903));
167+
168+
@property
169+
def gas(self):
170+
"""Return the gas resistance in ohms"""
171+
var1 = ((1340 + (5 * self._sw_err)) * (lookupTable1[self._gas_range])) / 65536
172+
var2 = ((self._adc_gas * 32768) - 16777216) + var1
173+
var3 = (lookupTable2[self._gas_range] * var1) / 512
174+
calc_gas_res = (var3 + (var2 / 2)) / var2
175+
return int(calc_gas_res)
176+
177+
def _perform_reading(self):
178+
"""Perform a single-shot reading from the sensor and fill internal data structure for calculations"""
179+
180+
# set filter
181+
self._write(_BME680_REG_CONFIG, [self.filter << 2])
182+
# turn on temp oversample & pressure oversample
183+
self._write(_BME680_REG_CTRL_MEAS, [(self.osrs_t << 5)|(self.osrs_p << 2)])
184+
# turn on humidity oversample
185+
self._write(_BME680_REG_CTRL_HUM, [self.osrs_h])
186+
# gas measurements enabled
187+
self._write(_BME680_REG_CTRL_GAS, [_BME680_RUNGAS])
188+
189+
v = self._read(_BME680_REG_CTRL_MEAS, 1)[0]
190+
v = (v & 0xFC) | 0x01 # enable single shot!
191+
self._write(_BME680_REG_CTRL_MEAS, [v])
192+
time.sleep(0.5)
193+
data = self._read(_BME680_REG_STATUS, 15)
194+
self._status = data[0] & 0x80
195+
gas_idx = data[0] & 0x0F
196+
meas_idx = data[1]
197+
#print("status 0x%x gas_idx %d meas_idx %d" % (status, gas_idx, meas_idx))
198+
199+
self._adc_pres = self._read24(data[2:5]) / 16
200+
self._adc_temp = self._read24(data[5:8]) / 16
201+
self._adc_hum = struct.unpack('>H', bytes(data[8:10]))[0]
202+
self._adc_gas = int(struct.unpack('>H', bytes(data[13:15]))[0] / 64)
203+
self._gas_range = data[14] & 0x0F
204+
#print(self._adc_hum)
205+
#print(self._adc_gas)
206+
self._status |= data[14] & 0x30 # VALID + STABILITY mask
207+
147208
def _read24(self, arr):
148-
"""Read an unsigned 24-bit value as a floating point and return it."""
209+
"""Parse an unsigned 24-bit value as a floating point and return it."""
149210
ret = 0.0
150211
#print([hex(i) for i in arr])
151212
for b in arr:
@@ -167,9 +228,9 @@ def _read_coefficients(self):
167228
self._H2 = h2m * 16 + (self._H1 % 16)
168229
self._H1 /= 16
169230

170-
self._HEATRANGE = (self._read(0x02, 1)[0] & 0x30) / 16
171-
self._HEATVAL = self._read(0x00, 1)[0]
172-
self._SWERR = (self._read(0x04, 1)[0] & 0xF0) / 16
231+
self._heat_range = (self._read(0x02, 1)[0] & 0x30) / 16
232+
self._heat_val = self._read(0x00, 1)[0]
233+
self._sw_err = (self._read(0x04, 1)[0] & 0xF0) / 16
173234

174235
#print("T1-3: %d %d %d" % (self._T1, self._T2, self._T3))
175236
#print("P1-3: %d %d %d" % (self._P1, self._P2, self._P3))
@@ -186,21 +247,27 @@ def _read_byte(self, register):
186247
return self._read(register, 1)[0]
187248

188249
class Adafruit_BME680_I2C(Adafruit_BME680):
189-
def __init__(self, i2c, address=_BME680_ADDRESS):
250+
def __init__(self, i2c, address=_BME680_ADDRESS, debug=False):
251+
"""Initialize the I2C device at the 'address' given"""
190252
import adafruit_bus_device.i2c_device as i2c_device
191253
self._i2c = i2c_device.I2CDevice(i2c, address)
254+
self._debug = debug
192255
super().__init__()
193256

194257
def _read(self, register, length):
258+
"""Returns an array of 'length' bytes from the 'register'"""
195259
with self._i2c as i2c:
196260
i2c.write(bytes([register & 0xFF]))
197261
result = bytearray(length)
198262
i2c.read_into(result)
199-
print("$%02X => %s" % (register, [hex(i) for i in result]))
263+
if self._debug:
264+
print("\t$%02X => %s" % (register, [hex(i) for i in result]))
200265
return result
201266

202267
def _write(self, register, values):
268+
"""Writes an array of 'length' bytes to the 'register'"""
203269
with self._i2c as i2c:
204270
values = [(v & 0xFF) for v in [register]+values]
205271
i2c.write(bytes(values))
206-
print("$%02X <= %s" % (values[0], [hex(i) for i in values[1:]]))
272+
if self._debug:
273+
print("\t$%02X <= %s" % (values[0], [hex(i) for i in values[1:]]))

0 commit comments

Comments
 (0)