Skip to content

Commit 8b142fc

Browse files
committed
feat(bme280): Add measurement modes and sensor configuration.
1 parent f748804 commit 8b142fc

2 files changed

Lines changed: 203 additions & 0 deletions

File tree

lib/bme280/bme280/device.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,26 @@
77
CALIB_H_SIZE,
88
CALIB_TP_SIZE,
99
DATA_BLOCK_SIZE,
10+
FILTER_SHIFT,
1011
MODE_FORCED,
1112
MODE_MASK,
13+
MODE_NORMAL,
1214
MODE_SLEEP,
1315
OSRS_P_SHIFT,
1416
OSRS_T_SHIFT,
1517
OSRS_X1,
1618
REG_CALIB_HUM,
1719
REG_CALIB_TEMP_PRESS,
1820
REG_CHIP_ID,
21+
REG_CONFIG,
1922
REG_CTRL_HUM,
2023
REG_CTRL_MEAS,
2124
REG_DATA_START,
2225
REG_SOFT_RESET,
2326
REG_STATUS,
2427
RESET_DELAY_MS,
2528
SOFT_RESET_CMD,
29+
STANDBY_SHIFT,
2630
STATUS_IM_UPDATE,
2731
STATUS_MEASURING,
2832
)
@@ -139,6 +143,73 @@ def reset(self):
139143
self._read_calibration()
140144
self._configure_default()
141145

146+
# --------------------------------------------------
147+
# Power and mode control
148+
# --------------------------------------------------
149+
150+
def power_off(self):
151+
"""Enter sleep mode. Stops all measurements."""
152+
ctrl = self._read_reg(REG_CTRL_MEAS)
153+
self._write_reg(REG_CTRL_MEAS, ctrl & ~MODE_MASK)
154+
155+
def power_on(self):
156+
"""Enter normal mode. Continuous measurements at configured standby rate."""
157+
ctrl = self._read_reg(REG_CTRL_MEAS)
158+
self._write_reg(REG_CTRL_MEAS, (ctrl & ~MODE_MASK) | MODE_NORMAL)
159+
160+
def set_continuous(self, standby=None):
161+
"""Start continuous measurements in normal mode.
162+
163+
Args:
164+
standby: standby time constant (STANDBY_0_5_MS .. STANDBY_1000_MS).
165+
If None, the current config register value is kept.
166+
"""
167+
if standby is not None:
168+
self.set_standby(standby)
169+
self.power_on()
170+
171+
# --------------------------------------------------
172+
# Sensor configuration
173+
# --------------------------------------------------
174+
175+
def set_oversampling(self, temperature=None, pressure=None, humidity=None):
176+
"""Configure oversampling for one or more channels.
177+
178+
Args:
179+
temperature: OSRS_SKIP .. OSRS_X16 (None = keep current).
180+
pressure: OSRS_SKIP .. OSRS_X16 (None = keep current).
181+
humidity: OSRS_SKIP .. OSRS_X16 (None = keep current).
182+
"""
183+
if humidity is not None:
184+
self._write_reg(REG_CTRL_HUM, humidity)
185+
if temperature is not None or pressure is not None:
186+
ctrl = self._read_reg(REG_CTRL_MEAS)
187+
if temperature is not None:
188+
ctrl = (ctrl & ~(0x07 << OSRS_T_SHIFT)) | (temperature << OSRS_T_SHIFT)
189+
if pressure is not None:
190+
ctrl = (ctrl & ~(0x07 << OSRS_P_SHIFT)) | (pressure << OSRS_P_SHIFT)
191+
self._write_reg(REG_CTRL_MEAS, ctrl)
192+
193+
def set_iir_filter(self, coefficient):
194+
"""Configure the IIR filter coefficient.
195+
196+
Args:
197+
coefficient: FILTER_OFF .. FILTER_16.
198+
"""
199+
config = self._read_reg(REG_CONFIG)
200+
config = (config & ~(0x07 << FILTER_SHIFT)) | (coefficient << FILTER_SHIFT)
201+
self._write_reg(REG_CONFIG, config)
202+
203+
def set_standby(self, standby):
204+
"""Configure the standby time for normal mode.
205+
206+
Args:
207+
standby: STANDBY_0_5_MS .. STANDBY_1000_MS.
208+
"""
209+
config = self._read_reg(REG_CONFIG)
210+
config = (config & ~(0x07 << STANDBY_SHIFT)) | (standby << STANDBY_SHIFT)
211+
self._write_reg(REG_CONFIG, config)
212+
142213
# --------------------------------------------------
143214
# Status
144215
# --------------------------------------------------

tests/scenarios/bme280.yaml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,135 @@ tests:
274274
result = triggered and abs(t - 25.08) < 0.1
275275
expect_true: true
276276
mode: [mock]
277+
278+
# ----- Power and mode control -----
279+
280+
- name: "power_off sets sleep mode"
281+
action: script
282+
script: |
283+
i2c.clear_write_log()
284+
dev.power_off()
285+
log = i2c.get_write_log()
286+
wrote_sleep = any(reg == 0xF4 and (data[0] & 0x03) == 0x00 for reg, data in log)
287+
result = wrote_sleep
288+
expect_true: true
289+
mode: [mock]
290+
291+
- name: "power_on sets normal mode"
292+
action: script
293+
script: |
294+
i2c.clear_write_log()
295+
dev.power_on()
296+
log = i2c.get_write_log()
297+
wrote_normal = any(reg == 0xF4 and (data[0] & 0x03) == 0x03 for reg, data in log)
298+
result = wrote_normal
299+
expect_true: true
300+
mode: [mock]
301+
302+
- name: "power_off preserves oversampling bits"
303+
action: script
304+
script: |
305+
from bme280.const import OSRS_X4, OSRS_T_SHIFT, OSRS_P_SHIFT
306+
dev.set_oversampling(temperature=OSRS_X4, pressure=OSRS_X4)
307+
i2c.clear_write_log()
308+
dev.power_off()
309+
log = i2c.get_write_log()
310+
ctrl = [data[0] for reg, data in log if reg == 0xF4][-1]
311+
osrs_t = (ctrl >> 5) & 0x07
312+
osrs_p = (ctrl >> 2) & 0x07
313+
result = osrs_t == OSRS_X4 and osrs_p == OSRS_X4 and (ctrl & 0x03) == 0x00
314+
expect_true: true
315+
mode: [mock]
316+
317+
- name: "set_continuous enters normal mode"
318+
action: script
319+
script: |
320+
dev.power_off()
321+
i2c.clear_write_log()
322+
dev.set_continuous()
323+
log = i2c.get_write_log()
324+
wrote_normal = any(reg == 0xF4 and (data[0] & 0x03) == 0x03 for reg, data in log)
325+
result = wrote_normal
326+
expect_true: true
327+
mode: [mock]
328+
329+
- name: "set_continuous with standby configures both"
330+
action: script
331+
script: |
332+
from bme280.const import STANDBY_500_MS, STANDBY_SHIFT
333+
i2c.clear_write_log()
334+
dev.set_continuous(standby=STANDBY_500_MS)
335+
log = i2c.get_write_log()
336+
wrote_config = any(reg == 0xF5 for reg, data in log)
337+
wrote_normal = any(reg == 0xF4 and (data[0] & 0x03) == 0x03 for reg, data in log)
338+
result = wrote_config and wrote_normal
339+
expect_true: true
340+
mode: [mock]
341+
342+
# ----- Configuration -----
343+
344+
- name: "set_oversampling configures temperature and pressure"
345+
action: script
346+
script: |
347+
from bme280.const import OSRS_X2, OSRS_X4, OSRS_T_SHIFT, OSRS_P_SHIFT
348+
i2c.clear_write_log()
349+
dev.set_oversampling(temperature=OSRS_X2, pressure=OSRS_X4)
350+
log = i2c.get_write_log()
351+
ctrl_writes = [data[0] for reg, data in log if reg == 0xF4]
352+
ctrl = ctrl_writes[-1]
353+
osrs_t = (ctrl >> OSRS_T_SHIFT) & 0x07
354+
osrs_p = (ctrl >> OSRS_P_SHIFT) & 0x07
355+
result = osrs_t == OSRS_X2 and osrs_p == OSRS_X4
356+
expect_true: true
357+
mode: [mock]
358+
359+
- name: "set_oversampling configures humidity"
360+
action: script
361+
script: |
362+
from bme280.const import OSRS_X8
363+
i2c.clear_write_log()
364+
dev.set_oversampling(humidity=OSRS_X8)
365+
log = i2c.get_write_log()
366+
hum_writes = [data[0] for reg, data in log if reg == 0xF2]
367+
result = len(hum_writes) == 1 and hum_writes[0] == OSRS_X8
368+
expect_true: true
369+
mode: [mock]
370+
371+
- name: "set_iir_filter writes config register"
372+
action: script
373+
script: |
374+
from bme280.const import FILTER_16, FILTER_SHIFT
375+
i2c.clear_write_log()
376+
dev.set_iir_filter(FILTER_16)
377+
log = i2c.get_write_log()
378+
config_writes = [data[0] for reg, data in log if reg == 0xF5]
379+
result = len(config_writes) == 1 and ((config_writes[0] >> FILTER_SHIFT) & 0x07) == FILTER_16
380+
expect_true: true
381+
mode: [mock]
382+
383+
- name: "set_standby writes config register"
384+
action: script
385+
script: |
386+
from bme280.const import STANDBY_250_MS, STANDBY_SHIFT
387+
i2c.clear_write_log()
388+
dev.set_standby(STANDBY_250_MS)
389+
log = i2c.get_write_log()
390+
config_writes = [data[0] for reg, data in log if reg == 0xF5]
391+
result = len(config_writes) == 1 and ((config_writes[0] >> STANDBY_SHIFT) & 0x07) == STANDBY_250_MS
392+
expect_true: true
393+
mode: [mock]
394+
395+
- name: "set_iir_filter preserves standby bits"
396+
action: script
397+
script: |
398+
from bme280.const import STANDBY_500_MS, STANDBY_SHIFT, FILTER_4, FILTER_SHIFT
399+
dev.set_standby(STANDBY_500_MS)
400+
i2c.clear_write_log()
401+
dev.set_iir_filter(FILTER_4)
402+
log = i2c.get_write_log()
403+
config = [data[0] for reg, data in log if reg == 0xF5][-1]
404+
standby = (config >> STANDBY_SHIFT) & 0x07
405+
filt = (config >> FILTER_SHIFT) & 0x07
406+
result = standby == STANDBY_500_MS and filt == FILTER_4
407+
expect_true: true
408+
mode: [mock]

0 commit comments

Comments
 (0)