Author Topic: STM32 - SMBUS, Timers and other questions  (Read 5621 times)

0 Members and 1 Guest are viewing this topic.

Offline MAntunesTopic starter

  • Regular Contributor
  • *
  • Posts: 99
  • Country: pt
STM32 - SMBUS, Timers and other questions
« on: June 05, 2018, 11:33:01 am »
Hello,

right now I'm working with a STM Nucleo L432KC board and I have a couple of questions in which I'd like your help.
The first one is regarding SMBus. I'm trying to read from a Melexis MLX90614 sensor and I'm using this code.

Code: [Select]
#define MLX90614_ADDRESS (0x5A << 1)
#define MLX90614_TA 0x06
#define MLX90614_TOBJ1 0x07

(...)

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;
}

if ((data_read[1] & 0x80) == 0x80)
{
return HAL_ERROR;
}

aux = data_read[0] + (data_read[1] << 8);
ambient_temperature = aux * 0.02 - 273.15;

I'm getting some strange values and I'd like to know if the problem is the sensor or my code.

The other question is regarding the sprintf function.  I can't print floating point values. Is there anything I need to do to enable this?

Thank you,
Miguel
« Last Edit: June 20, 2018, 03:26:04 pm by MAntunes »
 

Offline Gibson486

  • Frequent Contributor
  • **
  • Posts: 324
  • Country: us
Re: STM32 - SMBUS and sprintf with floats
« Reply #1 on: June 05, 2018, 01:24:19 pm »
Are you trying to print ambient_temperature?

https://www.tutorialspoint.com/c_standard_library/c_function_sprintf.htm

Are you putting ambient_temperature into a char array? Each digit or decimal has to be 1 index of the array.

Also, something does not look right:

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

I think you a missing a "(" before "data_read".
« Last Edit: June 05, 2018, 01:32:53 pm by Gibson486 »
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 3683
  • Country: us
Re: STM32 - SMBUS and sprintf with floats
« Reply #2 on: June 05, 2018, 01:53:03 pm »
Newlib nano and probably other c libraries for MCUs have integer only printf/scant by default to save space.  You can enable floating point printf by adding asm (".global _printf_float"); to you c file.  See: https://github.com/32bitmicro/newlib-nano-1.0/blob/master/newlib/README.nano
 

Offline MAntunesTopic starter

  • Regular Contributor
  • *
  • Posts: 99
  • Country: pt
Re: STM32 - SMBUS and sprintf with floats
« Reply #3 on: June 05, 2018, 02:08:03 pm »
Newlib nano and probably other c libraries for MCUs have integer only printf/scant by default to save space.  You can enable floating point printf by adding asm (".global _printf_float"); to you c file.  See: https://github.com/32bitmicro/newlib-nano-1.0/blob/master/newlib/README.nano
Thank you. I'll try this.

Are you trying to print ambient_temperature?

https://www.tutorialspoint.com/c_standard_library/c_function_sprintf.htm

Are you putting ambient_temperature into a char array? Each digit or decimal has to be 1 index of the array.

Also, something does not look right:

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

I think you a missing a "(" before "data_read".
You're right, I got lost in copying the code.
And yes, that's one the variables I'm trying to put in string.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14297
  • Country: fr
Re: STM32 - SMBUS and sprintf with floats
« Reply #4 on: June 05, 2018, 02:31:20 pm »
The default printf() doesn't support floats to save a fair amount of code. Using arm-gcc, you can enable float support by adding this option to the linker: "-u _printf_float".
You can also use ejeffrey's way. Does the same thing. I tend to prefer the former, but it's your call.

Regarding your I2C code, you are casting a constant value (MLX90614_TA) to a pointer in the HAL_SMBUS_Master_Transmit_IT() call. This is uh... just wrong.
You should use an uint8_t variable instead, and pass a pointer to it, such as so:

Code: [Select]
uint8_t RAMAddress = MLX90614_TA;

return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1, MLX90614_ADDRESS, &RAMAddress, 1, SMBUS_FIRST_FRAME);
 

Offline MAntunesTopic starter

  • Regular Contributor
  • *
  • Posts: 99
  • Country: pt
Re: STM32 - SMBUS and sprintf with floats
« Reply #5 on: June 05, 2018, 03:28:38 pm »
The default printf() doesn't support floats to save a fair amount of code. Using arm-gcc, you can enable float support by adding this option to the linker: "-u _printf_float".
You can also use ejeffrey's way. Does the same thing. I tend to prefer the former, but it's your call.

Regarding your I2C code, you are casting a constant value (MLX90614_TA) to a pointer in the HAL_SMBUS_Master_Transmit_IT() call. This is uh... just wrong.
You should use an uint8_t variable instead, and pass a pointer to it, such as so:

Code: [Select]
uint8_t RAMAddress = MLX90614_TA;

return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1, MLX90614_ADDRESS, &RAMAddress, 1, SMBUS_FIRST_FRAME);
Thanks a lot. It was indeed that problem that was causing some errors in my code.
 

Offline MAntunesTopic starter

  • Regular Contributor
  • *
  • Posts: 99
  • Country: pt
Re: STM32 - SMBUS and Timer Interrupt
« Reply #6 on: June 19, 2018, 01:24:24 pm »
Hello again,

after correcting the function that was causing the errors reading the sensor I'm back again with some problems, now Timer related.
I'm using Timer2 to cause an interruption every 1ms. But when I read my sensor using SMBus that time changes and I don't know why.

The function that reads values from the sensor:
Code: [Select]
HAL_StatusTypeDef MLX90614_ReadData(struct MLX90614 *mysensor)
{
HAL_StatusTypeDef return_value;
uint8_t data_read[3];
uint16_t aux;
float ambient_temperature;
float ir_temperature;

data_read[0] = MLX90614_TA;
return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1,MLX90614_ADDRESS,&data_read[0],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,&data_read[1],2,SMBUS_LAST_FRAME_NO_PEC);
while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

if(return_value != HAL_OK)
{
return return_value;
}
if ((data_read[2] & 0x80) == 0x80)
{
return HAL_ERROR;
}

aux = data_read[1] + (data_read[2] << 8);
ambient_temperature = aux * 0.02 - 273.15;
mysensor->local_temperature = ambient_temperature;

data_read[0] = MLX90614_TOBJ1;
return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1,MLX90614_ADDRESS,&data_read[0],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,&data_read[1],2,SMBUS_LAST_FRAME_NO_PEC);
while(HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);

if(return_value != HAL_OK)
{
return return_value;
}
if ((data_read[2] & 0x80) == 0x80)
{
return HAL_ERROR;
}

aux = data_read[1] + (data_read[2] << 8);
ir_temperature = aux * 0.02 - 273.15;
mysensor->ir_temperature = ir_temperature;

return return_value;
}

The interrupt handler:
Code: [Select]
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_3);
millis++;
if(millis >= 999)
{
millis = 0;
print = 1;
}
}
}

Part of the main cycle:
Code: [Select]
(...)
while (1)
{
if(print == 1)
{
if(MLX90614_ReadData(mymlx90614) == HAL_OK)
{
sprintf(msg_send,"Local temperature: %.2f IR Temperature: %.2f\r\n",mymlx90614->local_temperature,mymlx90614->ir_temperature);
HAL_UART_Transmit(&huart2, (uint8_t*)msg_send, strlen(msg_send), 0xFFFF);
}
print = 0;
}
}
(...)

Timer 2 configuration:
Code: [Select]
static void MX_TIM2_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 31;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

If I comment the function call in the while loop the led blinks every 1ms or so. If I don't the led blinks every 4ms.
I sincerely do not know what is going on.

I'm using the internal clock (32MHz), a prescaler of 32 and a counter period of 1000. That should result in an interrupt every 1ms.

Do the I2C interrupts interact in some way with the Timer interrupts?

Thank you again,
Miguel
« Last Edit: June 19, 2018, 01:41:32 pm by MAntunes »
 

Offline MAntunesTopic starter

  • Regular Contributor
  • *
  • Posts: 99
  • Country: pt
Re: STM32 - SMBUS and sprintf with floats
« Reply #7 on: June 19, 2018, 03:12:30 pm »
Another question:

Is there any way of knowing the internal clock? Can I route it to a Pin so I can check it the oscilloscope?
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 3683
  • Country: us
Re: STM32 - SMBUS and sprintf with floats
« Reply #8 on: June 20, 2018, 12:05:19 am »
I am not famiar with STM but I doubt there is a way to route the internal clock to an external pin.  You should be able to use a PWM pin to produce a divided copy of the clock.
 

Offline Leiothrix

  • Regular Contributor
  • *
  • Posts: 104
  • Country: au
Re: STM32 - SMBUS and sprintf with floats
« Reply #9 on: June 20, 2018, 01:29:35 am »
Are the variables used in the ISR (millis and print) declared volatile?
 

Offline MAntunesTopic starter

  • Regular Contributor
  • *
  • Posts: 99
  • Country: pt
Re: STM32 - SMBUS and sprintf with floats
« Reply #10 on: June 20, 2018, 01:20:00 pm »
Are the variables used in the ISR (millis and print) declared volatile?
Yes, they are!

I really don't know what else to try... This is getting me crazy!  |O
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14297
  • Country: fr
Re: STM32 - SMBUS, Timers and other questions
« Reply #11 on: June 20, 2018, 04:50:04 pm »
To pinpoint whether it could come from your MLX90614_ReadData() function or from the sprintf() or HAL_UART_Transmit() calls, have you tried keeping the call to MLX90614_ReadData() and commenting out both sprintf() and HAL_UART_Transmit()? Then you can go from there to try and find out what chunk of code could be the culprit? Can be a bit tedious but it will help looking in the right direction.
 

Online Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3321
  • Country: nl
Re: STM32 - SMBUS, Timers and other questions
« Reply #12 on: June 22, 2018, 04:30:12 pm »
When having doubt wether a problem is in the software or in an external chip, my first go to is a logic analyser to snif the data on the communication bus.
I never really appreaciated how badly I needed that untill I bought one (some).
It transforms a lot of guesswork into knowing.

Search Ali / Ebay / China for "24m 8ch", and use it with the Excellent Sigrok / Pulseview software.
[urlhttps://sigrok.org/][/url]
I do have a Rigol DS1052E oscilloscope, but for debugging stuff like that such a logic analyser is much more usefull.
And because they only cost about EUR 5 there really is no excuse to not buy one.
If you grow out of the capabilities of it, you can buy more capable hardware, but don't be fooled by the low price of those boxes. They are plenty for debugging almost any serial protocol upto and including low speed USB (1.5mbps) and the many protocol decoders build into Pulseview are extremely handy.
 

Offline MAntunesTopic starter

  • Regular Contributor
  • *
  • Posts: 99
  • Country: pt
Re: STM32 - SMBUS, Timers and other questions
« Reply #13 on: June 26, 2018, 01:04:50 pm »
To pinpoint whether it could come from your MLX90614_ReadData() function or from the sprintf() or HAL_UART_Transmit() calls, have you tried keeping the call to MLX90614_ReadData() and commenting out both sprintf() and HAL_UART_Transmit()? Then you can go from there to try and find out what chunk of code could be the culprit? Can be a bit tedious but it will help looking in the right direction.

To pinpoint whether it could come from your MLX90614_ReadData() function or from the sprintf() or HAL_UART_Transmit() calls, have you tried keeping the call to MLX90614_ReadData() and commenting out both sprintf() and HAL_UART_Transmit()? Then you can go from there to try and find out what chunk of code could be the culprit? Can be a bit tedious but it will help looking in the right direction.

Thank you very much. I ended up using the HAL_GetTick() function and it started working fine.

Right know I'm dealing with another problem (I know, another problem) this time about the CAN bus. The problem can be seen here: https://community.st.com/thread/51211-cant-send-can-message-mailboxes-always-full
If anyone knows anything about CANbus in STM32 please give me some help. This is driving me crazy....

The CAN mailboxes are always full, even without sending any message...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf