/ adafruit_am2320.py
adafruit_am2320.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2018 Limor Fried 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 """ 23 `adafruit_am2320` 24 ==================================================== 25 26 This is a CircuitPython driver for the AM2320 temperature and humidity sensor. 27 28 * Author(s): Limor Fried 29 30 Implementation Notes 31 -------------------- 32 33 **Hardware:** 34 35 * Adafruit `AM2320 Temperature & Humidity Sensor 36 <https://www.adafruit.com/product/3721>`_ (Product ID: 3721) 37 38 **Software and Dependencies:** 39 40 * Adafruit CircuitPython firmware for the ESP8622 and M0-based boards: 41 https://github.com/adafruit/circuitpython/releases 42 * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice 43 44 """ 45 46 # imports 47 try: 48 import struct 49 except ImportError: 50 import ustruct as struct 51 52 import time 53 54 from adafruit_bus_device.i2c_device import I2CDevice 55 from micropython import const 56 57 __version__ = "0.0.0-auto.0" 58 __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_am2320.git" 59 60 61 AM2320_DEFAULT_ADDR = const(0x5C) 62 AM2320_CMD_READREG = const(0x03) 63 AM2320_REG_TEMP_H = const(0x02) 64 AM2320_REG_HUM_H = const(0x00) 65 66 67 def _crc16(data): 68 crc = 0xFFFF 69 for byte in data: 70 crc ^= byte 71 for _ in range(8): 72 if crc & 0x0001: 73 crc >>= 1 74 crc ^= 0xA001 75 else: 76 crc >>= 1 77 return crc 78 79 80 class AM2320: 81 """A driver for the AM2320 temperature and humidity sensor. 82 83 :param i2c_bus: The `busio.I2C` object to use. This is the only required parameter. 84 :param int address: (optional) The I2C address of the device. 85 86 """ 87 88 def __init__(self, i2c_bus, address=AM2320_DEFAULT_ADDR): 89 for _ in range(3): 90 # retry since we have to wake up the devices 91 try: 92 self._i2c = I2CDevice(i2c_bus, address) 93 return 94 except ValueError: 95 pass 96 time.sleep(0.25) 97 raise ValueError("AM2320 not found") 98 99 def _read_register(self, register, length): 100 with self._i2c as i2c: 101 # wake up sensor 102 try: 103 i2c.write(bytes([0x00])) 104 except OSError: 105 pass 106 time.sleep(0.01) # wait 10 ms 107 108 # Send command to read register 109 cmd = [AM2320_CMD_READREG, register & 0xFF, length] 110 # print("cmd: %s" % [hex(i) for i in cmd]) 111 i2c.write(bytes(cmd)) 112 time.sleep(0.002) # wait 2 ms for reply 113 result = bytearray(length + 4) # 2 bytes pre, 2 bytes crc 114 i2c.readinto(result) 115 # print("$%02X => %s" % (register, [hex(i) for i in result])) 116 # Check preamble indicates correct readings 117 if result[0] != 0x3 or result[1] != length: 118 raise RuntimeError("I2C read failure") 119 # Check CRC on all but last 2 bytes 120 crc1 = struct.unpack("<H", bytes(result[-2:]))[0] 121 crc2 = _crc16(result[0:-2]) 122 if crc1 != crc2: 123 raise RuntimeError("CRC failure 0x%04X vs 0x%04X" % (crc1, crc2)) 124 return result[2:-2] 125 126 @property 127 def temperature(self): 128 """The measured temperature in celsius.""" 129 temperature = struct.unpack(">H", self._read_register(AM2320_REG_TEMP_H, 2))[0] 130 if temperature >= 32768: 131 temperature = 32768 - temperature 132 return temperature / 10.0 133 134 @property 135 def relative_humidity(self): 136 """The measured relative humidity in percent.""" 137 humidity = struct.unpack(">H", self._read_register(AM2320_REG_HUM_H, 2))[0] 138 return humidity / 10.0