STM32 - SMBUS, Timers and other questions - Page 1
Forum section: electronics / general

author: MAntunes
author_rank: Regular Contributor
timestamp: June 05, 2018, 11:33:01 am
content: 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:#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 & 0x80) == 0x80){return HAL_ERROR;}aux = data_read + (data_read << 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

author: Gibson486
author_rank: Frequent Contributor
timestamp: June 05, 2018, 01:24:19 pm
content: Are you trying to print ambient_temperature?https://www.tutorialspoint.com/c_standard_library/c_function_sprintf.htmAre 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".

author: ejeffrey
author_rank: Super Contributor
timestamp: June 05, 2018, 01:53:03 pm
content: 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

author: MAntunes
author_rank: Regular Contributor
timestamp: June 05, 2018, 02:08:03 pm
content: Quote from: ejeffrey on June 05, 2018, 01:53:03 pmThank you. I'll try this.Quote from: Gibson486 on June 05, 2018, 01:24:19 pmYou're right, I got lost in copying the code.And yes, that's one the variables I'm trying to put in string.

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 05, 2018, 02:31:20 pm
content: 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:uint8_t RAMAddress = MLX90614_TA;return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1, MLX90614_ADDRESS, &RAMAddress, 1, SMBUS_FIRST_FRAME);

author: MAntunes
author_rank: Regular Contributor
timestamp: June 05, 2018, 03:28:38 pm
content: Quote from: SiliconWizard on June 05, 2018, 02:31:20 pmThanks a lot. It was indeed that problem that was causing some errors in my code.

author: MAntunes
author_rank: Regular Contributor
timestamp: June 19, 2018, 01:24:24 pm
content: 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:HAL_StatusTypeDef MLX90614_ReadData(struct MLX90614 *mysensor){HAL_StatusTypeDef return_value;uint8_t data_read;uint16_t aux;float ambient_temperature;float ir_temperature;data_read = MLX90614_TA;return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1,MLX90614_ADDRESS,&data_read,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,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 & 0x80) == 0x80){return HAL_ERROR;}aux = data_read + (data_read << 8);ambient_temperature = aux * 0.02 - 273.15;mysensor->local_temperature = ambient_temperature;data_read = MLX90614_TOBJ1;return_value = HAL_SMBUS_Master_Transmit_IT(&hsmbus1,MLX90614_ADDRESS,&data_read,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,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 & 0x80) == 0x80){return HAL_ERROR;}aux = data_read + (data_read << 8);ir_temperature = aux * 0.02 - 273.15;mysensor->ir_temperature = ir_temperature;return return_value;}The interrupt handler:Code: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:(...)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: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

author: MAntunes
author_rank: Regular Contributor
timestamp: June 19, 2018, 03:12:30 pm
content: 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?

author: ejeffrey
author_rank: Super Contributor
timestamp: June 20, 2018, 12:05:19 am
content: 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.

author: Leiothrix
author_rank: Regular Contributor
timestamp: June 20, 2018, 01:29:35 am
content: Are the variables used in the ISR (millis and print) declared volatile?

author: MAntunes
author_rank: Regular Contributor
timestamp: June 20, 2018, 01:20:00 pm
content: Quote from: Leiothrix on June 20, 2018, 01:29:35 amYes, they are!I really don't know what else to try... This is getting me crazy!

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 20, 2018, 04:50:04 pm
content: 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.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: June 22, 2018, 04:30:12 pm
content: 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/]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.

author: MAntunes
author_rank: Regular Contributor
timestamp: June 26, 2018, 01:04:50 pm
content: Quote from: SiliconWizard on June 20, 2018, 04:50:04 pmQuote from: SiliconWizard on June 20, 2018, 04:50:04 pmThank 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-fullIf 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...