cancel
Showing results for 
Search instead for 
Did you mean: 

About STM32F103; Timer and Encoder

TFern
Associate III

Hi Colleagues,

I am just trying STM32F103 using Encoder in TIM3. I am able to count the pulses and direction ; prima facie it looks fine.I am using the STM32 CubeIDE for configuring the parameters. I have a few questions though :

1) I need to compute the speed of the pulse.

Is it possible to use the same TIM3 in timer interrupt mode,viz with HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) callback function and calculate the speed by measuring the difference in counts between timer interrupts.

Or is it possible to use the same TIM3 in Input Capture Direct mode without using any additional pins ?

2) Is there an interrupt generated whenever the CounterPeriod ARR overflows ?I could not locate the Callback function for this.

3)Is there a bit which indicates the direction of rotation ? I am using

EncoderCntr = TIM3->CNT; and the counts increment/decrement as expected.

4)How to calculate the maximum speed of the encoder before pulses start to get dropped while counting.

I was just hoping for some quick answers while I do my own digging into the docs :) !!

Cheers !

5 REPLIES 5

The timer has only one counter, i.e. once it counts the encoder pulses, it can't simultaneously run out of the internal clock.

To measure speed, you need to connect one of the encoder outputs to another timer, either externally, out internally using the timers' master-slave connection.

While you can use TIM3's Update interrupt to detect counter over/underflow, I won't recommend it, as rapid direction reversal at that point may lead to confusion. Use periodic readouts instead, inferring over/underflow from the read values.

Current direction is indicated in TIMx_CR1.DIR.

Maximum speed is given by the need of edges to be separated by at least one internal clock period. Take into account also any input filtering you set.

Read the TIM chapter in Reference Manual.

I don't Cube.

JW

berendi
Principal

1. To calculate the speed, you have to read the counter periodically (e.g. from the SysTick interrupt) and calculate the speed from the difference. More precision can be achieved by reading the counter with a DMA request triggered by another timer. Hardware methods won't work, anything I can think of would be fooled if the wheel is almost stopped, and oscillating around a single position.

2. It is called update interrupt, it can be generated by setting the UIE bit in TIM3->DIER. There should be a HAL interface to do this, but I'm not surprised that you couldn't find it, HAL is very poorly documented (one of the reasons I don't use it).

TIM3->DIER |= TIM_DIER_UIE;
NVIC_EnableIRQ(TIM3_IRQn);

Then the interrupt handler must examine and clear the update interrupt flag.

void TIM3_IRQHandler(void) {
  uint32_t sr = TIM3->SR;
  if(sr & TIM_SR_UIF) {
    TIM3->SR = ~TIM_SR_UIF;
    /* do whatever needs to be done at counter overflow */
  }
}

3. There is no such flag, but it should be possible to create one with DMA (I haven't tried it, but I'm quite sure that it would work). However, because of the unfortunate DMA request map of the STM32F1, it would actually work on TIM1, TIM2 or TIM4, but not on TIM3. (It requires a DMA request on one of the inputs, not shared by the trigger).

 

Find the DMA channel for timer channel 1 in the DMA request mapping table of the reference manual.

 

Configure the DMA channel to transfer a 32-bit word from the IDR register of the GPIO port where the channel 2 pin in located to a volatile uint32_t variable in circular mode: CNDTR=1, CPAR=&GPIOx->IDR, CCR=DMA_CCR_MSIZE_1 | DMA_CCR_PSIZE_1 | DMA_CCR_CIRC | DMA_CCR_EN, CMAR=the address of the variable.

 

Enable capture on channel 1 (TIM_CCER_CC1E) and DMA request generation (TIM_DIER_CC1DE).

 

Now DMA will copy the pin state of the channel 2 pin on every rising edge of channel 1. Direction of counting depends on the state of the other pin, so the bit value at the pin position in the DMA target variable will reflect the direction of counting at the last edge on channel 1.

4. The timer samples its inputs once in every timer clock cycle (which usually equals the system clock frequency on the STM32F1, but check your clock setup). It will work as long as the frequency of changes in the combined input state is less than the timer clock frequency.

Hi Jan,

Thanks much for your answers !

While you can use TIM3's Update interrupt to detect counter over/underflow, I won't recommend it, as rapid direction reversal at that point may lead to confusion. Use periodic readouts instead, inferring over/underflow from the read values.

I thought of the same. I thought of a possible issue with that...

eg. Suppose I have loaded the ARR register with 1000.If the current value is 900, and the next value is 300.How is one to know if the encoder overflowed, or if the encoder rotated in the opposite direction. Presumably one can check the direction bit with TIMx_CR1.DIR ?

To measure speed, you need to connect one of the encoder outputs to another timer, either externally, out internally using the timers' master-slave connection.

If i connect externally, I would probably have to use an extra uC pin ? If internally using the timer's master-slave avoids this, I guess that would be the way to go.

Read the TIM chapter in Reference Manual.

I will.

Thanks again.

Hi Berendi,

Thanks for your reply.

There is a strike through on your Point3. Is it intentional ?

Thanks.

Yes, I've just noted that @JW has an one-liner answer to your 3) question, which makes my complicated solution unnecessary.