cancel
Showing results for 
Search instead for 
Did you mean: 

32bit quadrature encoder

garzarolli
Associate II
Posted on March 04, 2010 at 23:16

32bit quadrature encoder

6 REPLIES 6
darcy23
Associate II
Posted on May 17, 2011 at 13:42

Goddam forum threw an exception (three times) and lost my reply.  Fix this bloody thing guys!  Enough of us have been complaining about it.  It's a real disincentive to start all over again

This method will mean you don't need to sacrifice a timer.  I'd make it a very high priority interrupt

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

void TIM2_IRQHandler(void)

{

    uint16_t    snap = TIM2->CNT;

    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

    if ( snap < 0x7FFF )

        rotary_encoder_control.encoder_total_count_tracker += (sint32_t)0xFFFF;        //Roll over in upwards direction (high, then reset to low)

    else

        rotary_encoder_control.encoder_total_count_tracker -= (sint32_t)0xFFFF;        //Roll over in downwards direction (low, then reset to high)

    rotary_encoder_control.encoder_count_interrupt_catcher = false;

}

In the function that retrieves the encoder count

    do

    {

        //encoder_count_interrupt_catcher is set to false in the interrupt that modifies encoder_total_count_tracker

        //  If this process is interrupted by that interrupt we should detect it with the while condition below and

        //  take another snapshot of the values

        rotary_encoder_control.encoder_count_interrupt_catcher = true;

        snap_tracker = rotary_encoder_control.encoder_total_count_tracker;

        snap_counter = TIM2->CNT;

    } while ( rotary_encoder_control.encoder_count_interrupt_catcher == false );

    result = snap_tracker + (sint32_t)snap_counter;

Darcy

Singh.Harjit
Senior II
Posted on May 17, 2011 at 13:42

I like how you have created a ''lock'' around the counter read and the upper word increment. I implemented the same functionality but I like your implementation better.

 

One question - shouldn't the 0xFFFF be ''0x10000'' since the overflow happens at 0x10000 (65536) pulses?

Harjit

darcy23
Associate II
Posted on May 17, 2011 at 13:42

Looking at that, yes, it probably should inc/dec by 0x10000  :)

davidwalker9
Associate II
Posted on May 17, 2011 at 13:42

I haven't tried this yet, but does the STM32 support the STREX instruction? If so you could replace the access to the wrapped count as

do {

  snap_tracker = __LDREX(&rotary_encoder_control.encoder_total_count_tracker);

  result = snap_tracker + (sint32_t)TIM2->CNT;

} while (__STREX(snap_tracker, &rotary_encoder_control.encoder_total_count_tracker);

If the tracker is touched in between the LDREX and STREX instructions by the ISR the operation will be retried.

Tomas DRESLER
Senior II
Posted on May 17, 2011 at 13:42

It does have LDREX/STREX.

Thanks for this clever idea :)

Btw. it's not possible by HW, there is no direction link between timers, except (probably) paralelizing the timers and setting the second one a prescaler by 32768 - and getting 31 bits. Never tested, though.
jveith
Associate II
Posted on July 28, 2012 at 17:25

Edison wrote:

Btw. it's not possible by HW, there is no direction link between timers, except (probably) paralelizing the timers and setting the second one a prescaler by 32768 - and getting 31 bits. Never tested, though.

Seems not working. I tried to use the prescaler as electronic gear to switch the rotary encoder between mm and cm. User must not use the prescaler in encoder mode. In case of changing the rotary direction, the counter cannot follow the wheel becouse the prescaler generates a ''dead zone''. Reversing the direction several times, moves the index reference more and more away.