1
votes

I use STM32F4 microcontroller and HAL library. I would like to read temperature from LSM303DLHC sensor. Following code is responsible for this task.

LSM303DLHC_Status_t LSM303DLHC_get_temp(int16_t *temp)
{
    uint8_t data_h = 0x00;
    uint8_t data_l = 0x00;
    uint16_t data_tmp = 0x00;
    uint8_t temp_enable = 0x00;

    if (HAL_I2C_Mem_Read(&hi2c1, LSM303_MAGNE_ADDRESS, TEMP_OUT_H_M, 1, &data_h, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }

    if (HAL_I2C_Mem_Read(&hi2c1, LSM303_MAGNE_ADDRESS, TEMP_OUT_L_M, 1, &data_l, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }

    data_tmp = (int16_t)((data_h << 8) | data_l);

    *temp = data_tmp/8;

    /*Enable temperature sensor*/
    if (HAL_I2C_Mem_Read(&hi2c1, LSM303_MAGNE_ADDRESS, CRA_REG_M, 1, &temp_enable, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }

    temp_enable |= (0x01 << 7);

    if (HAL_I2C_Mem_Write(&hi2c1, LSM303_MAGNE_ADDRESS, CRA_REG_M, 1, &temp_enable, 1, 100) != HAL_OK)
    {
        return LSM303DLHC_ERROR;
    }
    /*End enable temperature sensor*/

    return LSM303DLHC_OK;
}

According to data sheet and many tutorial temperature is computed by this expression:

temp = (int16_t)((data_h << 8) | data_l);
temp = temp/8;

In room where I am is about 20 degree of Celsius. My function returns about 128-136 value.

Where did I make mistake?

3
Reading the value and then enabling the sensor looks very strange. Shouldn't the read come between the enable and the disable? Perhaps with some delay too, if the sensor needs time to produce a reading after having been enabled.unwind
The code can invoke undefined behaviour when shifting into the sign-bit.too honest for this site
After each measure temperature sensor must be enabled. First time I enabled temperature sensor in LSM303DLHC_init_temp(), then after each measure I also enabled temperature sensor. I tried enabled temperature sensor before read from register(HAL_I2C_MEM_READ) but the result is the same.J. Doe

3 Answers

1
votes

Well, on my side I get the following value when I read the temp register in a room at 20 C.

TH=255, TL=224

So it seems that the 0 value from the register corresponds to 21 C (approx.), and I can get the correct value using code when the temperature goes under 21 C (TH bit 7 set to 1):

printf("TH=%d, TL=%d\n", RegVal[0], RegVal[1]);
int16_t IntTemp = ((int16_t)RegVal[0] << 8) + RegVal[1];

printf("temp=%0.2f\n", (float)IntTemp / 128 + 21);

temp=20.75

0
votes

Your Value is a 12 bit value but you treated it like a 16 bit value.

in the LSM303DLHC Datasheet the temperature register is shown like this: TEMP_OUT_H_M (31h), TEMP_OUT_L_M (32h)

High Register: TEMP11, TEMP10, ..., TEMP4 Low Register: TEMP3, TEMP2, TEMP1, TEMP0, -, -, -, -

The first 4 bits (LSB(!)) do not have temperature values.

Your temp value is around 0x130 (128-136) as you wrote. In binary it is 0000 0001 0011 0000. The first four bits are not relevant. So you have to read 0000 0001 0011 which is 0x13 which is 19 in decimal.

Best regards, Stefan

Edit: Be careful with datatypes! You try to shift a byte Value by 8. This will not work. define your values with int:

int16_t data_h = 0;
int8_t data_l = 0;

Then use:

*temp = ((int16_t)((data_h << 8) | data_l)>>4);

Tipp: Use the programming mode of the MS Windows Calculator and play with binary and hex and decimal numbers.

0
votes
# python

# enable Temperature sensor 
bus.write_byte_data(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRA_REG_M, 0x90)  

...
# read register
tempH = bus.read_byte_data(LSM303_ADDRESS_MAG, 0x31)
tempL = bus.read_byte_data(LSM303_ADDRESS_MAG, 0x32)
temp = (tempH << 8 ) +  tempL
if temp > 32767:  # 2's complement
    temp -= 65536
temperature = float( 20 + ( temp >> 4 )/ 8 )  # 16bit --> 12bit , 8LSB/deg