Arduino library · Sensors

Adafruit AHTX0: the AHT20 temperature and humidity sensor

The AHT20 is a small I2C temperature and humidity chip found on many low-cost modules, often sharing a board with a BMP280. Adafruit’s AHTX0 library reads it at its one fixed address, 0x38, and returns two sensors_event_t structs per measurement: one for humidity, one for temperature, in the Unified Sensor style.

Built in on Mokxi: #include <Adafruit_AHTX0.h> and it builds, with nothing to install. Free, and no account needed.

What Adafruit AHTX0 does

Getting a reading out takes a short ritual that the library runs for you. It sends the trigger command, polls the busy bit every 10 ms while the chip works (about 80 ms), then unpacks two 20-bit counts into percent and degrees. begin() also checks the calibrated bit in the status byte and sends the chip’s initialization command when that bit is clear, a step that hand-written drivers often forget.

The DHT20 is an AHT20 inside a DHT-style case and has its own library page for Rob Tillaart’s driver; this page is for sketches written against Adafruit’s calls. In Mokxi the aht20 part takes its values from sliders. The example is the touch climate display: an AHT20 and a 16x2 LCD on the same two wires, and a touch pad that flips between Celsius and Fahrenheit using getTemperatureCentis(), a Mokxi addition that returns hundredths of a degree.

Library Manager nameAdafruit AHTX0
AuthorAdafruit
Include#include <Adafruit_AHTX0.h>
Boardsevery board Mokxi compiles for but ATtiny85
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesHumidity sensor, AHT20

Install it

It builds on every board Mokxi compiles for but ATtiny85.

In Mokxi it is built in: #include <Adafruit_AHTX0.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "Adafruit AHTX0" by Adafruit from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add Adafruit AHTX0 to lib_deps in PlatformIO. Mokxi follows the calls of release 2.0.6, so a sketch written here builds there too.

The calls you will use

In the order a sketch meets them.

Adafruit_AHTX0 aht

Creates the driver. Unlike most Adafruit drivers, the bus and the address are passed to begin(), not the constructor.

aht.begin()

Waits out the power-up time, resets the chip and makes sure it is calibrated. Returns false when nothing answers at 0x38. aht.begin(&Wire1) uses a second bus.

aht.getEvent(&humidity, &temp)

Takes one measurement and fills both events: humidity.relative_humidity in percent and temp.temperature in degrees Celsius. Either pointer may be NULL.

sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);
Serial.print(temp.temperature);
Serial.println(" C");

aht.getStatus()

The raw status byte: bit 7 is busy and bit 3 is calibrated. 0xFF means the chip did not reply.

aht.getTemperatureSensor()

An Adafruit_Sensor for temperature alone, for code that wants one getEvent(&event) per value. getHumiditySensor() is the other half; each takes its own measurement.

aht.getTemperatureCentis()

Mokxi’s own: the last measurement in hundredths of a degree, for sums without floats. getHumidityCentis() does the same for humidity. The upstream library has neither.

Example: Touch climate display

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino · Arduino Uno R3
// Touch climate display: an AHT20 temperature and humidity sensor and a 16x2
// LCD on the same two I2C wires, and a TTP223 touch pad that switches the
// temperature between Celsius and Fahrenheit.
//
//   A4, A5  SDA and SCL, to the AHT20 (0x38); the LCD backpack (0x27) is on
//           the header's other SDA and SCL, which are the same two wires
//   pin 2   the TTP223's SIG: high while a finger is on the pad
//   power   the AHT20 on 5V, the LCD on IOREF (also 5 V), the TTP223 on 3V3:
//           its 3.3 V high is still a HIGH to a 5 V Uno
//
// Two I2C devices on one pair of wires is what the bus is for: each answers
// only its own address. The AHT20 module and the backpack both carry
// pull-ups, which is normal and harmless.
//
// # The sensor
//
// Adafruit_AHTX0.h asks the AHT20 for a reading and waits the 80 ms the chip
// takes to make one. The sketch then takes the numbers in hundredths
// (getTemperatureCentis and getHumidityCentis), because Fahrenheit is a sum
// and there is no floating point on this board:
//
//   F x 100 = C x 100 x 9 / 5 + 3200
//
// # The touch pad
//
// The TTP223 needs no pull-up and does not bounce: SIG is a real output,
// high while touched. It takes up to 60 ms to decide, and it ignores the pad
// for the first half second after power comes up. The sketch flips the units
// on the rising edge, so holding a finger there flips them once.
//
// Everything is on the display and nothing goes to the serial monitor: the
// sensor library, two I2C drivers and the LCD font fill most of the 8 KB an
// example is allowed.

#include <Adafruit_AHTX0.h>
#include "mokxi_lcd1602_i2c.h"

const int TOUCH = 2;

Adafruit_AHTX0 aht;
Lcd1602I2c lcd(A5, A4);

bool fahrenheit = false;
bool wasTouched = false;

/** Hundredths to tenths, rounded half away from zero. */
int tenthsOf(long centis) {
  return (int)((centis >= 0 ? centis + 5 : centis - 5) / 10);
}


void show() {
  sensors_event_t humidity, temp;
  if (!aht.getEvent(&humidity, &temp)) {
    lcd.setCursor(0, 0);
    lcd.print("sensor?");
    lcd.padLine();
    return;
  }
  long c = aht.getTemperatureCentis();
  int shown = tenthsOf(fahrenheit ? c * 9 / 5 + 3200 : c);
  int rh = (int)((aht.getHumidityCentis() + 50) / 100);

  lcd.setCursor(0, 0);
  lcd.print("Temp  ");
  lcd.printFixed(shown, 1);
  lcd.print(fahrenheit ? " F" : " C");
  lcd.padLine();
  lcd.setCursor(0, 1);
  lcd.print("Humid ");
  lcd.print(rh);
  lcd.print(" %");
  lcd.padLine();
}

void setup() {
  pinMode(TOUCH, INPUT);
  lcd.begin();
  lcd.print("Mokxi climate");
  if (!aht.begin()) {
    lcd.setCursor(0, 1);
    lcd.print("no AHT20");
    while (true) {
      delay(100);
    }
  }
  delay(400);
  lcd.clear();
}

void loop() {
  bool touched = digitalRead(TOUCH) == HIGH;
  bool flipped = touched && !wasTouched;
  wasTouched = touched;
  if (flipped) {
    fahrenheit = !fahrenheit;
  }

  static unsigned long last = 0;
  if (flipped || millis() - last >= 500) {
    last = millis();
    show();
  }
  delay(20);
}

Open it in the editor, wired and ready to run · Touch climate display: the project page

Common errors and how to fix them

Could not find AHT

Nothing replied at 0x38 within half a second. Check the two bus wires and the supply; on a combined AHT20 and BMP280 board both chips hang off the same pins, so a scanner should list two addresses.

error: 'class Adafruit_AHTX0' has no member named 'readTemperature'

That call comes from the DHT and SHT31 libraries. AHTX0 reads through getEvent() only, so declare two sensors_event_t variables and read their fields.

The humidity shown never moves while the temperature does

The sketch is printing a field from the wrong event, often temp twice. Read relative_humidity from the humidity event and temperature from the temp event after a single getEvent().

Questions and answers

Can two AHT20 sensors share one I2C bus?

Not directly: the address is fixed at 0x38. Put the second one on another bus with begin(&Wire1) where the board has one, or behind an I2C multiplexer.

Why does the touch climate project use hundredths instead of floats?

The sensor library, two I2C drivers and the LCD font fill most of the flash an Uno example has, so the sketch does its Fahrenheit sum in whole numbers from getTemperatureCentis().

Projects that use Adafruit AHTX0

Built-in projects that include it. Each page has the full sketch and opens in the editor, already wired.

Try Adafruit AHTX0 without installing anything

Open the example, change the sketch, and keep your version in a free account.