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.py

    import 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))
    
    

    boot.py no data
    main.py

    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 strange

    Thanks 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


Log in to reply
 

Pycom on Twitter