今天主要和大家聊一聊,如何使用鸿蒙系统去提取AHT20的温湿度传感器的数值,该传感器采用ADC位数为20Bit,具有体积小,精度高和成本低的优点。
编辑
第一:温湿度传感器基本参数
编辑
管脚定义与参考电路
编辑
编辑
I2C时序特性----支持标准100Hz,高速400KHz
编辑
编辑
第二:温度代码具体实现
上面分析了,温湿度传感器的基本实现原理与方法,主要精力可以放在代码的具体实现上。
#include "aht20.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "wifiiot_i2c.h"
#include "wifiiot_errno.h"
#define AHT20_I2C_IDX WIFI_IOT_I2C_IDX_0
#define AHT20_STARTUP_TIME 20*1000
#define AHT20_CALIBRATION_TIME 40*1000
#define AHT20_MEASURE_TIME 75*1000
#define AHT20_DEVICE_ADDR 0x38
#define AHT20_READ_ADDR ((0x38<<1)|0x1)
#define AHT20_WRITE_ADDR ((0x38<<1)|0x0)
#define AHT20_CMD_CALIBRATION 0xBE
#define AHT20_CMD_CALIBRATION_ARG0 0x08
#define AHT20_CMD_CALIBRATION_ARG1 0x00
#define AHT20_CMD_TRIGGER 0xAC
#define AHT20_CMD_TRIGGER_ARG0 0x33
#define AHT20_CMD_TRIGGER_ARG1 0x00
#define AHT20_CMD_RESET 0xBA
#define AHT20_CMD_STATUS 0x71
#define AHT20_STATUS_BUSY_SHIFT 7
#define AHT20_STATUS_BUSY_MASK (0x1<<AHT20_STATUS_BUSY_SHIFT)
#define AHT20_STATUS_BUSY(status) ((status & AHT20_STATUS_BUSY_MASK) >> AHT20_STATUS_BUSY_SHIFT)
#define AHT20_STATUS_MODE_SHIFT 5
#define AHT20_STATUS_MODE_MASK (0x3<<AHT20_STATUS_MODE_SHIFT)
#define AHT20_STATUS_MODE(status) ((status & AHT20_STATUS_MODE_MASK) >> AHT20_STATUS_MODE_SHIFT)
#define AHT20_STATUS_CALI_SHIFT 3
#define AHT20_STATUS_CALI_MASK (0x1<<AHT20_STATUS_CALI_SHIFT)
#define AHT20_STATUS_CALI(status) ((status & AHT20_STATUS_CALI_MASK) >> AHT20_STATUS_CALI_SHIFT)
#define AHT20_STATUS_RESPONSE_MAX 6
#define AHT20_RESOLUTION (1<<20)
#define AHT20_MAX_RETRY 10
static uint32_t AHT20_Read(uint8_t* buffer, uint32_t buffLen)
{
WifiIotI2cData data = { 0 };
data.receiveBuf = buffer;
data.receiveLen = buffLen;
uint32_t retval = I2cRead(AHT20_I2C_IDX, AHT20_READ_ADDR, &data);
if (retval != WIFI_IOT_SUCCESS) {
printf("I2cRead() failed, %0X!\n", retval);
return retval;
}
return WIFI_IOT_SUCCESS;
}
static uint32_t AHT20_Write(uint8_t* buffer, uint32_t buffLen)
{
WifiIotI2cData data = { 0 };
data.sendBuf = buffer;
data.sendLen = buffLen;
uint32_t retval = I2cWrite(AHT20_I2C_IDX, AHT20_WRITE_ADDR, &data);
if (retval != WIFI_IOT_SUCCESS) {
printf("I2cWrite(%02X) failed, %0X!\n", buffer[0], retval);
return retval;
}
return WIFI_IOT_SUCCESS;
}
static uint32_t AHT20_StatusCommand(void)
{
uint8_t statusCmd[] = { AHT20_CMD_STATUS };
return AHT20_Write(statusCmd, sizeof(statusCmd));
}
static uint32_t AHT20_ResetCommand(void)
{
uint8_t resetCmd[] = {AHT20_CMD_RESET};
return AHT20_Write(resetCmd, sizeof(resetCmd));
}
static uint32_t AHT20_CalibrateCommand(void)
{
uint8_t clibrateCmd[] = {AHT20_CMD_CALIBRATION, AHT20_CMD_CALIBRATION_ARG0, AHT20_CMD_CALIBRATION_ARG1};
return AHT20_Write(clibrateCmd, sizeof(clibrateCmd));
}
uint32_t AHT20_Calibrate(void)
{
uint32_t retval = 0;
uint8_t buffer[AHT20_STATUS_RESPONSE_MAX];
memset(&buffer, 0x0, sizeof(buffer));
retval = AHT20_StatusCommand();
if (retval != WIFI_IOT_SUCCESS) {
return retval;
}
retval = AHT20_Read(buffer, sizeof(buffer));
if (retval != WIFI_IOT_SUCCESS) {
return retval;
}
if (AHT20_STATUS_BUSY(buffer[0]) || !AHT20_STATUS_CALI(buffer[0])) {
retval = AHT20_ResetCommand();
if (retval != WIFI_IOT_SUCCESS) {
return retval;
}
usleep(AHT20_STARTUP_TIME);
retval = AHT20_CalibrateCommand();
usleep(AHT20_CALIBRATION_TIME);
return retval;
}
return WIFI_IOT_SUCCESS;
}
uint32_t AHT20_StartMeasure(void)
{
uint8_t triggerCmd[] = {AHT20_CMD_TRIGGER, AHT20_CMD_TRIGGER_ARG0, AHT20_CMD_TRIGGER_ARG1};
return AHT20_Write(triggerCmd, sizeof(triggerCmd));
}
uint32_t AHT20_GetMeasureResult(float* temp, float* humi)
{
uint32_t retval = 0, i = 0;
if (temp == NULL || humi == NULL) {
return WIFI_IOT_FAILURE;
}
uint8_t buffer[AHT20_STATUS_RESPONSE_MAX];
memset(&buffer, 0x0, sizeof(buffer));
retval = AHT20_Read(buffer, sizeof(buffer));
if (retval != WIFI_IOT_SUCCESS) {
return retval;
}
for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) {
usleep(AHT20_MEASURE_TIME);
retval = AHT20_Read(buffer, sizeof(buffer));
if (retval != WIFI_IOT_SUCCESS) {
return retval;
}
}
if (i >= AHT20_MAX_RETRY) {
printf("AHT20 device always busy!\r\n");
return WIFI_IOT_FAILURE;
}
uint32_t humiRaw = buffer[1];
humiRaw = (humiRaw << 8) | buffer[2];
humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4);
*humi = humiRaw / (float)AHT20_RESOLUTION * 100;
uint32_t tempRaw = buffer[3] & 0x0F;
tempRaw = (tempRaw << 8) | buffer[4];
tempRaw = (tempRaw << 8) | buffer[5];
*temp = tempRaw / (float)AHT20_RESOLUTION * 200 - 50;
return WIFI_IOT_SUCCESS;
}
接下来,可以利用鸿蒙系统对温湿度传感器里面的温度数据进行读取,然后再将获取到的温湿度数据进行显示输出。
#include "aht20.h"
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_i2c.h"
void Aht20TestTask(void* arg)
{
(void) arg;
uint32_t retval = 0;
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA);
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL);
I2cInit(WIFI_IOT_I2C_IDX_0, 400*1000);
retval = AHT20_Calibrate();
printf("AHT20_Calibrate: %d\r\n", retval);
while (1) {
float temp = 0.0, humi = 0.0;
retval = AHT20_StartMeasure();
printf("AHT20_StartMeasure: %d\r\n", retval);
retval = AHT20_GetMeasureResult(&temp, &humi);
printf("AHT20_GetMeasureResult: %d, temp = %.2f, humi = %.2f\r\n", retval, temp, humi);
sleep(1);
}
}
void Aht20Test(void)
{
osThreadAttr_t attr;
attr.name = "Aht20Task";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 4096;
attr.priority = osPriorityNormal;
if (osThreadNew(Aht20TestTask, NULL, &attr) == NULL) {
printf("[Aht20Test] Failed to create Aht20TestTask!\n");
}
}
APP_FEATURE_INIT(Aht20Test);
具体的操作实现如视频所示。
第三:视频显示效果