cancel
Showing results for 
Search instead for 
Did you mean: 

Measure time between encoder counts

benkatz
Associate
Posted on March 06, 2016 at 07:39

Hello,

I'm trying to measure the period between counts on a quadrature encoder while simultaneously keeping count.

I'm using an F446 on a Nucleo dev board (for now), and using mbed for compiling. I've got keeping track of the encoder count working just fine on PA0 and PA1, TIM2. Basically, I'd like to store the count of a free-running timer every time TIM2->CNT changes value (i.e. whenever there's a rising or falling edge on either encoder channel)

According to the reference (RM0090, p609), ''You can obtain dynamic information (speed, acceleration, deceleration) by measuring the period between two encoder events using a second timer configured in capture mode.'', but I don't really know how to go about this. The pins are set up for alternate function 1 (attached to TIM2_CH1 and TIM2_CH2), so I don't know how to also attach them to another timer for input capture.

Any advice about how to do this would be greatly appreciated!

Thanks

Here's my encoder setup code, for reference:

RCC->AHB1ENR |= 0x00000001; // Enable clock for GPIOA

GPIOA->MODER |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER1_1 ; //PA0, PA1 as Alternate Function

GPIOA->OTYPER |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 ; //PA0, PA1 as Inputs

GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0 | GPIO_OSPEEDER_OSPEEDR1 ;

GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_1 | GPIO_PUPDR_PUPDR1_1 ; // Pull Down

GPIOA->AFR[0] |= 0x00000011 ; // AF01 for PA0, PA1

// configure TIM2 as Encoder input

RCC->APB1ENR |= 0x00000001; // Enable clock for TIM2

TIM2->SMCR = 0x0003; // SMS='011' (Encoder mode 3) <

TIM

slave mode control register

TIM2->CCMR1 = 0xf1f1; // CC1S='01' CC2S='01' <

TIM

capture/compare mode register 1

TIM2->CCMR2 = 0x0000; // <

TIM

capture/compare mode register 2

TIM2->CCER = 0x0011; // CC1P CC2P <

TIM

capture/compare enable register

TIM2->PSC = 0x0000; // Prescaler = (0+1) <

TIM

prescaler

TIM2->ARR = 0xffffffff; // reload at 0xfffffff <

TIM

auto-reload register

TIM2->CNT = 0; //reset the counter before we use it

TIM2->CR1 = 0x01; // CEN(Counter ENable)='1'

#stm32 #tim #encoder

4 REPLIES 4
Posted on March 06, 2016 at 16:37

Well I suspect the way forward is to set up a Master-Slave relationship, where the TRGO of TIM2 feeds to the ITRx of another free running counter, gate that to TRC to latch the CNT to CCRx of that counter, effectively time stamping the arrival. Review timer block diagrams in the Reference Manual RM0090 if these relationships are unclear.

One might also be able to trigger a DMA action reading a free running counter, and time stamp things that way.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
benkatz
Associate
Posted on March 07, 2016 at 07:12

Thanks for the help! Seem to have things working.

Master Mode Selection for TIM2 set to Compare Pulse :

TIM2->CR2 = 0x030; //MMS = 101

TIM8 Triggering on ITR2 (TIM2), SMS in Reset Mode:

TIM8->SMCR = 0x94; //TS = 010 for ITR2, SMS = 100

TIM8 Capture/Compare 1 Selection to TRC

TIM8->CCMR1 = 0x3;// CC1S = 11, IC1 mapped on TRC

Trigger on rising edge:

TIM8->CCER |= TIM_CCER_CC1P;

Enable Output:

TIM8->CCER |= TIM_CCER_CC1E;

so TIM8->CNT gets stored in TIM8->CCR1 when triggered by TIM2
Siragh ASUTP
Associate II
Posted on November 25, 2016 at 20:44

Hi

I am trying to measure the period (TIM2 encoder mode, TIM4-Reset), but the register CNT TIM4 constantly changing, even in the case where the encoder is stationary. Why is this happening?

Posted on November 25, 2016 at 23:58

If TIM4 is a free running counter you expect to use to time stamp the period you'd better hope it keeps counting up.

Perhaps you can describe your configuration details with a little more specificity

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..