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

    AttributeError: 'I2C' object has no attribute '__exit__'

    Scheduled Pinned Locked Moved LoPy
    lopy4 htu21d
    3 Posts 2 Posters 474 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.
    • D Offline
      dnear1
      last edited by

      I'm trying to port Adafruit's micropython code for the HTU21D sensor to work in Pycom. I took the code and tried to modify some of the parameters to match what I have working from other library files, like for the MPA3115A2 sensor.. but I'm getting this error and can't seem to find info to resolve..
      The code fails with

      Traceback (most recent call last):
        File "main.py",  line 9 in <module>
        File "/flash/lib/htu21d.py", line 71, in __init__
        File"/flash/lib/htu21d.py", line 75, in _command
      AttributeError: 'I2C' object has no attribute '__exit__'
      

      /flash/lib/htu21d.py:

      # The MIT License (MIT)
      #
      # Copyright (c) 2018 ktown for Adafruit Industries
      #
      # Permission is hereby granted, free of charge, to any person obtaining a copy
      # of this software and associated documentation files (the "Software"), to deal
      # in the Software without restriction, including without limitation the rights
      # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      # copies of the Software, and to permit persons to whom the Software is
      # furnished to do so, subject to the following conditions:
      #
      # The above copyright notice and this permission notice shall be included in
      # all copies or substantial portions of the Software.
      #
      # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      # THE SOFTWARE.
      
      """
      `adafruit_htu21d`
      ====================================================
      This is a breakout for the Adafruit HTU21D-F humidity sensor breakout.
      * Author(s): ktown
      Implementation Notes
      --------------------
      **Hardware:**
      * Adafruit `HTU21D-F Temperature & Humidity Sensor Breakout Board
        <https://www.adafruit.com/product/1899>`_ (Product ID: 1899)
      **Software and Dependencies:**
      * Adafruit CircuitPython firmware for the supported boards:
        https://github.com/adafruit/circuitpython/releases
      * Adafruit's Bus Device library:
        https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
      """
      from machine import I2C
      
      
      
      def _crc(data):
          crc = 0
          for byte in data:
              crc ^= byte
              for _ in range(8):
                  if crc & 0x80:
                      crc <<= 1
                      crc ^= 0x131
                  else:
                      crc <<= 1
          return crc
      
      
      class HTU21D:
          HTU21D_I2CADDR=const(0x40)
          HUMIDITY = const(0xf5)
          TEMPERATURE = const(0xf3)
          _RESET = const(0xfe)
          _READ_USER1 = const(0xe7)
          _USER1_VAL = const(0x3a)
          """
          A driver for the HTU21D-F temperature and humidity sensor.
          :param i2c_bus: The `busio.I2C` object to use. This is the only
          required parameter.
          :param int address: (optional) The I2C address of the device.
          """
          def __init__(self, sda = 'P9', scl = 'P10'):
              self.i2c_device = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
              self._command(_RESET)
              self._measurement = 0
      
          def _command(self, command):
              with self.i2c_device as i2c:
                  i2c.writeto_mem(HTU21D_I2CADDR,struct.pack('B', command))
      
          def _data(self):
              data = bytearray(3)
              while True:
                  # While busy, the sensor doesn't respond to reads.
                  try:
                      with self.i2c_device as i2c:
                          i2c.readinto(data)
                          if data[0] != 0xff:  # Check if read succeeded.
                              break
                  except OSError:
                      pass
              value, checksum = struct.unpack('>HB', data)
              if checksum != _crc(data[:2]):
                  raise ValueError("CRC mismatch")
              return value
      
          @property
          def relative_humidity(self):
              """The measured relative humidity in percent."""
              self.measurement(HUMIDITY)
              self._measurement = 0
              return self._data() * 125.0 / 65536.0 - 6.0
      
          @property
          def temperature(self):
              """The measured temperature in degrees Celcius."""
              self.measurement(TEMPERATURE)
              self._measurement = 0
              return self._data() * 175.72 / 65536.0 - 46.85
      
          def measurement(self, what):
              """
              Starts a measurement.
              Starts a measurement of either ``HUMIDITY`` or ``TEMPERATURE``
              depending on the ``what`` argument. Returns immediately, and the
              result of the measurement can be retrieved with the
              ``temperature`` and ``relative_humidity`` properties. This way it
              will take much less time.
              This can be useful if you want to start the measurement, but don't
              want the call to block until the measurement is ready -- for instance,
              when you are doing other things at the same time.
              """
              if what not in (HUMIDITY, TEMPERATURE):
                  raise ValueError()
              if not self._measurement:
                  self._command(what)
              elif self._measurement != what:
                  raise RuntimeError("other measurement in progress")
              self._measurement = what
      

      /main.py:

      from htu21d import HTU21D
       
      # Create library object using our Bus I2C port
      #i2c = busio.I2C(board.SCL, board.SDA)
      #from machine import I2C, Pin
      #i2c = I2C(0, pins=("P9","P10"))
      #i2c.init(I2C.MASTER, baudrate=9600)
      
      sensor = HTU21D()
      
      print("\nTemperature: %0.1f C" % sensor.temperature)
      print("Humidity: %0.1f %%" % sensor.relative_humidity)
      
      robert-hhR 1 Reply Last reply Reply Quote 0
      • robert-hhR Offline
        robert-hh @dnear1
        last edited by

        @dnear1 This is caused by the I2C call in a with statement. Remove with, then it works.

        1 Reply Last reply Reply Quote 0
        • D Offline
          dnear1
          last edited by dnear1

          Thanks!
          After clearing that error, I ran into several more.
          This is what I ended up with when I got it working finally
          /flash/lib/htu21d.py:

          # The MIT License (MIT)
          #
          # Copyright (c) 2018 ktown for Adafruit Industries
          #
          # Permission is hereby granted, free of charge, to any person obtaining a copy
          # of this software and associated documentation files (the "Software"), to deal
          # in the Software without restriction, including without limitation the rights
          # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
          # copies of the Software, and to permit persons to whom the Software is
          # furnished to do so, subject to the following conditions:
          #
          # The above copyright notice and this permission notice shall be included in
          # all copies or substantial portions of the Software.
          #
          # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
          # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
          # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
          # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
          # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
          # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
          # THE SOFTWARE.
          
          """
          `adafruit_htu21d`
          ====================================================
          This is a breakout for the Adafruit HTU21D-F humidity sensor breakout.
          * Author(s): ktown
          Implementation Notes
          --------------------
          **Hardware:**
          * Adafruit `HTU21D-F Temperature & Humidity Sensor Breakout Board
            <https://www.adafruit.com/product/1899>`_ (Product ID: 1899)
          **Software and Dependencies:**
          * Adafruit CircuitPython firmware for the supported boards:
            https://github.com/adafruit/circuitpython/releases
          * Adafruit's Bus Device library:
            https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
          """
          from machine import I2C
          import struct
          HTU21D_I2CADDR=const(0x40)
          HUMIDITY = const(0xf5)
          TEMPERATURE = const(0xf3)
          _RESET = const(0xfe)
          _READ_USER1 = const(0xe7)
          _USER1_VAL = const(0x3a)
          
          
          def _crc(data):
              crc = 0
              for byte in data:
                  crc ^= byte
                  for _ in range(8):
                      if crc & 0x80:
                          crc <<= 1
                          crc ^= 0x131
                      else:
                          crc <<= 1
              return crc
          
          
          class HTU21D:
              #HTU21D_I2CADDR=const(0x40)
              #HUMIDITY = const(0xf5)
              #TEMPERATURE = const(0xf3)
              #_RESET = const(0xfe)
              #_READ_USER1 = const(0xe7)
              #_USER1_VAL = const(0x3a)
              """
              A driver for the HTU21D-F temperature and humidity sensor.
              :param i2c_bus: The `busio.I2C` object to use. This is the only
              required parameter.
              :param int address: (optional) The I2C address of the device.
              """
              def __init__(self, sda = 'P9', scl = 'P10'):
                  self.i2c_device = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
                  self._command(_RESET)
                  self._measurement = 0
                  self.addr = HTU21D_I2CADDR
          
              def _command(self, command):
                  #with self.i2c_device as i2c:
                  self.i2c_device.writeto(HTU21D_I2CADDR, command)
          
              def _data(self):
                  data = bytearray(3)
                  while True:
                      # While busy, the sensor doesn't respond to reads.
                      try:
                          #with self.i2c_device as i2c:
                         self.i2c_device.readfrom_into(self.addr, data)
                         if data[0] != 0xff:  # Check if read succeeded.
                             break
                      except OSError:
                          pass
                  value,checksum=struct.unpack('>HB',data)
                  if checksum != _crc(data[:2]):
                      raise ValueError('CRC mismatch:'+data+':'+checksum+':')
                  return value
          
              @property
              def relative_humidity(self):
                  """The measured relative humidity in percent."""
                  self.measurement(HUMIDITY)
                  self._measurement = 0
                  return self._data() * 125.0 / 65536.0 - 6.0
          
              @property
              def temperature(self):
                  """The measured temperature in degrees Celcius."""
                  self.measurement(TEMPERATURE)
                  self._measurement = 0
                  return self._data() * 175.72 / 65536.0 - 46.85
          
              def measurement(self, what):
                  """
                  Starts a measurement.
                  Starts a measurement of either ``HUMIDITY`` or ``TEMPERATURE``
                  depending on the ``what`` argument. Returns immediately, and the
                  result of the measurement can be retrieved with the
                  ``temperature`` and ``relative_humidity`` properties. This way it
                  will take much less time.
                  This can be useful if you want to start the measurement, but don't
                  want the call to block until the measurement is ready -- for instance,
                  when you are doing other things at the same time.
                  """
                  if what not in (HUMIDITY, TEMPERATURE):
                      raise ValueError()
                  if not self._measurement:
                      self._command(what)
                  elif self._measurement != what:
                      raise RuntimeError("other measurement in progress")
                  self._measurement = what```
          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