Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTU2X sensor not successful with getting data

Tags:

c++

i2c

stm32

Did the following steps to test if my temperature sensor HTU2X is working thoroughly. Selected my board (Nucleo-64 STM32F411RE) from STM32CubeIDE then enabled I2C1 for pins PB8 (as the SCL) and PB9 (as the SDA) as in the screenshot below, then saved the project. enter image description here

Here's also the wiring: enter image description here Then wrote a run() function and ran it in main.c to do the job the following way:

lib.hpp

#ifndef INC_LIB_HPP_
#define INC_LIB_HPP_

#if __cplusplus
extern "C" {
#endif

inline I2C_HandleTypeDef hi2c1;
inline UART_HandleTypeDef huart2;
inline uint8_t buf[32];

inline HAL_StatusTypeDef ret;
inline int16_t val;
inline float temp_c;

void run();
void I2C1_Scan();
void HTU21D_Init();

#if __cplusplus
}
#endif

#endif

CODE EDIT: lib.cpp

static constexpr uint8_t HTU21D_ADDR = (0x40 << 1);  // 7-bit address shifted for HAL

void I2C1_Scan()
{
    char msg[32];
    bool found = false;

    for (uint8_t addr7 = 1; addr7 < 127; addr7++)
    {
        uint16_t addr8 = addr7 << 1; // what HAL expects
        if (HAL_I2C_IsDeviceReady(&hi2c1, addr8, 2, 1000) == HAL_OK)
        {
            // print in both 7-bit and 8-bit forms to avoid confusion
            snprintf(msg, sizeof(msg), "Found: 0x%02X (7b), 0x%02X (8b)\r\n", addr7, addr8);
            HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
            found = true;
        }
    }
    if( not found)
        HAL_UART_Transmit(&huart2, (uint8_t*)"No Match!\r\n", 10, HAL_MAX_DELAY);
}


void HTU21D_Init(void)
{
    uint8_t reset_cmd = 0xFE;
    char msg[64];

    // Wait after power-up (sensor needs ~15ms, give it 100ms)
    HAL_Delay(100);

    // Send soft reset command (0xFE)
    auto result = HAL_I2C_Master_Transmit(&hi2c1, HTU21D_ADDR, &reset_cmd, 1, HAL_MAX_DELAY);

    // Print numeric HAL status
    snprintf(msg, sizeof(msg), "Soft reset status: %d\r\n", (int)result);
    HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

    // Wait after reset
    HAL_Delay(100);

    // Check if device is ready
    result = HAL_I2C_IsDeviceReady(&hi2c1, HTU21D_ADDR, 3, 10000);

    // Print numeric HAL status
    snprintf(msg, sizeof(msg), "IsDeviceReady status: %d\r\n", (int)result);
    HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
}

void run() {
    static constexpr uint8_t REG_TEMP = 0x00;
    HAL_Delay(100); // give power and peripherals time to settle
    I2C1_Scan();    // check which devices are on the bus
    HTU21D_Init();  // try reset + ready check

    while (1)
    {
        buf[0] = REG_TEMP;
        ret = HAL_I2C_Master_Transmit(&hi2c1, HTU21D_ADDR, buf, 1, HAL_MAX_DELAY);      
        if(ret != HAL_OK) {             
         snprintf(msg, sizeof(msg), "Transmit status: %d\r\n", (int)ret);   
         HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);         
        }
        else {
            ret = HAL_I2C_Master_Receive(&hi2c1, HTU21D_ADDR, buf, 2, HAL_MAX_DELAY);
            if(ret != HAL_OK)
                strcpy((char*)buf, "ERROR Rx \r\n");
            else {
                val = ((int16_t)buf[0] << 4) | (buf[1] >> 4);

                if(val > 0x7FF)
                    val |= 0xF000;

                temp_c = val * 0.0625;

                temp_c *= 100;
                sprintf((char*)buf,
                        "%u.%02u C\r\n",
                        ((unsigned int)temp_c / 100),
                        ((unsigned int) temp_c % 100));
            }
        }

        HAL_UART_Transmit(&huart2, buf, strlen((char*)buf), HAL_MAX_DELAY);
        HAL_Delay(500);
    } // End of whil(1)
}

The problem is that I get the Error Tx as output, shown below:

Output

Any idea where the problem is and how to fix it please?

like image 360
Franky Avatar asked Jun 28 '26 03:06

Franky


1 Answers

static constexpr uint8_t REG_TEMP = 0x00;

Based on datasheet page 10, there are two registers for reading the temperature measurement, register 0xE3 (with Holding the master during measurement, i.e. with clock stretching), or register 0xF3 without clock stretching. Your code is trying to read temperature measurement from register 0x00 which does not exist and therefore causing the device to return error. HTU21 register table With register 0xF3, the measurement takes up to 50ms to complete(see page 4 of the datasheet). The temperature data is returned in 3 bytes, first two bytes as the raw temperature data, plus one byte checksum, if you only read 2 bytes (which is acceptable), checksum will not be sent by the HTU21 (see page 11 of the datasheet).


static constexpr uint8_t REG_TEMP_NO_HOLD = 0xF3;
char msg[80]{0};

while (1)
    {
        uint8_t cmd = REG_TEMP_NO_HOLD;
        int ret = HAL_I2C_Master_Transmit(&hi2c1, HTU21D_ADDR, &cmd, 1, HAL_MAX_DELAY);      
        if(ret != HAL_OK) {             
            snprintf(msg, sizeof(msg), "Transmit status: %d\r\n", ret);   
        }
        else {
            HAL_Delay(50); // as per datasheet page 4
            uint8_t rx_data[3]{0};
            ret = HAL_I2C_Master_Receive(&hi2c1, HTU21D_ADDR, rx_data, 3, HAL_MAX_DELAY);
            if(ret != HAL_OK)
                snprintf(msg, sizeof(msg), "ERROR Rx %d\r\n", ret);
            else {
                int16_t raw_temp = (rx_data[0] << 8) | rx_data[1];  // remove status bits
                int16_t temp_c = (int16_t) (-46.85 + 175.72 * raw_temp / 65536);
                
                snprintf(msg, sizeof(msg), 
                        "Temp(C): %d, status: %d, checksum: %02x\r\n",
                        temp_c, rx_data[1] & 0x03, rx_data[2]);
            }
        }

        HAL_UART_Transmit(&huart2, (const uint8_t*) msg, strlen(msg), HAL_MAX_DELAY);
        HAL_Delay(500);
    } // End of whil(1)
like image 156
hcheung Avatar answered Jul 01 '26 02:07

hcheung



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!