20
20
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
# THE SOFTWARE.
22
22
"""
23
- `adafruit_bme280` - Adafruit BME680 - Temperature, Humidity, Pressure & Gas Sensor
24
- ====================================================================================
23
+ `adafruit_bme280` - Adafruit BME280 - Temperature, Humidity & Barometic Pressure Sensor
24
+ =========================================================================================
25
25
26
26
CircuitPython driver from BME280 Temperature, Humidity and Barometic Pressure sensor
27
27
28
28
* Author(s): ladyada
29
29
"""
30
30
import math
31
- import time
31
+ from time import sleep
32
32
from micropython import const
33
33
try :
34
34
import struct
67
67
_BME280_HUMIDITY_MIN = const (0 )
68
68
_BME280_HUMIDITY_MAX = const (100 )
69
69
70
+ """iir_filter values"""
71
+ IIR_FILTER_DISABLE = const (0 )
72
+ IIR_FILTER_X2 = const (0x01 )
73
+ IIR_FILTER_X4 = const (0x02 )
74
+ IIR_FILTER_X8 = const (0x03 )
75
+ IIR_FILTER_X16 = const (0x04 )
76
+
77
+ _BME280_IIR_FILTERS = frozenset ((IIR_FILTER_DISABLE , IIR_FILTER_X2 ,
78
+ IIR_FILTER_X4 , IIR_FILTER_X8 , IIR_FILTER_X16 ))
79
+
80
+ """overscan values for temperature, pressure, and humidity"""
81
+ OVERSCAN_DISABLE = const (0x00 )
82
+ OVERSCAN_X1 = const (0x01 )
83
+ OVERSCAN_X2 = const (0x02 )
84
+ OVERSCAN_X4 = const (0x03 )
85
+ OVERSCAN_X8 = const (0x04 )
86
+ OVERSCAN_X16 = const (0x05 )
87
+
88
+ _BME280_OVERSCANS = {OVERSCAN_DISABLE :0 , OVERSCAN_X1 :1 , OVERSCAN_X2 :2 ,
89
+ OVERSCAN_X4 :4 , OVERSCAN_X8 :8 , OVERSCAN_X16 :16 }
90
+
91
+ """mode values"""
92
+ MODE_SLEEP = const (0x00 )
93
+ MODE_FORCE = const (0x01 )
94
+ MODE_NORMAL = const (0x03 )
95
+
96
+ _BME280_MODES = frozenset ((MODE_SLEEP , MODE_FORCE , MODE_NORMAL ))
97
+ """
98
+ standby timeconstant values
99
+ TC_X[_Y] where X=milliseconds and Y=tenths of a millisecond
100
+ """
101
+ STANDBY_TC_0_5 = const (0x00 ) #0.5ms
102
+ STANDBY_TC_10 = const (0x06 ) #10ms
103
+ STANDBY_TC_20 = const (0x07 ) #20ms
104
+ STANDBY_TC_62_5 = const (0x01 ) #62.5ms
105
+ STANDBY_TC_125 = const (0x02 ) #125ms
106
+ STANDBY_TC_250 = const (0x03 ) #250ms
107
+ STANDBY_TC_500 = const (0x04 ) #500ms
108
+ STANDBY_TC_1000 = const (0x05 ) #1000ms
109
+
110
+ _BME280_STANDBY_TCS = frozenset ((STANDBY_TC_0_5 , STANDBY_TC_10 , STANDBY_TC_20 ,
111
+ STANDBY_TC_62_5 , STANDBY_TC_125 , STANDBY_TC_250 ,
112
+ STANDBY_TC_500 , STANDBY_TC_1000 ))
113
+
70
114
class Adafruit_BME280 :
71
115
"""Driver from BME280 Temperature, Humidity and Barometic Pressure sensor"""
116
+ # pylint: disable=too-many-instance-attributes
72
117
def __init__ (self ):
73
- """Check the BME280 was found, read the coefficients and enable the sensor for continuous
74
- reads"""
118
+ """Check the BME280 was found, read the coefficients and enable the sensor"""
75
119
# Check device ID.
76
120
chip_id = self ._read_byte (_BME280_REGISTER_CHIPID )
77
121
if _BME280_CHIPID != chip_id :
78
122
raise RuntimeError ('Failed to find BME280! Chip ID 0x%x' % chip_id )
79
- self ._write_register_byte (_BME280_REGISTER_SOFTRESET , 0xB6 )
80
- time .sleep (0.5 )
123
+ #Set some reasonable defaults.
124
+ self ._iir_filter = IIR_FILTER_DISABLE
125
+ self ._overscan_humidity = OVERSCAN_X1
126
+ self ._overscan_temperature = OVERSCAN_X1
127
+ self ._overscan_pressure = OVERSCAN_X16
128
+ self ._t_standby = STANDBY_TC_125
129
+ self ._mode = MODE_SLEEP
130
+ self ._reset ()
81
131
self ._read_coefficients ()
132
+ self ._write_ctrl_meas ()
133
+ self ._write_config ()
82
134
self .sea_level_pressure = 1013.25
83
135
"""Pressure in hectoPascals at sea level. Used to calibrate `altitude`."""
84
- # turn on humidity oversample 16x
85
- self ._write_register_byte (_BME280_REGISTER_CTRL_HUM , 0x03 )
86
136
self ._t_fine = None
87
137
88
138
def _read_temperature (self ):
89
139
# perform one measurement
90
- self ._write_register_byte ( _BME280_REGISTER_CTRL_MEAS , 0xFE ) # high res, forced mode
91
-
92
- # Wait for conversion to complete
93
- while self ._read_byte ( _BME280_REGISTER_STATUS ) & 0x08 :
94
- time . sleep (0.002 )
95
- raw_temperature = self ._read24 (_BME280_REGISTER_TEMPDATA ) / 16 # lowest 4 bits get dropped
140
+ if self .mode != MODE_NORMAL :
141
+ self . mode = MODE_FORCE
142
+ # Wait for conversion to complete
143
+ while self ._get_status ( ) & 0x08 :
144
+ sleep (0.002 )
145
+ raw_temperature = self ._read24 (_BME280_REGISTER_TEMPDATA ) / 16 # lowest 4 bits get dropped
96
146
#print("raw temp: ", UT)
97
-
98
147
var1 = (raw_temperature / 16384.0 - self ._temp_calib [0 ] / 1024.0 ) * self ._temp_calib [1 ]
99
148
#print(var1)
100
149
var2 = ((raw_temperature / 131072.0 - self ._temp_calib [0 ] / 8192.0 ) * (
@@ -104,6 +153,173 @@ def _read_temperature(self):
104
153
self ._t_fine = int (var1 + var2 )
105
154
#print("t_fine: ", self.t_fine)
106
155
156
+ def _reset (self ):
157
+ """Soft reset the sensor"""
158
+ self ._write_register_byte (_BME280_REGISTER_SOFTRESET , 0xB6 )
159
+ sleep (0.004 ) #Datasheet says 2ms. Using 4ms just to be safe
160
+
161
+ def _write_ctrl_meas (self ):
162
+ """
163
+ Write the values to the ctrl_meas and ctrl_hum registers in the device
164
+ ctrl_meas sets the pressure and temperature data acquistion options
165
+ ctrl_hum sets the humidty oversampling and must be written to first
166
+ """
167
+ self ._write_register_byte (_BME280_REGISTER_CTRL_HUM , self .overscan_humidity )
168
+ self ._write_register_byte (_BME280_REGISTER_CTRL_MEAS , self ._ctrl_meas )
169
+
170
+ def _get_status (self ):
171
+ """Get the value from the status register in the device """
172
+ return self ._read_byte (_BME280_REGISTER_STATUS )
173
+
174
+ def _read_config (self ):
175
+ """Read the value from the config register in the device """
176
+ return self ._read_byte (_BME280_REGISTER_CONFIG )
177
+
178
+ def _write_config (self ):
179
+ """Write the value to the config register in the device """
180
+ normal_flag = False
181
+ if self ._mode == MODE_NORMAL :
182
+ #Writes to the config register may be ignored while in Normal mode
183
+ normal_flag = True
184
+ self .mode = MODE_SLEEP #So we switch to Sleep mode first
185
+ self ._write_register_byte (_BME280_REGISTER_CONFIG , self ._config )
186
+ if normal_flag :
187
+ self .mode = MODE_NORMAL
188
+
189
+ @property
190
+ def mode (self ):
191
+ """
192
+ Operation mode
193
+ Allowed values are the constants MODE_*
194
+ """
195
+ return self ._mode
196
+
197
+ @mode .setter
198
+ def mode (self , value ):
199
+ if not value in _BME280_MODES :
200
+ raise ValueError ('Mode \' %s\' not supported' % (value ))
201
+ self ._mode = value
202
+ self ._write_ctrl_meas ()
203
+
204
+ @property
205
+ def standby_period (self ):
206
+ """
207
+ Control the inactive period when in Normal mode
208
+ Allowed standby periods are the constants STANDBY_TC_*
209
+ """
210
+ return self ._t_standby
211
+
212
+ @standby_period .setter
213
+ def standby_period (self , value ):
214
+ if not value in _BME280_STANDBY_TCS :
215
+ raise ValueError ('Standby Period \' %s\' not supported' % (value ))
216
+ if self ._t_standby == value :
217
+ return
218
+ self ._t_standby = value
219
+ self ._write_config ()
220
+
221
+ @property
222
+ def overscan_humidity (self ):
223
+ """
224
+ Humidity Oversampling
225
+ Allowed values are the constants OVERSCAN_*
226
+ """
227
+ return self ._overscan_humidity
228
+
229
+ @overscan_humidity .setter
230
+ def overscan_humidity (self , value ):
231
+ if not value in _BME280_OVERSCANS :
232
+ raise ValueError ('Overscan value \' %s\' not supported' % (value ))
233
+ self ._overscan_humidity = value
234
+ self ._write_ctrl_meas ()
235
+
236
+ @property
237
+ def overscan_temperature (self ):
238
+ """
239
+ Temperature Oversampling
240
+ Allowed values are the constants OVERSCAN_*
241
+ """
242
+ return self ._overscan_temperature
243
+
244
+ @overscan_temperature .setter
245
+ def overscan_temperature (self , value ):
246
+ if not value in _BME280_OVERSCANS :
247
+ raise ValueError ('Overscan value \' %s\' not supported' % (value ))
248
+ self ._overscan_temperature = value
249
+ self ._write_ctrl_meas ()
250
+
251
+ @property
252
+ def overscan_pressure (self ):
253
+ """
254
+ Pressure Oversampling
255
+ Allowed values are the constants OVERSCAN_*
256
+ """
257
+ return self ._overscan_pressure
258
+
259
+ @overscan_pressure .setter
260
+ def overscan_pressure (self , value ):
261
+ if not value in _BME280_OVERSCANS :
262
+ raise ValueError ('Overscan value \' %s\' not supported' % (value ))
263
+ self ._overscan_pressure = value
264
+ self ._write_ctrl_meas ()
265
+
266
+ @property
267
+ def iir_filter (self ):
268
+ """
269
+ Controls the time constant of the IIR filter
270
+ Allowed values are the constants IIR_FILTER_*
271
+ """
272
+ return self ._iir_filter
273
+
274
+ @iir_filter .setter
275
+ def iir_filter (self , value ):
276
+ if not value in _BME280_IIR_FILTERS :
277
+ raise ValueError ('IIR Filter \' %s\' not supported' % (value ))
278
+ self ._iir_filter = value
279
+ self ._write_config ()
280
+
281
+ @property
282
+ def _config (self ):
283
+ """Value to be written to the device's config register """
284
+ config = 0
285
+ if self .mode == MODE_NORMAL :
286
+ config += (self ._t_standby << 5 )
287
+ if self ._iir_filter :
288
+ config += (self ._iir_filter << 2 )
289
+ return config
290
+
291
+ @property
292
+ def _ctrl_meas (self ):
293
+ """Value to be written to the device's ctrl_meas register """
294
+ ctrl_meas = (self .overscan_temperature << 5 )
295
+ ctrl_meas += (self .overscan_pressure << 2 )
296
+ ctrl_meas += self .mode
297
+ return ctrl_meas
298
+
299
+ @property
300
+ def measurement_time_typical (self ):
301
+ """Typical time in milliseconds required to complete a measurement in normal mode"""
302
+ meas_time_ms = 1.0
303
+ if self .overscan_temperature != OVERSCAN_DISABLE :
304
+ meas_time_ms += (2 * _BME280_OVERSCANS .get (self .overscan_temperature ))
305
+ if self .overscan_pressure != OVERSCAN_DISABLE :
306
+ meas_time_ms += (2 * _BME280_OVERSCANS .get (self .overscan_pressure ) + 0.5 )
307
+ if self .overscan_humidity != OVERSCAN_DISABLE :
308
+ meas_time_ms += (2 * _BME280_OVERSCANS .get (self .overscan_humidity ) + 0.5 )
309
+ return meas_time_ms
310
+
311
+ @property
312
+ def measurement_time_max (self ):
313
+ """Maximum time in milliseconds required to complete a measurement in normal mode"""
314
+ meas_time_ms = 1.25
315
+ if self .overscan_temperature != OVERSCAN_DISABLE :
316
+ meas_time_ms += (2.3 * _BME280_OVERSCANS .get (self .overscan_temperature ))
317
+ if self .overscan_pressure != OVERSCAN_DISABLE :
318
+ meas_time_ms += (2.3 * _BME280_OVERSCANS .get (self .overscan_pressure ) + 0.575 )
319
+ if self .overscan_humidity != OVERSCAN_DISABLE :
320
+ meas_time_ms += (2.3 * _BME280_OVERSCANS .get (self .overscan_humidity ) + 0.575 )
321
+ return meas_time_ms
322
+
107
323
@property
108
324
def temperature (self ):
109
325
"""The compensated temperature in degrees celsius."""
@@ -112,7 +328,10 @@ def temperature(self):
112
328
113
329
@property
114
330
def pressure (self ):
115
- """The compensated pressure in hectoPascals."""
331
+ """
332
+ The compensated pressure in hectoPascals.
333
+ returns None if pressure measurement is disabled
334
+ """
116
335
self ._read_temperature ()
117
336
118
337
# Algorithm from the BME280 driver
@@ -145,7 +364,10 @@ def pressure(self):
145
364
146
365
@property
147
366
def humidity (self ):
148
- """The relative humidity in RH %"""
367
+ """
368
+ The relative humidity in RH %
369
+ returns None if humidity measurement is disabled
370
+ """
149
371
self ._read_temperature ()
150
372
hum = self ._read_register (_BME280_REGISTER_HUMIDDATA , 2 )
151
373
#print("Humidity data: ", hum)
0 commit comments