102 lines
3.6 KiB
Python
102 lines
3.6 KiB
Python
import struct
|
|
import time
|
|
|
|
|
|
class BME280:
|
|
DEFAULT_ADDR = 0x77
|
|
|
|
def __init__(self, i2c, addr=DEFAULT_ADDR):
|
|
self.i2c = i2c
|
|
self.addr = addr
|
|
|
|
# Reset sensor
|
|
self.i2c.writeto_mem(self.addr, 0xE0, b"\xb6")
|
|
time.sleep(0.1)
|
|
|
|
self._read_calibration_data()
|
|
|
|
# Humidity oversampling x1
|
|
self.i2c.writeto_mem(self.addr, 0xF2, b"\x01")
|
|
# Pressure oversampling x1, Temp oversampling x1, Normal mode
|
|
self.i2c.writeto_mem(self.addr, 0xF4, b"\x27")
|
|
# Standby 1000ms, filter off
|
|
self.i2c.writeto_mem(self.addr, 0xF5, b"\xa0")
|
|
|
|
def _read_calibration_data(self):
|
|
calib = self.i2c.readfrom_mem(self.addr, 0x88, 24)
|
|
c = struct.unpack("<HhhHhhhhhhhh", calib)
|
|
self.dig_t1, self.dig_t2, self.dig_t3 = c[0], c[1], c[2]
|
|
self.dig_p1, self.dig_p2, self.dig_p3 = c[3], c[4], c[5]
|
|
self.dig_p4, self.dig_p5, self.dig_p6 = c[6], c[7], c[8]
|
|
self.dig_p7, self.dig_p8, self.dig_p9 = c[9], c[10], c[11]
|
|
|
|
self.dig_h1 = self.i2c.readfrom_mem(self.addr, 0xA1, 1)[0]
|
|
h = struct.unpack("<hB", self.i2c.readfrom_mem(self.addr, 0xE1, 3)[:3])
|
|
self.dig_h2, self.dig_h3 = h[0], h[1]
|
|
|
|
e4 = self.i2c.readfrom_mem(self.addr, 0xE4, 2)
|
|
self.dig_h4 = (e4[0] << 4) | (e4[1] & 0x0F)
|
|
|
|
e5_e6 = self.i2c.readfrom_mem(self.addr, 0xE5, 2)
|
|
self.dig_h5 = (e5_e6[0] >> 4) | (e5_e6[1] << 4)
|
|
|
|
self.dig_h6 = struct.unpack("<b", self.i2c.readfrom_mem(self.addr, 0xE7, 1))[0]
|
|
|
|
def read_values(self):
|
|
raw = self.i2c.readfrom_mem(self.addr, 0xF7, 8)
|
|
raw_p = ((raw[0] << 16) | (raw[1] << 8) | raw[2]) >> 4
|
|
raw_t = ((raw[3] << 16) | (raw[4] << 8) | raw[5]) >> 4
|
|
raw_h = (raw[6] << 8) | raw[7]
|
|
|
|
# Temperature calculation (Celsius)
|
|
var1 = (((raw_t >> 3) - (self.dig_t1 << 1)) * self.dig_t2) >> 11
|
|
var2 = (
|
|
(((raw_t >> 4) - self.dig_t1) * ((raw_t >> 4) - self.dig_t1)) >> 12
|
|
) * self.dig_t3 >> 14
|
|
t_fine = var1 + var2
|
|
temp = ((t_fine * 5 + 128) >> 8) / 100.0
|
|
|
|
# Pressure calculation (hPa)
|
|
p_var1 = t_fine - 128000
|
|
p_var2 = (
|
|
p_var1 * p_var1 * self.dig_p6 + ((p_var1 * self.dig_p5) << 17) + (self.dig_p4 << 35)
|
|
)
|
|
p_var1 = ((p_var1 * p_var1 * self.dig_p3) >> 8) + ((p_var1 * self.dig_p2) << 12)
|
|
p_var1 = (((1 << 47) + p_var1) * self.dig_p1) >> 33
|
|
|
|
if p_var1 == 0:
|
|
pressure = 0.0
|
|
else:
|
|
p = 1048576 - raw_p
|
|
p = (((p << 31) - p_var2) * 3125) // p_var1
|
|
p_var1 = (self.dig_p9 * (p >> 13) * (p >> 13)) >> 25
|
|
p_var2 = (self.dig_p8 * p) >> 19
|
|
p = ((p + p_var1 + p_var2) >> 8) + (self.dig_p7 << 4)
|
|
pressure = (p / 256.0) / 100.0
|
|
|
|
# Humidity calculation (%)
|
|
h_var = t_fine - 76800
|
|
h_var = ((((raw_h << 14) - (self.dig_h4 << 20) - (self.dig_h5 * h_var)) + 16384) >> 15) * (
|
|
(
|
|
(
|
|
(
|
|
(((h_var * self.dig_h6) >> 10) * (((h_var * self.dig_h3) >> 11) + 32768))
|
|
>> 10
|
|
)
|
|
+ 2097152
|
|
)
|
|
* self.dig_h2
|
|
+ 8192
|
|
)
|
|
>> 14
|
|
)
|
|
h_var = h_var - (((((h_var >> 15) * (h_var >> 15)) >> 7) * self.dig_h1) >> 4)
|
|
h_var = max(0, min(h_var, 419430400))
|
|
humidity = (h_var >> 12) / 1024.0
|
|
|
|
return {
|
|
"temperature": round(temp, 2),
|
|
"pressure": round(pressure, 2),
|
|
"humidity": round(humidity, 2),
|
|
}
|