diff --git a/aht20/ahtx0.py b/aht20/ahtx0.py new file mode 100644 index 0000000..7f09459 --- /dev/null +++ b/aht20/ahtx0.py @@ -0,0 +1,121 @@ +# The MIT License (MIT) +# +# Copyright (c) 2020 Kattni Rembor for Adafruit Industries +# Copyright (c) 2020 Andreas Bühl +# +# 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. +""" + +MicroPython driver for the AHT10 and AHT20 Humidity and Temperature Sensor + +Author(s): Andreas Bühl, Kattni Rembor + +""" + +import utime +from micropython import const + + +class AHT10: + """Interface library for AHT10/AHT20 temperature+humidity sensors""" + + AHTX0_I2CADDR_DEFAULT = const(0x38) # Default I2C address + AHTX0_CMD_INITIALIZE = 0xE1 # Initialization command + AHTX0_CMD_TRIGGER = const(0xAC) # Trigger reading command + AHTX0_CMD_SOFTRESET = const(0xBA) # Soft reset command + AHTX0_STATUS_BUSY = const(0x80) # Status bit for busy + AHTX0_STATUS_CALIBRATED = const(0x08) # Status bit for calibrated + + def __init__(self, i2c, address=AHTX0_I2CADDR_DEFAULT): + utime.sleep_ms(20) # 20ms delay to wake up + self._i2c = i2c + self._address = address + self._buf = bytearray(6) + self.reset() + if not self.initialize(): + raise RuntimeError("Could not initialize") + self._temp = None + self._humidity = None + + def reset(self): + """Perform a soft-reset of the AHT""" + self._buf[0] = self.AHTX0_CMD_SOFTRESET + self._i2c.writeto(self._address, self._buf[0:1]) + utime.sleep_ms(20) # 20ms delay to wake up + + def initialize(self): + """Ask the sensor to self-initialize. Returns True on success, False otherwise""" + self._buf[0] = self.AHTX0_CMD_INITIALIZE + self._buf[1] = 0x08 + self._buf[2] = 0x00 + self._i2c.writeto(self._address, self._buf[0:3]) + self._wait_for_idle() + if not self.status & self.AHTX0_STATUS_CALIBRATED: + return False + return True + + @property + def status(self): + """The status byte initially returned from the sensor, see datasheet for details""" + self._read_to_buffer() + return self._buf[0] + + @property + def relative_humidity(self): + """The measured relative humidity in percent.""" + self._perform_measurement() + self._humidity = ( + (self._buf[1] << 12) | (self._buf[2] << 4) | (self._buf[3] >> 4) + ) + self._humidity = (self._humidity * 100) / 0x100000 + return self._humidity + + @property + def temperature(self): + """The measured temperature in degrees Celcius.""" + self._perform_measurement() + self._temp = ((self._buf[3] & 0xF) << 16) | (self._buf[4] << 8) | self._buf[5] + self._temp = ((self._temp * 200.0) / 0x100000) - 50 + return self._temp + + def _read_to_buffer(self): + """Read sensor data to buffer""" + self._i2c.readfrom_into(self._address, self._buf) + + def _trigger_measurement(self): + """Internal function for triggering the AHT to read temp/humidity""" + self._buf[0] = self.AHTX0_CMD_TRIGGER + self._buf[1] = 0x33 + self._buf[2] = 0x00 + self._i2c.writeto(self._address, self._buf[0:3]) + + def _wait_for_idle(self): + """Wait until sensor can receive a new command""" + while self.status & self.AHTX0_STATUS_BUSY: + utime.sleep_ms(5) + + def _perform_measurement(self): + """Trigger measurement and write result to buffer""" + self._trigger_measurement() + self._wait_for_idle() + self._read_to_buffer() + + +class AHT20(AHT10): + AHTX0_CMD_INITIALIZE = 0xBE # Calibration command diff --git a/aht20/main.py b/aht20/main.py new file mode 100644 index 0000000..ce2032c --- /dev/null +++ b/aht20/main.py @@ -0,0 +1,22 @@ +import time +from machine import Pin, I2C + +import ahtx0 + +I2C_A = I2C(scl=Pin(1), sda=Pin(2)) + +# Create the sensor object using I2C +sensor = ahtx0.AHT10(I2C_A) + + +def celsius_to_fahrenheit(celsius: float): + return (celsius * (9 / 5)) + 32 + + +while True: + temp_c = sensor.temperature + temf_f = celsius_to_fahrenheit(temp_c) + raw_humidity = sensor.relative_humidity + print("\nTemperature: {:.2f} C / {:.2f} F".format(temp_c, temf_f)) + print("Humidity: {:.2f} %".format(raw_humidity)) + time.sleep(5) diff --git a/requirements.in b/requirements.in index 96890b1..cd0ccb3 100644 --- a/requirements.in +++ b/requirements.in @@ -2,4 +2,5 @@ pip-tools esptool adafruit-ampy docopt -black \ No newline at end of file +black +mpremote \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 7c1d232..948efef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,22 +1,72 @@ # -# This file is autogenerated by pip-compile -# To update, run: +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: # # pip-compile requirements.in # ---trusted-host pypi.python.org - -adafruit-ampy==1.0.7 -appdirs==1.4.3 # via black -attrs==19.1.0 # via black -black==18.9b0 -click==7.0 # via adafruit-ampy, black, pip-tools +adafruit-ampy==1.1.0 + # via -r requirements.in +bitarray==2.9.2 + # via bitstring +bitstring==4.2.3 + # via esptool +black==24.8.0 + # via -r requirements.in +build==1.2.1 + # via pip-tools +cffi==1.17.0 + # via cryptography +click==8.1.7 + # via + # adafruit-ampy + # black + # pip-tools +cryptography==43.0.0 + # via esptool docopt==0.6.2 -ecdsa==0.13 # via esptool -esptool==2.6 -pip-tools==3.4.0 -pyaes==1.6.1 # via esptool -pyserial==3.4 # via adafruit-ampy, esptool -python-dotenv==0.10.1 # via adafruit-ampy -six==1.12.0 # via pip-tools -toml==0.10.0 # via black + # via -r requirements.in +ecdsa==0.19.0 + # via esptool +esptool==4.7.0 + # via -r requirements.in +intelhex==2.3.0 + # via esptool +mpremote==1.23.0 + # via -r requirements.in +mypy-extensions==1.0.0 + # via black +packaging==24.1 + # via + # black + # build +pathspec==0.12.1 + # via black +pip-tools==7.4.1 + # via -r requirements.in +platformdirs==4.2.2 + # via black +pycparser==2.22 + # via cffi +pyproject-hooks==1.1.0 + # via + # build + # pip-tools +pyserial==3.5 + # via + # adafruit-ampy + # esptool + # mpremote +python-dotenv==1.0.1 + # via adafruit-ampy +pyyaml==6.0.2 + # via esptool +reedsolo==1.7.0 + # via esptool +six==1.16.0 + # via ecdsa +wheel==0.44.0 + # via pip-tools + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/requirements.txt.bak b/requirements.txt.bak new file mode 100644 index 0000000..7c1d232 --- /dev/null +++ b/requirements.txt.bak @@ -0,0 +1,22 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +--trusted-host pypi.python.org + +adafruit-ampy==1.0.7 +appdirs==1.4.3 # via black +attrs==19.1.0 # via black +black==18.9b0 +click==7.0 # via adafruit-ampy, black, pip-tools +docopt==0.6.2 +ecdsa==0.13 # via esptool +esptool==2.6 +pip-tools==3.4.0 +pyaes==1.6.1 # via esptool +pyserial==3.4 # via adafruit-ampy, esptool +python-dotenv==0.10.1 # via adafruit-ampy +six==1.12.0 # via pip-tools +toml==0.10.0 # via black