Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    Adafruit BME280 & Sipy

    Scheduled Pinned Locked Moved SiPy
    3 Posts 2 Posters 49 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • E Offline
      ecabanas
      last edited by

      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-hhR 1 Reply Last reply Reply Quote 0
      • robert-hhR Offline
        robert-hh @ecabanas
        last edited by robert-hh

        @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

        E 1 Reply Last reply Reply Quote 0
        • E Offline
          ecabanas @robert-hh
          last edited by

          @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

          1 Reply Last reply Reply Quote 0

          Hello! It looks like you're interested in this conversation, but you don't have an account yet.

          Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

          With your input, this post could be even better 💗

          Register Login
          • 1 / 1
          • First post
            Last post

          Pycom on Twitter

          Pycom