cancel
Showing results for 
Search instead for 
Did you mean: 

Rotary Encoder Application

JPanc.1
Associate II

I am using STM32F103C8T6 for counting rotary encoder pulse.

My Encoder PPR is 5000.

But when I program for timer1 as encoder mode and show count on segment it shows 20000 pulse per rotation it is 4 times higher than the actual value. What should I do to get exact value of pulses.???

And another question is how to get interrupt after particular no. of pulses??

I am sharing my code for reference.

*/*****************Timer Interrupt******************************/*
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(htim);
  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
  /* NOTE : This function Should not be modified, when the callback is needed,
            the __HAL_TIM_IC_CaptureCallback could be implemented in the user file
   */
}
*/*****************Main Function******************************/*
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
  
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin,GPIO_PIN_RESET);
  HAL_TIM_Base_Start_IT(&htim1);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint32_t temp;
  uint16_t DG[6];
  while (1)
  {
    /* USER CODE END WHILE */
	  temp = TIM1->CNT;
	  for(char i=0; i<6; i++)
	  {
		 DG[i] = temp%10;
		 temp = temp/10;
	  }
	  writeDisplayUP(DDG[DG[5]],DDG[DG[4]],DDG[DG[3]],DDG[DG[2]],DDG[DG[1]],DDG[DG[0]]);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
*/*****************Timer as Encoder Mode Init******************************/*
static void MX_TIM1_Init(void)
{
 
  /* USER CODE BEGIN TIM1_Init 0 */
 
  /* USER CODE END TIM1_Init 0 */
 
  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
  /* USER CODE BEGIN TIM1_Init 1 */
 
  /* USER CODE END TIM1_Init 1 */
  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_FALLING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 5;
  sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 5;
  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();
  }
  /* USER CODE BEGIN TIM1_Init 2 */
 
  /* USER CODE END TIM1_Init 2 */
 
}

1 ACCEPTED SOLUTION

Accepted Solutions

> What should I do to get exact value of pulses.???

Divide by 4. The encoder mode counts all edges on both channels, not pulses. You can also chose encoder mode 1 or 2, which would count edges only on one channel, that would then result in number twice as high as the number of pulses.

> And another question is how to get interrupt after particular no. of pulses??

This is not simple for the generic case of changing direction, but you can easily get interrupt at a given state of the counter, just set some of the unused channels (CH3, CH4) as output compare, set the required level in the respective CCRx and enable interrupt from that channel.

For the generic case of counting *pulses*, you would need to connect the signal to an other timer, either externally, using up a pin, or internally, through the master-slave mechanism.

JW

View solution in original post

3 REPLIES 3

> What should I do to get exact value of pulses.???

Divide by 4. The encoder mode counts all edges on both channels, not pulses. You can also chose encoder mode 1 or 2, which would count edges only on one channel, that would then result in number twice as high as the number of pulses.

> And another question is how to get interrupt after particular no. of pulses??

This is not simple for the generic case of changing direction, but you can easily get interrupt at a given state of the counter, just set some of the unused channels (CH3, CH4) as output compare, set the required level in the respective CCRx and enable interrupt from that channel.

For the generic case of counting *pulses*, you would need to connect the signal to an other timer, either externally, using up a pin, or internally, through the master-slave mechanism.

JW

This is not simple for the generic case of changing direction, but you can easily get interrupt at a given state of the counter, just set some of the unused channels (CH3, CH4) as output compare, set the required level in the respective CCRx and enable interrupt from that channel.

I didn't get this. Pls Help

And another question what if I require to interrupt at more than 65535 value i.e 80000???

Is there any way to do this?