这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【ESP-IDF系列】【ESP32】使用ESP-32-S3通过I2C协议驱动AH

共1条 1/1 1 跳转至

【ESP-IDF系列】【ESP32】使用ESP-32-S3通过I2C协议驱动AHT20湿温度传感器

助工
2025-03-21 18:22:04     打赏

AHT10简介和应用电路分析

AHT20传感器是奥松电子推出的一款湿温度传感器, 在之前的文章中我曾经出了一篇使用树莓派PICO驱动, 链接已经附加上了,大家感兴趣的话可以看一下. 而AHT20传感器的驱动实际上和AHT10的相差不多. 而我们选择使用AHT20传感器的目的是为了让大家熟悉ESP-IDF框架中较为新的 driver/i2cmaster.h 库的使用.image.pngAHT20传感器


我在其他的应用电路中有看到过, 在VDD间串联了一个330欧姆的电阻, 实际上这个电阻对电路的影响非常大. 在我3.3V的电路中大概有2V的压降,从而造成了传感器不工作的情况. 对于官方的典型应用电路, 如果你的开发板工作电压是在3.3V, 千万不要加这个电阻. 其推荐应用电路如下所示.

image.png

在实际的使用中发现两个上拉电阻和Cap的滤波电容对实际的电路影响不大, 去掉了也并不会在很大程度上影响到I2C通讯. 如果开发板上干扰较多的话,建议严格按照上述的原理图. 


ESP-IDF的I2C驱动

ESP-IDF一共具有三个I2C驱动的库, 它们分别是 i2c.h(遗留 I2C API 的头文件用于使用旧驱动程序的应用).  i2c_master.h (提供标准通信模式下特定 API 的头文件(用于使用主机模式的新驱动程序的应用)) i2c_slave.h (提供标准通信模式下特定 API 的头文件(用于使从机模式的新驱动程序的应用)

需要注意的一点是旧版驱动程序和新版驱动程序不能混合使用, 所以如果大家使用ESP-IDF开发应用的时候如果不想手动编写驱动程序的话, 一定要注意头文件中的驱动版本.


对于Master设备的驱动初始化的时候一般只需要按照下面的代码即可完成I2C总线的初始化

i2c_master_bus_config_t i2c_mst_config = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = TEST_I2C_PORT,
    .scl_io_num = I2C_MASTER_SCL_IO,
    .sda_io_num = I2C_MASTER_SDA_IO,
    .glitch_ignore_cnt = 7,
    .flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));


上述的代码仅仅是对总线进行初始化. 如果想要对对应的I2C设备进行初始化的话,我们还需要创建设备句柄, 并且把它挂载到I2C总线上.

i2c_device_config_t dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = 0x58,
    .scl_speed_hz = 100000,
};

i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));

上述代码则是绑定了一个I2C设备, 其地址为0X58 通讯的频率为100000HZ.  之后对这个设备句柄进行了初始化. 之后我们便可以使用I2C驱动的i2c_master_transmit 和 i2c_master_receive 进行数据的收发.


AHT20的驱动

首先我们需要绑定当前的AHT20设备句柄到I2C master总线上

void aht20_init(void)
{
    i2c_device_config_t dev_cfg = {
        .dev_addr_length = I2C_ADDR_BIT_LEN_7,
        .device_address = AHT20_I2C_ADDRESS,
        .scl_speed_hz = 400000,
    };
    esp_err_t ret = i2c_master_bus_add_device(i2c_bus_handle, &dev_cfg, &aht10_dev_handle);

    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to create I2C device handle: %d", ret);
    }

    ESP_LOGI(TAG, "Initializing AHT10...");
    uint8_t init_cmd[3] = {AHT20_CMD_INIT, 0x08, 0x00};
    i2c_master_transmit(aht10_dev_handle, init_cmd, 3, 1000 / portTICK_PERIOD_MS);
    vTaskDelay(40 / portTICK_PERIOD_MS); // Wait for 40ms
}

上述代码完成了数据手册里的第一部分, 即上电初始化.

image.png


之后使用按照数据手册定义, 发送0XAC和对应的命令来触发传感器的测量.

image.png

如下代码所示

    uint8_t status;
    uint8_t trigger_cmd[3] = {AHT20_CMD_TRIGGER, 0x33, 0x00};
    uint8_t data[7] = {0};

       // Send trigger command
    i2c_master_transmit(aht10_dev_handle, trigger_cmd, 3, 1000 / portTICK_PERIOD_MS);


湿温度的测量需要一定的时间,在我们触发测量操作之后应该等待测量完成

image.png

如下代码所示


 vTaskDelay(80 / portTICK_PERIOD_MS); // Wait for 80ms

 // 检查是否测量完成
 i2c_master_receive(aht10_dev_handle, &status, 1, 1000 / portTICK_PERIOD_MS);
 while (status & 0x80) // Bit[7] should be 0
    {
        vTaskDelay(10 / portTICK_PERIOD_MS);
        i2c_master_receive(aht10_dev_handle, &status, 1, 1000 / portTICK_PERIOD_MS);
    }


接着,我们可以从I2C总线上读取数据, 并且进行计算出湿温度数据.

image.png


如下代码所示


     // 读取7个bytes数据
    i2c_master_receive(aht10_dev_handle, data, 7, 1000 / portTICK_PERIOD_MS);

    uint32_t raw_humidity = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | ((uint32_t)data[3] >> 4);
    uint32_t raw_temperature = (((uint32_t)data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | (uint32_t)data[5];
    // 计算湿温度数据
    *humidity = ((float)raw_humidity / 1048576.0) * 100.0;
    *temperature = ((float)raw_temperature / 1048576.0) * 200.0 - 50.0;



完整代码如下所示

头文件

#ifndef AHT20_H
#define AHT20_H

#include "driver/i2c_master.h"

// AHT20 I2C address
#define AHT20_I2C_ADDRESS 0x38

/* AHT20 命令 */
#define AHT20_CMD_INIT 0xBE
/* 初始化命令 */
#define AHT20_CMD_TRIGGER 0xAC
/* 软件复位命令*/
#define AHT20_CMD_SOFT_RESET 0xBA

// Function prototypes
void aht20_init(void);
float aht20_read_temperature_and_humidity(float *humidity, float *temperature);
void aht20_soft_reset(void);

#endif // AHT20_H

源码文件

#include "aht20.h"
#include "driver/i2c_master.h"
#include <unistd.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

extern i2c_master_bus_handle_t i2c_bus_handle;
i2c_master_dev_handle_t aht10_dev_handle;

static const char *TAG = "AHT20";

void aht20_init(void)
{
    i2c_device_config_t dev_cfg = {
        .dev_addr_length = I2C_ADDR_BIT_LEN_7,
        .device_address = AHT20_I2C_ADDRESS,
        .scl_speed_hz = 400000,
    };
    esp_err_t ret = i2c_master_bus_add_device(i2c_bus_handle, &dev_cfg, &aht10_dev_handle);

    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to create I2C device handle: %d", ret);
    }

    ESP_LOGI(TAG, "Initializing AHT10...");
    uint8_t init_cmd[3] = {AHT20_CMD_INIT, 0x08, 0x00};
    i2c_master_transmit(aht10_dev_handle, init_cmd, 3, 1000 / portTICK_PERIOD_MS);
    vTaskDelay(40 / portTICK_PERIOD_MS); // Wait for 40ms
}

// Function to read temperature and humidity
float aht20_read_temperature_and_humidity(float *humidity, float *temperature)
{
    uint8_t status;
    uint8_t trigger_cmd[3] = {AHT20_CMD_TRIGGER, 0x33, 0x00};
    uint8_t data[7] = {0};

       // Send trigger command
    i2c_master_transmit(aht10_dev_handle, trigger_cmd, 3, 1000 / portTICK_PERIOD_MS);
    vTaskDelay(80 / portTICK_PERIOD_MS); // Wait for 80ms

    // Check if measurement is complete
    i2c_master_receive(aht10_dev_handle, &status, 1, 1000 / portTICK_PERIOD_MS);
    while (status & 0x80) // Bit[7] should be 0
    {
        vTaskDelay(10 / portTICK_PERIOD_MS);
        i2c_master_receive(aht10_dev_handle, &status, 1, 1000 / portTICK_PERIOD_MS);
    }

    // Read data
    i2c_master_receive(aht10_dev_handle, data, 7, 1000 / portTICK_PERIOD_MS);

    uint32_t raw_humidity = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | ((uint32_t)data[3] >> 4);
    uint32_t raw_temperature = (((uint32_t)data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | (uint32_t)data[5];

    *humidity = ((float)raw_humidity / 1048576.0) * 100.0;
    *temperature = ((float)raw_temperature / 1048576.0) * 200.0 - 50.0;

    return 0;
}


控制台效果如下:

image.png


图片效果如下:

image.png



源码文件:

oled_aht20.zip





关键词: ESP-IDF     SSD1306     AHT20     I2C    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]