#!/usr/bin/env python import time AUX_SPI=256 # Sampling OVER_SAMPLE_1 = 1 OVER_SAMPLE_2 = 2 OVER_SAMPLE_4 = 3 OVER_SAMPLE_8 = 4 OVER_SAMPLE_16 = 5 class sensor: """ A class to read the BME280 pressure, humidity, and temperature sensor._ """ # BME280 Registers _calib00 = 0x88 _T1 = 0x88 - _calib00 _T2 = 0x8A - _calib00 _T3 = 0x8C - _calib00 _P1 = 0x8E - _calib00 _P2 = 0x90 - _calib00 _P3 = 0x92 - _calib00 _P4 = 0x94 - _calib00 _P5 = 0x96 - _calib00 _P6 = 0x98 - _calib00 _P7 = 0x9A - _calib00 _P8 = 0x9C - _calib00 _P9 = 0x9E - _calib00 _H1 = 0xA1 - _calib00 _chip_id = 0xD0 _reset = 0xE0 _calib26 = 0xE1 _H2 = 0xE1 - _calib26 _H3 = 0xE3 - _calib26 _xE4 = 0xE4 - _calib26 _xE5 = 0xE5 - _calib26 _xE6 = 0xE6 - _calib26 _H6 = 0xE7 - _calib26 _ctrl_hum = 0xF2 _status = 0xF3 _ctrl_meas = 0xF4 _config = 0xF5 _rawdata = 0xF7 _p_msb = 0xF7 - _rawdata _p_lsb = 0xF8 - _rawdata _p_xlsb = 0xF9 - _rawdata _t_msb = 0xFA - _rawdata _t_lsb = 0xFB - _rawdata _t_xlsb = 0xFC - _rawdata _h_msb = 0xFD - _rawdata _h_lsb = 0xFE - _rawdata _os_ms = [0, 1, 2, 4, 8, 16] def __init__(self, pi, sampling=OVER_SAMPLE_1, bus=1, address=0x76, channel=0, baud=10000000, flags=0): self.pi = pi self.sampling = sampling self.h = pi.i2c_open(bus, address) self._load_calibration() self.measure_delay = self._measurement_time(sampling, sampling, sampling) self.t_fine = 0.0 def _measurement_time(self, os_temp, os_press, os_hum): ms = ( (1.25 + 2.3 * sensor._os_ms[os_temp]) + (0.575 + 2.3 * sensor._os_ms[os_press]) + (0.575 + 2.3 * sensor._os_ms[os_hum]) ) return (ms/1000.0) def _u16(self, _calib, off): return (_calib[off] | (_calib[off+1]<<8)) def _s16(self, _calib, off): v = self._u16(_calib, off) if v > 32767: v -= 65536 return v def _u8(self, _calib, off): return _calib[off] def _s8(self, _calib, off): v = self._u8(_calib,off) if v > 127: v -= 256 return v def _write_registers(self, data): self.pi.i2c_write_device(self.h, data) def _read_registers(self, reg, count): return self.pi.i2c_read_i2c_block_data(self.h, reg, count) def _load_calibration(self): c, d1 = self._read_registers(sensor._calib00, 26) self.T1 = self._u16(d1, sensor._T1) self.T2 = self._s16(d1, sensor._T2) self.T3 = self._s16(d1, sensor._T3) self.P1 = self._u16(d1, sensor._P1) self.P2 = self._s16(d1, sensor._P2) self.P3 = self._s16(d1, sensor._P3) self.P4 = self._s16(d1, sensor._P4) self.P5 = self._s16(d1, sensor._P5) self.P6 = self._s16(d1, sensor._P6) self.P7 = self._s16(d1, sensor._P7) self.P8 = self._s16(d1, sensor._P8) self.P9 = self._s16(d1, sensor._P9) self.H1 = self._u8(d1, sensor._H1) c, d2 = self._read_registers(sensor._calib26, 7) self.H2 = self._s16(d2, sensor._H2) self.H3 = self._u8(d2, sensor._H3) t = self._u8(d2, sensor._xE5) t_l = t & 15 t_h = (t >> 4) & 15 self.H4 = (self._u8(d2, sensor._xE4) << 4) | t_l if self.H4 > 2047: self.H4 -= 4096 self.H5 = (self._u8(d2, sensor._xE6) << 4) | t_h if self.H5 > 2047: self.H5 -= 4096 self.H6 = self._s8(d2, sensor._H6) def _read_raw_data(self): # Set oversampling rate and force reading. self._write_registers( [sensor._ctrl_hum, self.sampling, sensor._ctrl_meas, self.sampling << 5 | self.sampling << 2 | 1]) # Measurement delay. time.sleep(self.measure_delay) # Grab reading. c, d = self._read_registers(sensor._rawdata, 8) msb = self._u8(d, sensor._t_msb) lsb = self._u8(d, sensor._t_lsb) xlsb = self._u8(d, sensor._t_xlsb) raw_t = ((msb << 16) | (lsb << 8) | xlsb) >> 4 msb = self._u8(d, sensor._p_msb) lsb = self._u8(d, sensor._p_lsb) xlsb = self._u8(d, sensor._p_xlsb) raw_p = ((msb << 16) | (lsb << 8) | xlsb) >> 4 msb = self._u8(d, sensor._h_msb) lsb = self._u8(d, sensor._h_lsb) raw_h = (msb << 8) | lsb return raw_t, raw_p, raw_h def read_data(self): """ Returns the temperature, pressure, and humidity as a tuple. Each value is a float. The temperature is returned in degrees centigrade. The pressure is returned in Pascals. The humidity is returned as the relative humidity between 0 and 100%. """ raw_t, raw_p, raw_h = self._read_raw_data() var1 = (raw_t/16384.0 - (self.T1)/1024.0) * float(self.T2) var2 = (((raw_t)/131072.0 - (self.T1)/8192.0) * ((raw_t)/131072.0 - (self.T1)/8192.0)) * (self.T3) self.t_fine = var1 + var2 t = (var1 + var2) / 5120.0 var1 = (self.t_fine/2.0) - 64000.0 var2 = var1 * var1 * self.P6 / 32768.0 var2 = var2 + (var1 * self.P5 * 2.0) var2 = (var2/4.0)+(self.P4 * 65536.0) var1 = ((self.P3 * var1 * var1 / 524288.0) + (self.P2 * var1)) / 524288.0 var1 = (1.0 + var1 / 32768.0)*self.P1 if var1 != 0.0: p = 1048576.0 - raw_p p = (p - (var2 / 4096.0)) * 6250.0 / var1 var1 = self.P9 * p * p / 2147483648.0 var2 = p * self.P8 / 32768.0 p = p + (var1 + var2 + self.P7) / 16.0 else: p = 0 h = self.t_fine - 76800.0 h = ( (raw_h - ((self.H4) * 64.0 + (self.H5) / 16384.0 * h)) * ((self.H2) / 65536.0 * (1.0 + (self.H6) / 67108864.0 * h * (1.0 + (self.H3) / 67108864.0 * h)))) h = h * (1.0 - self.H1 * h / 524288.0) if h > 100.0: h = 100.0 elif h < 0.0: h = 0.0 return t, p, h def cancel(self): """ Cancels the sensor and releases resources. """ if self.h is not None: self.pi.i2c_close(self.h) self.h = None if __name__ == "__main__": # import time import BME280 import pigpio pi = pigpio.pi() if not pi.connected: exit(0) s = BME280.sensor(pi) t, p, h = s.read_data() print("h={:.2f} p={:.1f} t={:.2f}".format(h, p/100.0, t), flush=True) # stop = time.time() + 60 # while stop > time.time(): # t, p, h = s.read_data() # print("h={:.2f} p={:.1f} t={:.2f}".format(h, p/100.0, t)) # time.sleep(0.9) s.cancel() pi.stop()