diff --git a/bme280.py b/bme280.py index 1a29a1c..642468a 100644 --- a/bme280.py +++ b/bme280.py @@ -33,6 +33,15 @@ 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 @@ -40,6 +49,11 @@ def read_all(addr: int = DEVICE_ADDRESS) -> tuple[float, float, float]: 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) diff --git a/tests/test_bme280.py b/tests/test_bme280.py index 0224e1d..6ec2bc9 100644 --- a/tests/test_bme280.py +++ b/tests/test_bme280.py @@ -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 @@ -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()