2021-02-02 06:19 PM
Hi,
I am trying to setup the TIM1 of the STM32F410CBT microcontroller so that TIM1->CNT can measure Channel A and Channel B of a Quadrature Encoder Interface of a motor (the Encoder's datasheet is here, and it came attached with this motor here).
I have played with the TIM1 in Encoder Mode for a bit (based on several tutorials out there), and have scoped out the encoder's Channels A and B to see what the Quadrature Encoder signals look like. Here is a reference image:
In the image above, purple is Channel A, green is Channel B, and yellow indicates STEP signals (going into a motor driver that will increment the motor), and the blue signal indicates DIR (direction of rotation, where high indicates counterclockwise rotation, and low indicates clockwise rotation). The DIR output from the microcontroller also goes into the Motor Driver.
Here is my initialization code for setting up TIM1 in Encoder Mode:
/* TIM1 init function */
void MX_TIM1_Init(void)
{
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 10;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 10;
if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
I would like some clarification on some of the configurations above, particularly the ICxPolarity, ICxSelection, ICxPrescaler, and ICxFilter. I have also set it up as TIM_ENCODERMODE_TI12 as it receives input from two channels, and this is the same as setting up SMS (slave mode selection) into SMS = 011: Encoder Mode 3 in the Reference Manual.
#define TIM_ICSELECTION_DIRECTTI TIM_CCMR1_CC1S_0 /*!< TIM Input 1, 2, 3 or 4 is selected to be
connected to IC1, IC2, IC3 or IC4, respectively */
#define TIM_ICSELECTION_INDIRECTTI TIM_CCMR1_CC1S_1 /*!< TIM Input 1, 2, 3 or 4 is selected to be
connected to IC2, IC1, IC4 or IC3, respectively */
#define TIM_ICSELECTION_TRC TIM_CCMR1_CC1S /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC */
I also have a question that is not related to understanding the parameters/configurations above. If I pass one rising edge signal to the STEP input port of the Motor Driver that drives the Motor itself, TIM1->CNT actually increments by two and not by one. Is there a reason why the TIM1->CNT register increases by two with a single step increase?
Any advice would be greatly appreciated. Thank you!
Solved! Go to Solution.
2021-02-02 07:23 PM
The primary information source is the RM, so start with reading the TIM chapter there.
> ICxPolarity
In Encoder mode, it does not select edge, but inverts signal. Read description of TIMx_CCER.CCxP.
> ICxSelection
Not used for Encoder, only for capture. Read description of TIMx_CCMRx.CCxS and the Capture/compare channels subchapter.
>ICxPrescaler
Not used for Encoder, only for capture.
> ICxFilter
> needs to see 10 samples of the same value on either channels for it to be considered valid?
Yes. It the of course also limits the maximum usable input frequency/pulse lengths.
> Is this used for debouncing
Yes.
> Is there a reason why the TIM1->CNT register increases by two with a single step increase?
You've probably selected Encoder Mode 3 (hard to tell from the Cube/HAL gibberish), where there's a count upon every edge on either channel. Read Encoder interface mode subchapter.
JW
2021-02-02 07:23 PM
The primary information source is the RM, so start with reading the TIM chapter there.
> ICxPolarity
In Encoder mode, it does not select edge, but inverts signal. Read description of TIMx_CCER.CCxP.
> ICxSelection
Not used for Encoder, only for capture. Read description of TIMx_CCMRx.CCxS and the Capture/compare channels subchapter.
>ICxPrescaler
Not used for Encoder, only for capture.
> ICxFilter
> needs to see 10 samples of the same value on either channels for it to be considered valid?
Yes. It the of course also limits the maximum usable input frequency/pulse lengths.
> Is this used for debouncing
Yes.
> Is there a reason why the TIM1->CNT register increases by two with a single step increase?
You've probably selected Encoder Mode 3 (hard to tell from the Cube/HAL gibberish), where there's a count upon every edge on either channel. Read Encoder interface mode subchapter.
JW
2021-02-03 02:31 PM
Hi,
Thanks for the explanation, that was very helpful! Could you explain a bit more about how ICxFilter limits the maximum usable input frequency/pulse lengths? If the ICxFilter value is large, does that mean that the Channels A and B transitions and settling time must be longer?
I also saw a picture in page 306 of the Reference Manual where TI1 and TI2 can have jitter, and the TIM1 Counter seems to also show that jitter based on TI1 and TI2 signals. If this is the case, will it affect the timing requirements when reading from TIM1->CNT? If there is jitter when reading TIM1->CNT exactly after the motor moves (and the encoder produces signals), would I need some small delay before reading TIM1->CNT?
Thanks!
2021-02-04 09:37 AM
> how ICxFilter limits the maximum usable input frequency/pulse lengths
The filter basically means, that in case of input level change, the new level has to be stable for time set for the filter, until it gets "accepted" and passed further into the circuit.
In other words, if the input signal changes e.g. from 0 to 1 and then back to 0 sooner than the set filter time elapses, this change gets completely ignored.
In other words, pulses shorter than the set time get completely ignored.
> TI1 and TI2 can have jitter, and the TIM1 Counter seems to also show that jitter
Encoders are constructed so that when one signal changes the other is stable. So, if one signal is stable and the other oscillates, the counter oscillates between two consecutive values.
> If there is jitter when reading TIM1->CNT exactly after the motor moves (and the encoder produces signals), would I need some small delay before reading TIM1->CNT?
This is upon your decision. There is a delay between the "step" command and the moment when the driver outputs levels needed to move the motor, delay between this and the physical movement of the motor, there may be delay in the encoder between sensing input and changing its output, and the input filter on STM32 timer channel as described above imposes in fact another delay.
JW
2021-02-04 06:37 PM
From what I am understanding regarding your explanation on the ICxFilter, if I have for example some noise on the TI1 channel similar to the diagram below, where TI1 seems to have noise before settling for around y milliseconds, and the IC1Filter = x, seems to observe TI1 at the time period where TI1 was unstable:
The TIM1->CNT register will only count 3 pulses (one rising edge from TI2, and two falling edges from TI1 and TI2) and will only reflect 3 increments, even though TI1 goes high (and is stable at high) for y ms after the noise? Is my understanding correct?
Or, since the rising edge was disregarded, the time TI1 was high will be completely disregarded (STM32 will see TI1 as just flat 0V), and the TI2 pulses would also be ignored and considered as jitter since TI1 is flat? This would mean that TIM1->CNT did not increment at all?
"Encoders are constructed so that when one signal changes the other is stable. So, if one signal is stable and the other oscillates, the counter oscillates between two consecutive values." -> this seems to make sense to me. I noticed that sometimes TIM1->CNT can report a value, for example 1025, and then go back to 1024 in less than a second. I am also setting up the Encoder as Encoder Mode 3 (SMS=011).
Thanks!