Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions bme280.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,27 @@ def read_id(addr: int = DEVICE_ADDRESS) -> tuple[int, int]:
return chip_id, chip_version


def _wait_nvm_copy(bus: smbus2.SMBus, addr: int) -> None:
"""Poll status register until NVM copy is complete after soft reset."""
for _ in range(5):
if not (bus.read_byte_data(addr, 0xF3) & 0x01):
return
time.sleep(0.002)
raise OSError("BME280 NVM copy did not complete after soft reset")


def read_all(addr: int = DEVICE_ADDRESS) -> tuple[float, float, float]:
OVERSAMPLE_TEMP = 2
OVERSAMPLE_PRES = 2
OVERSAMPLE_HUM = 2
MODE = 1

with smbus2.SMBus(I2C_BUS) as bus:
# Soft reset to ensure the sensor starts from a known state
bus.write_byte_data(addr, 0xE0, 0xB6)
time.sleep(0.002) # 2ms startup delay (datasheet section 4.2)
_wait_nvm_copy(bus, addr)

bus.write_byte_data(addr, 0xF2, OVERSAMPLE_HUM)
bus.write_byte_data(addr, 0xF4, OVERSAMPLE_TEMP << 5 | OVERSAMPLE_PRES << 2 | MODE)

Expand Down
13 changes: 13 additions & 0 deletions tests/test_bme280.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

def make_mock_bus(chip_id: int = 96, chip_version: int = 0) -> MagicMock:
bus = MagicMock()
bus.read_byte_data.return_value = 0 # 0xF3 status: NVM copy done, not measuring
bus.read_i2c_block_data.side_effect = [
[chip_id, chip_version], # read_id
[0] * 24, # cal1 - T and P calibration
Expand Down Expand Up @@ -107,3 +108,15 @@ def test_pressure_zero_when_p1_calibration_is_zero(patched_smbus):
import bme280
result = bme280.sensor()
assert result['data']['pressure'] == 0.0


def test_nvm_copy_timeout_raises_oserror():
bus = MagicMock()
bus.read_byte_data.return_value = 0x01 # NVM copy never completes
with patch('bme280.smbus2.SMBus') as MockSMBus:
instance = MockSMBus.return_value
instance.__enter__ = MagicMock(return_value=bus)
instance.__exit__ = MagicMock(return_value=False)
import bme280
with pytest.raises(OSError, match="NVM copy"):
bme280.read_all()
Loading