cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103V8 TIM3 Encoder only counts one direction

DP_42
Associate II

Hello,

I'm working on a STM32F103V8. The TIM3 should decode the signal of a rotary decoder.
When I turn the rotary decoder clockwise the counter of TIM3 goes up.
When I turn the rotary decoder anticlockwise the counter of TIM3 goes up.

The MX_TIM3_Init is auto generated:

 

static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 65535;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 1;
  sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 1;
  if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */


  /* USER CODE END TIM3_Init 2 */

}

 

 The start of the Encoder looks like this.

 

void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */

	HAL_StatusTypeDef retVal;
	retVal = HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
	volatile int32_t i;

	for(;;)
	{
		i = TIM3->CNT;
		osDelay(100);
	}
  /* USER CODE END 5 */
}

 

I read the value of "i" via a Dynamic Printf while debugging.

I found a post on another forum with the same problem. They solved it by using TIM1... 

Hopefully someone can help me.

1 ACCEPTED SOLUTION

Accepted Solutions
DP_42
Associate II

As @waclawek.jan suggested:

I observed the waveforms of the rotary decoder. (see images: clockwise/anticlockwise)

pic_71_2.bmppic_71_3.bmp

the waveform look as expected.

Afterwards I checked on the GPIOA->IDR.

First a enabled the TIM3 global interrupt and implemended the callback.

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	uint32_t i = GPIOA->IDR;
	uint8_t j,y;
	j = (i&GPIO_PIN_6)?1:0;
	y = (i&GPIO_PIN_7)?1:0;
	(void)j;
	(void)y;
	return;
}

I started the TIM Encoder with 

HAL_TIM_Encoder_Start_IT(&htim3, TIM_CHANNEL_ALL);

Inside the HAL_TIM_IC_CaptureCallback function i used a dynamic printf to read the inputs of the pins PA6 and PA7. Those are the signals TIM3 Ch1 & Ch2.

I saw that one singal was stuck to "1". This is the reason why the counter only counts in one direction.

I checked the wiring and found that the wiring was based on an old scematic. After fixing that the counter worked as expected.

TDLR; Wrong wiring of the rotary encoder.

 

View solution in original post

3 REPLIES 3

Observe waveforms on the two input pins using oscilloscope or logic analyzer. Or, read out and vizualize the GPIOx_IDR register, on which the two input pins are located.

Is the waveform as expected, i.e. with 90deg. phase shift in one direction and -90deg in other?

Aren't the inputs shorted?

JW

Sarra.S
ST Employee

Hello @DP_42

Why did you set both IC1Polarity and IC2Polarity to TIM_ICPOLARITY_FALLING? This means that the timer is configured to count on the falling edge of both inputs.

If the encoder is generating signals such that both channels have falling edges when rotating in either direction, this could be the issue! 

Try to adjust the polarity settings to count on the rising edge and the other on the falling edge

 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

DP_42
Associate II

As @waclawek.jan suggested:

I observed the waveforms of the rotary decoder. (see images: clockwise/anticlockwise)

pic_71_2.bmppic_71_3.bmp

the waveform look as expected.

Afterwards I checked on the GPIOA->IDR.

First a enabled the TIM3 global interrupt and implemended the callback.

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	uint32_t i = GPIOA->IDR;
	uint8_t j,y;
	j = (i&GPIO_PIN_6)?1:0;
	y = (i&GPIO_PIN_7)?1:0;
	(void)j;
	(void)y;
	return;
}

I started the TIM Encoder with 

HAL_TIM_Encoder_Start_IT(&htim3, TIM_CHANNEL_ALL);

Inside the HAL_TIM_IC_CaptureCallback function i used a dynamic printf to read the inputs of the pins PA6 and PA7. Those are the signals TIM3 Ch1 & Ch2.

I saw that one singal was stuck to "1". This is the reason why the counter only counts in one direction.

I checked the wiring and found that the wiring was based on an old scematic. After fixing that the counter worked as expected.

TDLR; Wrong wiring of the rotary encoder.