Non-blocking Dual AHT10 I2C Sensor Library
This library enables simultaneous, non-blocking reading of up to two AHT10 temperature/humidity sensors at separate I2C addresses (0x38, 0x39). It is compatible with Arduino Uno, ATmega328, ESP32, and other common Arduino platforms.
Most AHT10 modules are shipped with I2C address 0x38 by default. A solder jumper (resistor) on the back can be moved to change the address to 0x39. This allows two sensors to be used on the same bus.
- Arduino Uno, Nano, Pro Mini (ATmega328)
- ESP32 (tested with ESP32 DevKit)
- Other Arduino-compatible boards with I2C
The update() method returns a status byte:
- Lower nibble: Status of sensor 0 (address 0x38)
- Upper nibble: Status of sensor 1 (address 0x39)
Status codes (nibble):
- 0 = Absent (not found)
- 1 = Idle (ready, no new value)
- 3 = Busy (measurement in progress)
- 5 = Ready (new value available)
- 9 = Error (error)
Example: 0x55 means both sensors are ready and provide valid values.
- Place the library in
lib/Dual_AHT10or install via PlatformIO/Arduino Library Manager.
#include <Wire.h>
#include "Dual_AHT10.h"
Dual_AHT10 aht;
void setup() {
Serial.begin(115200);
Wire.begin();
aht.init(0x38); // Only one sensor at 0x38
}
void loop() {
uint8_t status = aht.update();
if (Dual_AHT10::getState0(status) == Dual_AHT10::Ready) {
Serial.print("Temp: "); Serial.print(aht.getTemp0());
Serial.print(" °C, RH: "); Serial.print(aht.getHum0());
Serial.print(" %, Dew Point: "); Serial.print(aht.getDewPoint0());
Serial.println(" °C");
delay(1000);
}
}Works on Arduino Uno and ESP32 (with the appropriate Wire.begin() signature).
#include <Wire.h>
#include "Dual_AHT10.h"
Dual_AHT10 aht;
void setup() {
Serial.begin(115200);
Wire.begin();
aht.init(0x38, 0x39); // Two sensors
}
void loop() {
uint8_t status = aht.update();
if (Dual_AHT10::getState0(status) == Dual_AHT10::Ready) {
Serial.print("[0x38] Temp: "); Serial.print(aht.getTemp0());
Serial.print(" °C, RH: "); Serial.print(aht.getHum0());
Serial.print(" %, Dew Point: "); Serial.print(aht.getDewPoint0());
Serial.println(" °C");
}
if (Dual_AHT10::getState1(status) == Dual_AHT10::Ready) {
Serial.print("[0x39] Temp: "); Serial.print(aht.getTemp1());
Serial.print(" °C, RH: "); Serial.print(aht.getHum1());
Serial.print(" %, Dew Point: "); Serial.print(aht.getDewPoint1());
Serial.println(" °C");
}
delay(1000);
}If you want to use classic/blocking reads (as with many Arduino libraries), use readBlocking():
#include <Wire.h>
#include "Dual_AHT10.h"
Dual_AHT10 aht;
void setup() {
Serial.begin(115200);
Wire.begin();
aht.init(0x38);
}
void loop() {
if (aht.readBlocking()) {
Serial.print("Temp: "); Serial.print(aht.getTemp0());
Serial.print(" °C, RH: "); Serial.print(aht.getHum0());
Serial.print(" %, Dew Point: "); Serial.print(aht.getDewPoint0());
Serial.println(" °C");
}
delay(1000);
}#include <Wire.h>
#include "Dual_AHT10.h"
Dual_AHT10 aht;
void setup() {
Serial.begin(115200);
Wire.begin();
aht.init(0x38, 0x39);
}
void loop() {
if (aht.readBlocking()) {
Serial.print("[0x38] Temp: "); Serial.print(aht.getTemp0());
Serial.print(" °C, RH: "); Serial.print(aht.getHum0());
Serial.print(" %, Dew Point: "); Serial.print(aht.getDewPoint0());
Serial.println(" °C");
Serial.print("[0x39] Temp: "); Serial.print(aht.getTemp1());
Serial.print(" °C, RH: "); Serial.print(aht.getHum1());
Serial.print(" %, Dew Point: "); Serial.print(aht.getDewPoint1());
Serial.println(" °C");
}
delay(1000);
}Note: Blocking reads are intended for quick prototyping and compatibility. For responsive applications (e.g. ventilation control), non-blocking usage is recommended!
Constructive feedback, bug reports, and pull requests are very welcome! This is not rocket science—if you have improvements or find bugs, please open an issue or submit a PR.
Please use the GitHub Issues page to report bugs, suggest features, or ask questions: https://github.com/markus/Dual_AHT10/issues
- ATmega328P (Arduino Uno R3)
- (add your board here!)