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

    Interfacing with AM2320 on FiPy over I2C?

    Scheduled Pinned Locked Moved FiPy
    6 Posts 3 Posters 400 Views 3 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.
    • Z Offline
      zwarcola
      last edited by

      Has anyone had any success using the AM2320 on any of the pycom boards over i2c? I have been trying to interface with one using my FiPy and have only been able to receive errors. I have tried using various micropython libraries including ones by alexmrqt and mcauser. I always get some sort of OSError. I know my sensor works and is wired properly because I have been able to get accurate readings using a Raspberry Pi.

      Here is the code I have to use the alexmrqt library:

      i2c = I2C(0, I2C.MASTER)
      i2c = I2C(0, pins=('P10','P11'))
      i2c.init(I2C.MASTER, baudrate=100000)
      am = AM2320.AM2320(i2c)
      
      while True:
          pycom.rgbled(0x7f0000) # red
          try:
              temp = am.temperature
              humidity = am.relative_humidity
              print([str(temp), str(humidity)])
          except OSError:
              # In case the sensor fails
              print(OSError)
              pass
          except RuntimeError:
              print(RuntimeError)
              pass
          pycom.rgbled(0x007f00) # green
          time.sleep(5)
      

      And here is the driver itself:

      # Driver code for AM2320 temperature and humidity sensor
      
      try:
          import struct
      except ImportError:
          import ustruct as struct
      import time
      from micropython import const
      
      __version__ = "0.0.0-auto.0"
      __repo__ = "https://github.com/alexmrqt/Adafruit_CircuitPython_am2320.git"
      
      _AM2320_DEFAULT_ADDR = const(0x5C)
      _AM2320_CMD_READREG = const(0x03)
      _AM2320_REG_TEMP_H = const(0x02)
      _AM2320_REG_HUM_H = const(0x00)
      
      def _crc16(data):
          crc = 0xffff
          for byte in data:
              crc ^= byte
              for _ in range(8):
                  if crc & 0x0001:
                      crc >>= 1
                      crc ^= 0xA001
                  else:
                      crc >>= 1
          return crc
      
      
      class AM2320:
          """A driver for the AM2320 temperature and humidity sensor.
          :param i2c_bus: The `I2C` object to use. This is the only required parameter.
          :param int address: (optional) The I2C address of the device.
          """
          def __init__(self, i2c_bus, address=_AM2320_DEFAULT_ADDR):
              self._i2c_bus = i2c_bus
              self._addr = address
      
          def _read_register(self, register, length):
              # wake up sensor
              self._i2c_bus.writeto(self._addr, bytes([0x00]))
              time.sleep(0.01)  # wait 10 ms
      
              # Send command to read register
              cmd = [_AM2320_CMD_READREG, register & 0xFF, length]
              # print("cmd: %s" % [hex(i) for i in cmd])
              self._i2c_bus.writeto(self._addr, bytes(cmd))
              time.sleep(0.002)  # wait 2 ms for reply
              result = bytearray(length+4) # 2 bytes pre, 2 bytes crc
              self._i2c_bus.readfrom_into(self._addr, result)
              # print("$%02X => %s" % (register, [hex(i) for i in result]))
              # Check preamble indicates correct readings
              if result[0] != 0x3 or result[1] != length:
                  raise RuntimeError('I2C modbus read failure')
              # Check CRC on all but last 2 bytes
              crc1 = struct.unpack("<H", bytes(result[-2:]))[0]
              crc2 = _crc16(result[0:-2])
              if crc1 != crc2:
                  raise RuntimeError('CRC failure 0x%04X vs 0x%04X' % (crc1, crc2))
              return result[2:-2]
      
          @property
          def temperature(self):
              """The measured temperature in celsius."""
              temperature = struct.unpack(">H", self._read_register(_AM2320_REG_TEMP_H, 2))[0]
              if temperature >= 32768:
                  temperature = 32768 - temperature
              return temperature/10.0
      
          @property
          def relative_humidity(self):
              """The measured relative humidity in percent."""
              humidity = struct.unpack(">H", self._read_register(_AM2320_REG_HUM_H, 2))[0]
              return humidity/10.0
      
      

      I have been searching everywhere but nobody seems to have any info on combining the AM2320 with the pycom boards. Any help would be greatly appreciated!

      robert-hhR 2 Replies Last reply Reply Quote 0
      • robert-hhR Offline
        robert-hh @zwarcola
        last edited by robert-hh

        @zwarcola Do you have added pull-up resistors? If yes, what is the result to i2c.scan()? Does that report the address of the device, which is 92?

        Z 1 Reply Last reply Reply Quote 0
        • robert-hhR Offline
          robert-hh @zwarcola
          last edited by robert-hh

          @zwarcola I see the problem. The call to i2c.init() resets the pin definition. Just drop that call and add baudrate=100000 to the constructor call for i2c, or add pins=() to the init call.
          That's subtle pitfall in the code, for SPI and other interfaces too. The constructor and init() share the same init code, which means, you have to do all initialization in a single call.

          1 Reply Last reply Reply Quote 0
          • Z Offline
            zwarcola @robert-hh
            last edited by

            @robert-hh Hey Robert, sorry for the delayed response. So I have been toying with the i2c sensor a little more. After changing the initialization of the i2c device and adding pull-up resistors, I am still getting a blank list of addresses "[]" and am unable to read values from it either.

            Here is my updated i2c initialization:

            i2c = I2C(0, I2C.MASTER, baudrate=100000, pins=('P10','P11'))
            

            Any ideas?

            robert-hhR 1 Reply Last reply Reply Quote 0
            • robert-hhR Offline
              robert-hh @zwarcola
              last edited by

              @zwarcola No clue, and I cannot test since I do not have that sensor here. Reading the data sheet it seems important, that SCL is pulled high during power up of the device, since that defines, whether the sensor runs in I2C mode or the old Single-Wire mode of the AM2302/DHT11.

              1 Reply Last reply Reply Quote 0
              • tiborrrT Offline
                tiborrr
                last edited by

                Hi, @zwarcola I saw this post and was curious if you managed to find the solution for your problems, or did you just catch the error and then keep going.

                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