cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 - SMBus and Melexis MLX90614

Miguel Antunes
Associate II
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

29 REPLIES 29
Miguel Antunes
Associate II
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
Associate II

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
Associate II

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 III

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

Artem
Associate III

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

monty
Associate

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.

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
Associate II

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.

Hi Franz,

How do you manage to set emissivity ?

Regards,

Thomas