2020-01-12 12:16 PM
I have a simple and trivial question.
I read the registers of TIM3 in encoder mode in polling and so far everything is ok. The encoder is a normal panel encoder with knob.
I want my reading of the encoder register not to fall below a limit (this example: 4) and not to exceed an upper limit (example: 100, 240 0 600)
My serious problem is that I need to limit the reading when the encoder drops below 4 counts. The code I use is this:
else if(machine_mode == AUTO_MODE_WAITING)
{
// imposta il tempo di trattamento (solo encoder sx)
// ENCODER B (sezione sinistra!)
count2 = TIM3->CNT;
//LCD_LOCATE(1,1);
//LCD_printf("%3d",count2);
if(count2 > 40) count2 = TIM3->CNT = 40;
if(count2 < 4) count2 = TIM3->CNT = 4;
//LCD_LOCATE(1,1);
//LCD_printf("%3d",count2);
count2 /= 60;
count2 *=30;
__asm("CPSID i");
sec_total = count2;
min = sec_total / 60;
sec = sec_total - min*60;
sec_total_todo = sec_total;
first_auto_interval = sec_total / 3;
second_auto_interval = sec_total * 2 / 3;
LCD_LOCATE(2,12); // update minutes
printbytedec(min);
LCD_LOCATE(2,15); // update seconds
printbytedec(sec);
}
If the knob is turned normally towards 0 (CCW), the count is blocked at 4 and does not decrease further.
If the knob is turned very quickly towards 0 (CCW), often the encoder does not "fix" at 4, but counts further below, restarting from the upper module limit and the reading (count2) I find the is upper limit (that is 40).
How can I remedy the problem? The encoder is read in polling approximately every 100msec.
Here is my TIM3 initializiation routine in encoder mode: (I'm using STM32CubeMx)
/**
* @brief TIM3 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
LL_TIM_SetEncoderMode(TIM3, LL_TIM_ENCODERMODE_X4_TI12);
LL_TIM_IC_SetActiveInput(TIM3, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(TIM3, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(TIM3, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV2_N8);
LL_TIM_IC_SetPolarity(TIM3, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING);
LL_TIM_IC_SetActiveInput(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV2_N8);
LL_TIM_IC_SetPolarity(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);
TIM_InitStruct.Prescaler = 0;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 700;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM3);
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM3);
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
}
Many thanks for any suggestion and/or advice!
Max Mazza
2020-01-12 04:40 PM
With rapid turning, you probably get to reading the counter when it underflows (which in unsigned is >40).
Don't take the CNT as your output value and don't modify CNT.
Take signed difference betwen successive CNT readings, add this difference to your output variable and limit only that variable.
JW