Hongmeng's acquisition of temperature and humidity

Posted by mlin on Sun, 23 Jan 2022 11:21:31 +0100

introduce

HarmonyOS

HarmonyOS lightweight and small system is suitable for IOT devices with small memory. Through this article, developers can quickly get familiar with the environment construction, compilation, burning, debugging and running "Hello World" of HarmonyOS lightweight and small systems. There are two ways to develop lightweight and small systems: Develop and burn in Windows environment and compile in Linux environment. Unified use of Linux environment for development, compilation and burning.

AHT20

AHT20 temperature and humidity sensor has the characteristics of small size, reliable performance, rapid response, strong anti-interference ability, complete calibration, I2C digital interface and so on.

I2C

IC (inter integrated circuit) bus is a two-wire serial bus developed by PHILIPS company, which is used to connect microcontrollers and their peripherals. It is a serial bus composed of data line SDA and clock SCL, which can send and receive data. Bidirectional transmission is carried out between CPU and controlled I2C, and between I2C and I2C. The high-speed IC bus can generally reach more than 400kbps. There are three types of signals in the process of I2C bus transmitting data: start signal, end signal and response signal. Start signal: when SCL is high level, SDA jumps from high level to low level and starts transmitting data. End signal: SCL is high level, SDA jumps from low level to high level, and the junction transmits data. Response signal: after receiving 8bit data, the IC receiving the data sends a specific low-level pulse to the IC transmitting the data, indicating that the data has been received. After sending a signal to the controlled unit, the CPU waits for the controlled unit to send a response signal. After receiving the response signal, the CPU determines whether to continue transmitting the signal according to the actual situation. If no response signal is received, it is judged that the controlled unit has failed. Among these signals, the start signal is necessary, and the end signal and response signal can be omitted.

Specific design

Configure I2C

  1. Call the I2cInit interface to configure the I2C interface
hi_i2c_init(HI_I2C_IDX_0, 400*1000);
  1. Read function of I2C interface
static uint32_t AHT20_Read(uint8_t* buffer, uint32_t buffLen)
{
    hi_i2c_data data = { 0 };
    data.receive_buf = buffer;//Put the acquired data into data receive_ buf
    data.receive_len = buffLen;//Put the length of the data into the data receive_ len
    uint32_t retval = hi_i2c_read(AHT20_I2C_IDX, AHT20_READ_ADDR, &data);
    if (retval != HI_ERR_SUCCESS) {
        printf("I2cRead() failed, %0X!\n", retval);
        return retval;
    }
    return HI_ERR_SUCCESS;
}
  1. I2C write program
static uint32_t AHT20_Write(uint8_t* buffer, uint32_t buffLen)
{
    hi_i2c_data data = { 0 };
    data.send_buf = buffer;
    data.send_len = buffLen;
    uint32_t retval = hi_i2c_write(AHT20_I2C_IDX, AHT20_WRITE_ADDR, &data);
    if (retval != HI_ERR_SUCCESS) {
        printf("I2cWrite(%02X) failed, %0X!\n", buffer[0], retval);
        return retval;
    }
    return HI_ERR_SUCCESS;
}

AHT20 digital temperature and humidity sensor command

  1. Send get status command
static uint32_t AHT20_StatusCommand(void)
{
    uint8_t statusCmd[] = { AHT20_CMD_STATUS };
    return AHT20_Write(statusCmd, sizeof(statusCmd));
}
  1. Send soft reset command
static uint32_t AHT20_ResetCommand(void)
{
    uint8_t resetCmd[] = {AHT20_CMD_RESET};
    return AHT20_Write(resetCmd, sizeof(resetCmd));
}
  1. Send initialization calibration command
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));
}
  1. Send the trigger measurement command to start the measurement
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));
}

Obtain the value of AHT20 digital temperature and humidity sensor

  1. Before reading the temperature and humidity value, first check whether the calibration enable Bit[3] of the status word is 1 (one byte status word can be obtained by sending 0x71), //If it is not 1, send 0xBE command (initialization). The command parameter has two bytes, the first byte is 0x08 and the second byte is 0x00.
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 != HI_ERR_SUCCESS) {
        return retval;
    }

    retval = AHT20_Read(buffer, sizeof(buffer));
    if (retval != HI_ERR_SUCCESS) {
        return retval;
    }

    if (AHT20_STATUS_BUSY(buffer[0]) || !AHT20_STATUS_CALI(buffer[0])) {
        retval = AHT20_ResetCommand();
        if (retval != HI_ERR_SUCCESS) {
            return retval;
        }
        usleep(AHT20_STARTUP_TIME);
        retval = AHT20_CalibrateCommand();
        usleep(AHT20_CALIBRATION_TIME);
        return retval;
    }

    return HI_ERR_SUCCESS;
}
  1. Receive the measurement results and convert them into standard values
uint32_t AHT20_GetMeasureResult(float* temp, float* humi)
{
    uint32_t retval = 0, i = 0;
    if (temp == NULL || humi == NULL) {
        return HI_ERR_FAILURE;
    }

    uint8_t buffer[AHT20_STATUS_RESPONSE_MAX];
    memset(&buffer, 0x0, sizeof(buffer));//Empty memset
    retval = AHT20_Read(buffer, sizeof(buffer));  // recv status command result
    if (retval != HI_ERR_SUCCESS) {
        return retval;
    }

    for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) {
        // printf("AHT20 device busy, retry %d/%d!\r\n", i, AHT20_MAX_RETRY);
        usleep(AHT20_MEASURE_TIME);
        retval = AHT20_Read(buffer, sizeof(buffer));  // recv status command result
        if (retval != HI_ERR_SUCCESS) {
            return retval;
        }
    }
    if (i >= AHT20_MAX_RETRY) {
        printf("AHT20 device always busy!\r\n");
        return HI_ERR_SUCCESS;
    }

    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;
    // printf("humi = %05X, %f, temp= %05X, %f\r\n", humiRaw, *humi, tempRaw, *temp);
    return HI_ERR_SUCCESS;
}

Routine implementation

static void EnviromentTask(void *arg)     
{
    (void)arg;
    uint32_t retval = 0;
    float humidity = 0.0f;//Define variables for storage humidity
    float temperature = 0.0f;//Variables defining storage temperature
    I2cInit(AHT20_I2C_IDX, AHT20_BAUDRATE);//Initialize I2C
    while (WIFI_IOT_SUCCESS != AHT20_Calibrate()) {
        printf("AHT20 sensor init failed!\r\n");
        usleep(1000);
    }
    while(1) {
        retval = AHT20_StartMeasure();//Send trigger measurement command to start measurement
        if (retval != WIFI_IOT_SUCCESS) {
            printf("trigger measure failed!\r\n");
        }

        retval = AHT20_GetMeasureResult(&temperature, &humidity);//The value of temperature and humidity is placed in the address of the variable
        if (retval != WIFI_IOT_SUCCESS) {
            printf("get humidity data failed!\r\n");
        }
        snprintf(line, sizeof(line), "temp: %.2f", temperature);
        OledShowString(0, 1, line, 1);
        snprintf(line, sizeof(line), "humi: %.2f", humidity);
        OledShowString(0, 2, line, 1);
        sleep(1);
    }

}