from machine import Pin, I2C
from micropython import const
from time import sleep
import ustruct
_ADDR = const(0x76)
_CALIB2 = const(0xE1)
_CALIB1 = const(0x88)
_DATA = const(0xF7)
_CONFIG = const(0xF5)
_CTRL_MEAS = const(0xF4)
_CTRL_HUM = const(0xF2)
_CHIP_ID = const(0xD0)
_RESET = const(0xE0)
class TooManyAttempts(Exception):
"""Too many attempts"""
class BME280:
def __init__(self, i2c):
self._i2c = i2c
self._ready = bytearray(1)
self._chip_id = bytearray(1)
self._data = bytearray(8)
self._calib1 = bytearray(26)
self._calib2 = bytearray(7)
def ready(self):
attempts = 100
while True:
self._i2c.readfrom_into(_ADDR, self._ready)
if self._ready == b"\x00":
break
attempts -= 1
if not attempts:
raise TooManyAttempts()
def chip_id(self):
self.ready()
self._i2c.readfrom_mem_into(_ADDR, _CHIP_ID, self._chip_id)
return self._chip_id
def reset(self):
self.ready()
self._i2c.writeto_mem(_ADDR, _RESET, b"\xb6")
def ctrl_hum(self, osrs_h=16):
self.ready()
self._i2c.writeto_mem(_ADDR, _CTRL_HUM, chr(0b101))
def ctrl_meas(self, osrs_t=16, osrs_p=16, mode="normal"):
self.ready()
self._i2c.writeto_mem(_ADDR, _CTRL_MEAS, chr(0b10110111))
def config(self, t_sb=500, filter=2):
self.ready()
self._i2c.writeto_mem(_ADDR, _CONFIG, chr(0b10001000))
def data(self):
self.ready()
self._i2c.readfrom_mem_into(_ADDR, _DATA, self._data)
@property
def raw_pressure(self):
data = self._data
return (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
@property
def raw_temperature(self):
data = self._data
return (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
@property
def raw_humidity(self):
data = self._data
return (data[6] << 8) | data[7]
@property
def temperature(self):
temp_raw = self.raw_temperature
dig_T1, dig_T2, dig_T3 = self._calib[:3]
var1 = ((((temp_raw >> 3) - (dig_T1 << 1))) * (dig_T2)) >> 11
var2 = (
((((temp_raw >> 4) - (dig_T1)) * ((temp_raw >> 4) - (dig_T1))) >> 12)
* (dig_T3)
) >> 14
t_fine = var1 + var2
return float(((t_fine * 5) + 128) >> 8) / 100.0
def calibration(self):
self.ready()
self._i2c.readfrom_mem_into(_ADDR, _CALIB1, self._calib1)
self.ready()
self._i2c.readfrom_mem_into(_ADDR, _CALIB2, self._calib2)
self._calib = ustruct.unpack("HhhHhhhhhhhhBb", self._calib1) + ustruct.unpack(
"hBbbbB", self._calib2
)
def init(self):
self.reset()
sleep(0.1)
self.ctrl_hum()
self.ctrl_meas()
self.config()
self.calibration()
bme280 = BME280(I2C(0, scl=Pin(21), sda=Pin(20)))
print(bme280.chip_id())
bme280.init()
then
bme280.data()
refreshes the data and bme280.temperature
is a float containing the current temperature.
My temperature calibration code is from MattHawkinsUK/rpispy-misc which is using bit shifting whereas the pimoroni code at pimoroni/bme280-python seems to be doing lots of floating point maths.