cancel
Showing results for 
Search instead for 
Did you mean: 

Encoder mode and rotary encoder

Ariel G
Associate II
Posted on April 03, 2018 at 11:10

Hi,

I'm using STM32F072RB and a rotary encoder (with 30 dentet) connected to TIM2 in 'encoder mode' and I can see in TIM2->CNT that it is actually counting correctly.

I trying to get an interrupt on each detent rotation but unsuccessfully

To start the encoder in interrupt mode in the main function I'm using:

HAL_TIM_Encoder_Start_IT(&htim2, TIM_ENCODERMODE_TI2);

And the callback:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

{

if(htim->Instance == TIM2)

counterISR++;

}

but the counterISR is not equal to TIM2->CNT.

How to get an interrupt of each detent rotation? or what is the correct way to implement such thing?

Timer 2 init:

/* TIM2 init function */

static void MX_TIM2_Init(void)

{

TIM_Encoder_InitTypeDef sConfig;

TIM_MasterConfigTypeDef sMasterConfig;

htim2.Instance = TIM2;

htim2.Init.Prescaler = 0;

htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

htim2.Init.Period = 29;

htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

sConfig.EncoderMode = TIM_ENCODERMODE_TI2;

sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;

sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;

sConfig.IC1Prescaler = TIM_ICPSC_DIV1;

sConfig.IC1Filter = 0x0F;

sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;

sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;

sConfig.IC2Prescaler = TIM_ICPSC_DIV1;

sConfig.IC2Filter = 0x0F;

if (HAL_TIM_Encoder_Init(&htim2, &sConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

Note: this post was migrated and contained many threaded conversations, some content may be missing.
24 REPLIES 24
Posted on April 03, 2018 at 16:43

The encoder may be bouncing at the pulses boundaries and the filter you set may be insufficient. Try hardware filtering.

Nevertheless, in principle, the encoder when stopped, may oscillate on one of its inputs, that will cause mutliple interrupts, but the counter will correctly stay at one of two succeeding values.

JW

T J
Lead
Posted on April 04, 2018 at 01:15

Are you using Dials or Knobs ?

Some of us like Dials...

Posted on April 04, 2018 at 03:19

Mine go to 11

0690X00000604JNQAY.jpg
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Julien FAUCHER
Associate III
Posted on April 04, 2018 at 10:26

If i remember correctly, you just have to setup an interrupt on the Update event on your timer and then handle it like you would do for any interrupt.

I'm not familiar (at all) with HAL, but this is the event you should look for. (It's triggered on each timer value update)

EDIT : Also, could you tell us the ratio between 'counterISR' and TIM2->CNT ? 

Posted on April 04, 2018 at 08:59

Thank you I'll check that out

Posted on April 04, 2018 at 10:34

I don't understand what board are you meaning but I did connect the encoder with a low pass filter as suggested in the datasheet.

Posted on April 04, 2018 at 10:39

you mean to set an interrupt on timer overflow?

The ratio between counterISR and TIM2->CNT  is not constant, counterISR can move by 1/2/3 while TIM2->CNT move by 1 (constantly) on each step rotation