简单贴一个ESP32,Arduino框架使用的AHT20温湿度采集驱动。

AHT20是一个温湿度采集的小东西,

关于怎么写I2C器件的驱动之前的文章有介绍。

前言——AHT20基本参数

基本参数

  1. 测量范围

    • 温度:-40°C ~ +85°C

    • 湿度:0% ~ 100% RH

  2. 测量精度(典型值):

    • 温度:±0.3°C(在25°C时)

    • 湿度:±2% RH(20% ~ 80% RH范围内)

  3. 分辨率

    • 温度:0.01°C

    • 湿度:0.024% RH

  4. 响应时间

    • 湿度:8秒(τ63%响应时间)

    • 温度:5秒(τ63%响应时间)

电气特性

  1. 工作电压:2.2V ~ 5.5V(宽电压设计)

  2. 功耗

    • 测量时:1.5mA(典型值)

    • 待机时:0.2μA(低功耗模式)

  3. 通信接口:I²C接口(支持标准模式100kHz和快速模式400kHz)

  4. 输出数据

    • 温度:16位数字量

    • 湿度:16位数字量

一、头文件AHT20.h

#ifndef AHT20_H
#define AHT20_H

#include <Arduino.h>
#include <Wire.h>

#define AHT20_ADDRESS 0x38  // AHT20固定I2C地址

class AHT20 {
public:
    // 构造函数(指定Wire总线,可选指定引脚)
    AHT20(TwoWire &wire = Wire, uint8_t sdaPin = SDA, uint8_t sclPin = SCL);
    
    // 初始化传感器
    bool begin();
    
    // 读取温湿度数据
    bool read(float* temperature, float* humidity);
    
    // 单独读取温度
    float readTemperature();
    
    // 单独读取湿度
    float readHumidity();
    
    // 软复位传感器
    bool reset();

private:
    TwoWire* _wire;
    uint8_t _sdaPin;
    uint8_t _sclPin;
    
    // 检查传感器状态
    bool isCalibrated();
    bool isBusy();
    
    // 触发测量
    bool triggerMeasurement();
    
    // 读取原始数据
    bool readRawData(uint32_t* humidity, uint32_t* temperature);
};

#endif

二、源文件AHT20.cpp

#include "AHT20.h"

AHT20::AHT20(TwoWire &wire, uint8_t sdaPin, uint8_t sclPin) 
    : _wire(&wire), _sdaPin(sdaPin), _sclPin(sclPin) {
}

bool AHT20::begin() {
    _wire->begin(_sdaPin, _sclPin);
    return reset();
}

bool AHT20::reset() {
    _wire->beginTransmission(AHT20_ADDRESS);
    _wire->write(0xBA);  // 软复位命令
    if (_wire->endTransmission() != 0) {
        return false;
    }
    delay(20);  // 等待复位完成
    
    // 初始化校准
    _wire->beginTransmission(AHT20_ADDRESS);
    _wire->write(0xBE);  // 初始化命令
    _wire->write(0x08);
    _wire->write(0x00);
    if (_wire->endTransmission() != 0) {
        return false;
    }
    delay(10);  // 等待校准完成
    
    return isCalibrated();
}

bool AHT20::read(float* temperature, float* humidity) {
    if (!triggerMeasurement()) {
        return false;
    }
    
    uint32_t rawHumidity, rawTemperature;
    if (!readRawData(&rawHumidity, &rawTemperature)) {
        return false;
    }
    
    if (humidity != nullptr) {
        *humidity = (float)rawHumidity * 100 / 0x100000;  // 转换为百分比
    }
    
    if (temperature != nullptr) {
        *temperature = (float)rawTemperature * 200 / 0x100000 - 50;  // 转换为摄氏度
    }
    
    return true;
}

float AHT20::readTemperature() {
    float temperature;
    if (read(&temperature, nullptr)) {
        return temperature;
    }
    return NAN;
}

float AHT20::readHumidity() {
    float humidity;
    if (read(nullptr, &humidity)) {
        return humidity;
    }
    return NAN;
}

bool AHT20::isCalibrated() {
    _wire->beginTransmission(AHT20_ADDRESS);
    _wire->write(0x71);  // 读取状态字节
    if (_wire->endTransmission() != 0) {
        return false;
    }
    
    if (_wire->requestFrom(AHT20_ADDRESS, (uint8_t)1) != 1) {
        return false;
    }
    
    uint8_t status = _wire->read();
    return (status & 0x08) != 0;  // 检查校准位
}

bool AHT20::isBusy() {
    _wire->beginTransmission(AHT20_ADDRESS);
    _wire->write(0x71);  // 读取状态字节
    if (_wire->endTransmission() != 0) {
        return true;  // 假设忙状态以防通信失败
    }
    
    if (_wire->requestFrom(AHT20_ADDRESS, (uint8_t)1) != 1) {
        return true;
    }
    
    uint8_t status = _wire->read();
    return (status & 0x80) != 0;  // 检查忙位
}

bool AHT20::triggerMeasurement() {
    _wire->beginTransmission(AHT20_ADDRESS);
    _wire->write(0xAC);  // 触发测量命令
    _wire->write(0x33);
    _wire->write(0x00);
    if (_wire->endTransmission() != 0) {
        return false;
    }
    
    // 等待测量完成
    unsigned long start = millis();
    while (isBusy()) {
        if (millis() - start > 200) {  // 超时200ms
            return false;
        }
        delay(10);
    }
    
    return true;
}

bool AHT20::readRawData(uint32_t* humidity, uint32_t* temperature) {
    if (_wire->requestFrom(AHT20_ADDRESS, (uint8_t)6) != 6) {
        return false;
    }
    
    uint8_t data[6];
    for (int i = 0; i < 6; i++) {
        data[i] = _wire->read();
    }
    
    // 检查状态位
    if (data[0] & 0x80) {  // 忙状态
        return false;
    }
    
    if (humidity != nullptr) {
        *humidity = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | ((data[3] >> 4) & 0x0F);
    }
    
    if (temperature != nullptr) {
        *temperature = (((uint32_t)data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | data[5];
    }
    
    return true;
}

三、调用方法

1、全局定义

总线号和IO引脚号根据你实际情况修改。

#define I2C_SDA_PinNum 5
#define I2C_SCL_PinNum 4
AHT20 aht20(Wire1, I2C_SDA_PinNum, I2C_SCL_PinNum);

2、初始化,放setup()中

  if (!aht20.begin()) {
    Serial.println("无法初始化AHT20传感器!");
    while (1);
  }

3、数据读取

  float temperature_aht20 = aht20.readTemperature();
  float humidity = aht20.readHumidity();
  
  if (!isnan(temperature_aht20) && !isnan(humidity)) {
      Serial.print("温度: ");
      Serial.print(temperature_aht20);
      Serial.print(" °C\t");
      Serial.print("湿度: ");
      Serial.print(humidity);
      Serial.println(" %");
  } else {
      Serial.println("读取传感器数据失败!");
  }  

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐