2021-07-26 03:36 AM
Hi,
I'm measuring a 40-60Hz frequency range from an input capture timer (STM32L475RCTX TIM4). The result is an expected calculation from 4000 to 6000 (40.00Hz-60.00Hz) using this initialization code:
static void MX_TIM4_Init(void)
{
/* USER CODE BEGIN TIM4_Init 0 */
/* USER CODE END TIM4_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
/* USER CODE BEGIN TIM4_Init 1 */
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 50-1;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 65535;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_IC_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
}
The frequency computation is performed in HAL_TIM_IC_CaptureCallback routine and here's the result form an input frequency of 50.00Hz:
The result is 5037 that means 50.37Hz and the 0.37Hz does not a problem so far. The problem is when I pause the execution, restart and resume it. Then the result sometimes falls in 5037 (the same result than before) but sometimes is 4965 as shown:
The result changes when I do a pause, restart (reset) and resume the execution from the IDE. How can I manage to always get the same frequency result after successive restart cycles?
regards,
gaston
Solved! Go to Solution.
2021-07-26 07:36 AM
2021-07-26 06:22 AM
I'm guessing ignoring the first edge might be helpful here. Try to do the calculation based on the second and third edges rather than the first and second.
2021-07-26 07:29 AM
Hi TDK,
In order to do as you've suggested I've changed the callback routine this way:
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef* htim){
if(htim->Instance == TIM4){
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){
//HAL_GPIO_TogglePin(ACPW_GPIO_Port, ACPW_Pin);
acqStruct.zcdFlg = true; // zero cross detector
if(acqStruct.uhCaptureIndex == 0){
// Get the 1st Input Capture value
acqStruct.uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
acqStruct.uhCaptureIndex = 1;
}
else{
if(acqStruct.uhCaptureIndex == 1){
// Get the 2nd Input Capture value
acqStruct.uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
acqStruct.uhCaptureIndex = 2;
}
else{
// ***********Get the 2nd Input Capture value
// Get the 3rd Input Capture value
acqStruct.uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
// Capture computation
if (acqStruct.uwIC2Value2 > acqStruct.uwIC2Value1){
acqStruct.uwDiffCapture = (acqStruct.uwIC2Value2 - acqStruct.uwIC2Value1);
}
else{
if (acqStruct.uwIC2Value2 < acqStruct.uwIC2Value1){
// 0xFFFF is max TIM4_CCRx value
acqStruct.uwDiffCapture = ((0xFFFF - acqStruct.uwIC2Value1) + acqStruct.uwIC2Value2) + 1;
}
else{
// If capture values are equal, we have reached the limit of frequency measures
//Error_Handler();
}
}
// Frequency computation: for this example TIMx (TIM4) is clocked by
// APB2Clk
acqStruct.Frequency = (HAL_RCC_GetPCLK2Freq() / acqStruct.uwDiffCapture);
//acqStruct.uhCaptureIndex = 0;
acqStruct.uhCaptureIndex = 1;
// Moving Average
acqStruct.avgFrequency = acqMovingAverage(&acqStruct.averageBuffer[ACQ_FRQ_IX][0], ACQ_N_AVERAGE, acqStruct.Frequency, ACQ_FRQ_IX) + 1;
}
}
}
}
}
But the result still changes after successive restart cycles. I wonder if there some method to determine the edge type (rising/fallling) in the callback routine. By the way, this problem appears when configuring Both Edges in Polarity Selection. If I select Rise Edge everything goes okay and the frequency result is stable for successive restart cycles.
gaston
2021-07-26 07:36 AM
2021-07-26 09:09 AM
Great! It solves my problem. Thank you for your help TDK.
I share the code using Input Capture with Both Edges implementation for the Frequency measurement.
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef* htim){
if(htim->Instance == TIM4){
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){
//HAL_GPIO_TogglePin(ACPW_GPIO_Port, ACPW_Pin);
acqStruct.zcdFlg = true; // zero cross detector
if(acqStruct.uhCaptureIndex == 0){
// Get the 1st Input Capture value
acqStruct.uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
acqStruct.uhCaptureIndex = 1;
}
else{
if(acqStruct.uhCaptureIndex == 1){
// Skip 2nd Input Capture value
acqStruct.uhCaptureIndex = 2;
}
else{
// Get the 3rd Input Capture value
acqStruct.uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
// Capture computation
if (acqStruct.uwIC2Value2 > acqStruct.uwIC2Value1){
acqStruct.uwDiffCapture = (acqStruct.uwIC2Value2 - acqStruct.uwIC2Value1);
}
else{
if (acqStruct.uwIC2Value2 < acqStruct.uwIC2Value1){
// 0xFFFF is max TIM4_CCRx value
acqStruct.uwDiffCapture = ((0xFFFF - acqStruct.uwIC2Value1) + acqStruct.uwIC2Value2) + 1;
}
else{
// If capture values are equal, we have reached the limit of frequency measures
//Error_Handler();
}
}
// Frequency computation: for this example TIMx (TIM4) is clocked by
// APB2Clk
acqStruct.Frequency = (HAL_RCC_GetPCLK2Freq() / acqStruct.uwDiffCapture);
acqStruct.uhCaptureIndex = 0;
// Moving Average
acqStruct.avgFrequency = acqMovingAverage(&acqStruct.averageBuffer[ACQ_FRQ_IX][0], ACQ_N_AVERAGE, acqStruct.Frequency, ACQ_FRQ_IX) + 1;
}
}
}
}
}
regards,
gaston