Adafruit BME280 & Sipy
-
Hi all
I'm new with this board and I trying to move all my project made in arduino to pycom siPy. But I'm triying to learn and overall read the sensors to build new project.
Now I'm triying to read Adafruit BME280 or DFRobot BME280. See all what I did, and did not work:
SiPy Firmware 1.20.2.r1
Library BME280.pyimport time from ustruct import unpack, unpack_from from array import array # BME280 default address. BME280_I2CADDR = 0x77 # Operating Modes BME280_OSAMPLE_1 = 1 BME280_OSAMPLE_2 = 2 BME280_OSAMPLE_4 = 3 BME280_OSAMPLE_8 = 4 BME280_OSAMPLE_16 = 5 BME280_REGISTER_CONTROL_HUM = 0xF2 BME280_REGISTER_STATUS = 0xF3 BME280_REGISTER_CONTROL = 0xF4 MODE_SLEEP = const(0) MODE_FORCED = const(1) MODE_NORMAL = const(3) class BME280: def __init__(self, mode=BME280_OSAMPLE_8, address=BME280_I2CADDR, i2c=None, **kwargs): # Check that mode is valid. if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, BME280_OSAMPLE_8, BME280_OSAMPLE_16]: raise ValueError( 'Unexpected mode value {0}. Set mode to one of ' 'BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4,' 'BME280_OSAMPLE_8, BME280_OSAMPLE_16'.format(mode)) self._mode = mode self.address = address if i2c is None: raise ValueError('An I2C object is required.') self.i2c = i2c self.__sealevel = 101325 # load calibration data dig_88_a1 = self.i2c.readfrom_mem(self.address, 0x88, 26) dig_e1_e7 = self.i2c.readfrom_mem(self.address, 0xE1, 7) self.dig_T1, self.dig_T2, self.dig_T3, self.dig_P1, \ self.dig_P2, self.dig_P3, self.dig_P4, self.dig_P5, \ self.dig_P6, self.dig_P7, self.dig_P8, self.dig_P9, \ _, self.dig_H1 = unpack("<HhhHhhhhhhhhBB", dig_88_a1) self.dig_H2, self.dig_H3, self.dig_H4,\ self.dig_H5, self.dig_H6 = unpack("<hBbhb", dig_e1_e7) # unfold H4, H5, keeping care of a potential sign self.dig_H4 = (self.dig_H4 * 16) + (self.dig_H5 & 0xF) self.dig_H5 //= 16 self.t_fine = 0 # temporary data holders which stay allocated self._l1_barray = bytearray(1) self._l8_barray = bytearray(8) self._l3_resultarray = array("i", [0, 0, 0]) self._l1_barray[0] = self._mode << 5 | self._mode << 2 | MODE_SLEEP self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL, bytearray([0x3c | MODE_SLEEP])) def read_raw_data(self, result): """ Reads the raw (uncompensated) data from the sensor. Args: result: array of length 3 or alike where the result will be stored, in temperature, pressure, humidity order Returns: None """ self._l1_barray[0] = self._mode self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL_HUM, self._l1_barray) self._l1_barray[0] = self._mode << 5 | self._mode << 2 | MODE_FORCED self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL, self._l1_barray) # Wait for conversion to complete while self.i2c.readfrom_mem(self.address, BME280_REGISTER_STATUS, 1)[0] & 0x08: time.sleep_ms(10) # burst readout from 0xF7 to 0xFE, recommended by datasheet self.i2c.readfrom_mem_into(self.address, 0xF7, self._l8_barray) readout = self._l8_barray # pressure(0xF7): ((msb << 16) | (lsb << 8) | xlsb) >> 4 raw_press = ((readout[0] << 16) | (readout[1] << 8) | readout[2]) >> 4 # temperature(0xFA): ((msb << 16) | (lsb << 8) | xlsb) >> 4 raw_temp = ((readout[3] << 16) | (readout[4] << 8) | readout[5]) >> 4 # humidity(0xFD): (msb << 8) | lsb raw_hum = (readout[6] << 8) | readout[7] result[0] = raw_temp result[1] = raw_press result[2] = raw_hum def read_compensated_data(self, result=None): """ Reads the data from the sensor and returns the compensated data. Args: result: array of length 3 or alike where the result will be stored, in temperature, pressure, humidity order. You may use this to read out the sensor without allocating heap memory Returns: array with temperature, pressure, humidity. Will be the one from the result parameter if not None """ self.read_raw_data(self._l3_resultarray) raw_temp, raw_press, raw_hum = self._l3_resultarray # temperature var1 = (((raw_temp // 8) - (self.dig_T1 * 2)) * self.dig_T2) // 2048 var2 = (raw_temp // 16) - self.dig_T1 var2 = (((var2 * var2) // 4096) * self.dig_T3) // 16384 self.t_fine = var1 + var2 temp = (self.t_fine * 5 + 128) // 256 # pressure var1 = self.t_fine - 128000 var2 = var1 * var1 * self.dig_P6 var2 = var2 + ((var1 * self.dig_P5) << 17) var2 = var2 + (self.dig_P4 << 35) var1 = (((var1 * var1 * self.dig_P3) >> 8) + ((var1 * self.dig_P2) << 12)) var1 = (((1 << 47) + var1) * self.dig_P1) >> 33 if var1 == 0: pressure = 0 else: p = ((((1048576 - raw_press) << 31) - var2) * 3125) // var1 var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25 var2 = (self.dig_P8 * p) >> 19 pressure = ((p + var1 + var2) >> 8) + (self.dig_P7 << 4) # humidity h = self.t_fine - 76800 h = (((((raw_hum << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) + 16384) >> 15) * (((((((h * self.dig_H6) >> 10) * (((h * self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) * self.dig_H2 + 8192) >> 14)) h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4) h = 0 if h < 0 else h h = 419430400 if h > 419430400 else h humidity = h >> 12 if result: result[0] = temp result[1] = pressure result[2] = humidity return result return array("i", (temp, pressure, humidity)) @property def sealevel(self): return self.__sealevel @sealevel.setter def sealevel(self, value): if 300 < value < 1200: # just ensure some reasonable value self.__sealevel = value @property def altitude(self): ''' Altitude in m. ''' from math import pow try: p = 44330 * (1.0 - pow((self.read_compensated_data()[1] / 256) / self.__sealevel, 0.1903)) except: p = 0.0 return p @property def dew_point(self): """ Compute the dew point temperature for the current Temperature and Humidity measured pair """ from math import log t, p, h = self.read_compensated_data() t /= 100 h /= 1024 h = (log(h, 10) - 2) / 0.4343 + (17.62 * t) / (243.12 + t) return (243.12 * h / (17.62 - h)) * 100 @property def values(self): """ human readable values """ t, p, h = self.read_compensated_data() p = p / 256 h = h / 1024 return ("{}C".format(t / 100), "{:.02f}hPa".format(p/100), "{:.02f}%".format(h))
from machine import I2C import bme280 i2c = I2C(0,I2C.MASTER, baudrate=100000) bme = bme280.BME280(address=BME280_I2CADDR, i2c=i2c) print('Temp = ', bme.temperature())
But the error is:
Traceback (most recent call last): File "main.py", line 4, in <module> NameError: name 'BME280_I2CADDR' isn't defined
Anybody knows what is happening?
Thank's
Eduard
-
@robert-hh
I just applied the configuration from the library and now it works. I'm using Adafruit and DFrobot BME280 and changing the address to 77 they work perfect, Dew point only works on adafruit , very strangeThanks again for your help
-
@ecabanas said in Adafruit BME280 & Sipy:
bme = bme280.BME280(address=BME280_I2CADDR, i2c=i2c)
You have to write:
bme = bme280.BME280(address=bme280.BME280_I2CADDR, i2c=i2c)
If the I2c address of the board is 0x77, you do not have to specify it, since that is the default address of the library,
Edit: This is the lib that I am using: https://github.com/robert-hh/BME280