cancel
Showing results for 
Search instead for 
Did you mean: 

Setting up TIM1 in Encoder Mode

RrW1
Associate III

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:

0693W000007DhROQA0.jpgIn 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.

  • Is the ICxPolarity used to sample rising edge/falling edge signals of Channel A or B? Since I am using TIM_ICPOLARITY_RISING, my TIM1 will only consider rising edges on both channels A and B to affect TIM1->CNT, that holds the position of the motor?
  • What is ICxSelection used for? I copied the description provided by the HAL library, but I still don't understand what it refers too. I am also using only IC1 and IC2 am I not?
#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 */

  • Is the ICxPrescaler used as a divisor for the number of rising edge (or falling edge or both events) that passes through Channels A or B? If, for example, I configured TIM1 to consider only rising edges, and the Divisor/Prescaler is 2, does that mean that Channel A or B needs to have two rising edges on them so that TIM1 would report a step increase of 1?
  • If I use an ICxFilter of 10 for both channels, does that mean that TIM1 needs to see 10 samples of the same value on either channels for it to be considered valid? Is this used for debouncing the quadrature signals (if the signals are noisy)?

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!

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

4 REPLIES 4

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

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!

> 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

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:

0693W000007E2fgQAC.jpgThe 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!