Skip to main content
Miguel Antunes
Associate
May 23, 2018
Question

STM32L4 - SMBus and Melexis MLX90614

  • May 23, 2018
  • 23 replies
  • 8992 views
Posted on May 23, 2018 at 17:49

Hello,

I'm trying to read temperature values from a Melexis MLX90614 sensor with SMBus but something seems to be wrong.

I used the HAL_SMBUS_IsDeviceReady to see if I can connect to the sensor and I can.

#define MLX90614_ADDRESS (0x5A << 1)

#define MLX90614_TA 0x06

(...)

return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1,MLX90614_ADDRESS,(uint8_t*)MLX90614_TA,1,SMBUS_FIRST_FRAME);

while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

if (return_value != HAL_OK)

{

   return return_value;

}

return_value = HAL_SMBUS_Master_Receive_IT(&hsmbus1,MLX90614_ADDRESS,(uint8_t*)data_read,2,SMBUS_LAST_FRAME_NO_PEC);

while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

if(return_value != HAL_OK)

{

   return return_value;

}

This is the code I'm using to read to bytes from that sensor.

The code seems to stop in the first while.

The SMBus peripheral is configured in SMBus-Two-Wire-Interface in CubeMX.

I don't understand what should I put in the XferOptions field in either one of those functions and I don't know if that's the problem.

In

Thank you in advance.

Miguel Antunes

    This topic has been closed for replies.

    23 replies

    Miguel Antunes
    Associate
    May 24, 2018
    Posted on May 24, 2018 at 17:09

    I changed a couple of things in the configurations (screenshots below) and changed the code to the following:

    (...)

    return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1,MLX90614_ADDRESS,(uint8_t*)MLX90614_TA,1,SMBUS_FIRST_FRAME);

    while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

    if (return_value != HAL_OK)

    {

       return return_value;

    }

    return_value = HAL_SMBUS_Master_Receive_IT(&hsmbus1,MLX90614_ADDRESS,(uint8_t*)data_read,2,SMBUS_OTHER_AND_LAST_FRAME_NO_PEC);

    while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

    if(return_value != HAL_OK)

    {

       return return_value;

    }

    (...)

    Right now I can read values from the sensor but they don't seem to be correct.

    Any help?

    0690X0000060KvnQAE.png0690X0000060KvsQAE.png
    FIlse
    Visitor II
    September 12, 2018

    Hi,

    did you or anyone else manage to solve the problem? I'm asking because I have the same problem with the MLX90614-sensor. Instead of the STM32L4 I'm using one of the F0-series. I'm facing just the same problem while reading the ambient temperature from the sensor. I get values which don't make sense. Also when I'm trying to read the object temperature (address 0x07) I literally get nothing back. I'm kind of desperate and hope someone could me/us.

    My code looks like this:

        HAL_SMBUS_Master_Transmit_IT(&hsmbus1, 0x5A<<1, MLX90614_TOB, 1, SMBUS_FIRST_FRAME);

        while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

        HAL_SMBUS_Master_Receive_IT(&hsmbus1, 0x5A<<1, buffer, 2, SMBUS_OTHER_AND_LAST_FRAME_NO_PEC);

        while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

        int_temp = buffer[0] <<8 | buffer[1];

        temperature = int_temp*0.02 - 273.15;

    thank you in advance!

    FIlse
    Visitor II
    September 13, 2018

    My sensor is now working! Here's the code:

    char buffer[5];

    float temperature;

    int main(void){

    while (1)

    {

    HAL_I2C_Mem_Read(&hi2c1, 0x5A<<1, 0x07, 1, buffer, 2, 100);

     int_temp = (buffer[1] <<8 | buffer[0]);

      temperature = int_temp*0.02 - 273.15;

      HAL_Delay(200);

    }

    0690X000006C1JLQA0.png

    Since the sensor needs a repeated start, HAL_I2C_MEM_Read() will do the job for you! Because of the stop-condition, which is set by HAL_I2C_Master_Transmit and HAL_I2C_Master_Receive you wouldn't be able to read the values properly because of that missing repeated start. Mem_Read on the other hand does the following: start, I2C address + Write, Memory address, repeated start, I2C address + Read, N bytes, stop. Besides that when combining the two data bytes you have to pay attention that the lsbyte (in my example buffer[0]) comes first, so you have to shift the msbyte by 8 and "OR" it with lsbyte. After that you'll get proper temperature-values.

    Hope this will help other people, struggling with this sensor.

    Artem
    Associate II
    October 11, 2018

    So you are running the sensor in I2C mode instead of SMBus?

    Artem
    Associate II
    October 12, 2018

    Ok, got it working in standard I2C mode. Thank you!

    monty
    Visitor II
    February 10, 2019

    Hi,

    has anyone been able to use franz's code to read the sensor and could help me out? I have tried it multiple times on stm32F0x micro's but am unable to receive any data from the mlx90614.

    Thanks.

    thomasFromBrittany
    Visitor II
    February 13, 2019

    Hi Monty,

    I'm able to read MLX90614 data in I2C mode too, but when I set emissivity (and then read it, to be sure), I have two different values...

    That's what I use to read temperature :

    HAL_I2C_Mem_Read(&hi2c1, (0x5A<<1), MLX90614_REGISTER_TOBJ1, 1, buffer, 2, 100);

    Thomas

    FIlse
    Visitor II
    February 13, 2019

    Hi, sorry for answering late.

    Yes, there was already someone who messaged me and I went through the process of getting any signals from the sensor, step by step.

    Do you have an UART-adapter? If so, you could print the result of the communication to your terminal. In the case of the person, who messaged me, the I2C-interface was broken and so didn't get a signal. After he bought a new board, the code was working just fine.

    I would suggest you to check if you get any signal from the sensor.

    You can do this by checking all the i2c-addresses, the sensor is able to communicate with for example:

    int main(void)
    {
     /* USER CODE BEGIN 1 */
     
     /* USER CODE END 1 */
     
     /* MCU Configuration----------------------------------------------------------*/
     
     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
     HAL_Init();
     
     /* USER CODE BEGIN Init */
     
     /* USER CODE END Init */
     
     /* Configure the system clock */
     SystemClock_Config();
     
     /* USER CODE BEGIN SysInit */
     
     /* USER CODE END SysInit */
     
     /* Initialize all configured peripherals */
     MX_GPIO_Init();
     MX_I2C1_Init();
     MX_USART1_UART_Init();
     /* USER CODE BEGIN 2 */
     char uartbuffer[24];
     uint8_t i = 1;
     HAL_StatusTypeDef result;
     
     
     
     /* USER CODE END 2 */
     
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     while (1)
     {
     
     /* USER CODE END WHILE */
     
     /* USER CODE BEGIN 3 */
    	 for (i = 0; i<128; i++)
    	 {
    		 result = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t) (i<<1), 2, 2);
    		 if (result != HAL_OK)
    		 {
    			 sprintf(uartbuffer, ".");
    			 HAL_UART_Transmit(&huart1, uartbuffer, 1, 0xFFFF);
    		 }
    		 if (result == HAL_OK)
    		 {
    			 sprintf(uartbuffer, "0x%X", i);
    			 HAL_UART_Transmit(&huart1, uartbuffer, 4, 0xFFFF);
     
    		 }
    	 }
     
     }
     /* USER CODE END 3 */
     
    }

    This scans all addresses and prints the result on a terminal. If there are just dots and no addresses like 0x5A or 0x00, there is probably something wrong with your I2C-interface.

    thomasFromBrittany
    Visitor II
    February 13, 2019

    Hi Franz,

    How do you manage to set emissivity ?

    Regards,

    Thomas

    FIlse
    Visitor II
    February 13, 2019

    Hi Thomas,

    I'm sorry but I haven't tested that yet.

    But I'll try when I'm at work tomorrow! Have you checked the the documentation on that? https://www.melexis.com/-/media/files/documents/application-notes/mlx90614-changing-emissivity-unlocking-key-application-note-melexis.pdf

    Remember that you have to WRITE the new set emissivity value to your EEPROM. You can do that by using HAL_I2C_Master_Transmit(); Remember that when doing an write-operation, you have to append the package error code (PEC).

    Here's an write example to change the slave-address of the sensor:

    /* USER CODE BEGIN 2 */
    uint8_t i2cdata[4];
     
     
    i2cdata[0] = 0x2E; //EEPROM-address
    i2cdata[1] = 0x00; //Delete-Byte, low
    i2cdata[2] = 0x00; //Delete-Byte, high
    i2cdata[3] = 0x6F; //PEC -> CRC8-checksum for 2E0000, calculation: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
     
     
    HAL_I2C_Master_Transmit(&hi2c1, 0x00<<1, i2cdata, 4, 0xFFFF);
    HAL_Delay(500);
     
    i2cdata[0] = 0x2E; //EEPROM-address
    i2cdata[1] = 0x50; //newaddress, low
    i2cdata[2] = 0x00; //newaddress, high
    i2cdata[3] = 0x63; //PEC -> CRC8-checksum for 2E5000, calculation: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
     
    HAL_I2C_Master_Transmit(&hi2c1, 0x00<<1, i2cdata, 4, 0xFFFF);
    HAL_Delay(500);
     
     
    /* USER CODE END 2 */

    Changing the emissivity should be quite similar...

    thomasFromBrittany
    Visitor II
    February 13, 2019

    Hey Franz,

    Where do you find this snippet code ?

    For me, this does't work..

    When I send a new emissivity value (ex : Ke= 0x3333 => emissivity = 0.20), I read the EEPROM after (Ke = 0xFAE0 => emissivity = 0.98), this is not what I set !

    "

    uint8_t i2cdata[4];

    i2cdata[0] = 0x24; //EEPROM-address

    i2cdata[1] = 0x33; //Delete-Byte, low

    i2cdata[2] = 0x33; //Delete-Byte, high

    i2cdata[3] = 0xB7; //PEC -> CRC8-checksum for 243333, calculation: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

    HAL_I2C_Master_Transmit(&hi2c1, 0x5A<<1, i2cdata, 4, 0xFFFF);

    "

    If you have any idea about my problem, it's with pleasure !!

    dinamitemic
    Visitor II
    May 26, 2019

    Hi Thomas, Can I ask you how did you managed to read back from EEPROM.

    I've tried the same as reading from RAM but it didn't work. It seems like is performing a write instead of a read and after I've to reprogram some regs to make it works again.

    ty.locke
    Associate II
    May 28, 2019

    Be sure to change the op code when reading from EEPROM and you should be able to read the register values without issue. If you're trying to change the values be sure to erase the EEPROM address first before setting the new values

    thomasFromBrittany
    Visitor II
    February 13, 2019

    ..