cancel
Showing results for 
Search instead for 
Did you mean: 

High resolution and fast Quadrature encoders on STM32F4

kongisme
Associate II
Posted on June 13, 2013 at 04:22

Dear everyone,

I'm using STM32F407 and I'm using quadrature encoder which is high resolution linear scale and maximum 2Mhz pulse speed.

When the encoder speed is over 400khz, the data is missing.

I would like to know the stm32f407's encoder performance. 

Is it possible to decode the high speed quadrature encoder, max 2Mhz ?

Thank you in advance.

#qei
7 REPLIES 7
Posted on June 13, 2013 at 04:58

I'm confused, what is the question?

You seem to be stating a tested fact, that >400KHz something is lost. What is being lost? Which counters/timers are you using? How are you testing this, the STM32F4 in parallel to some other counter which you later compare? You move some fixed/known distance? You send a pulse train from some programmable source?

I'm not much into quad encoder/decoders, but the timers should be capable of rates significantly above 400 KHz, I don't think you'd want to interrupt at that rate.

So may be you can cite some specific parts, and present a test framework, test cases, and input signal specification.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
kongisme
Associate II
Posted on June 13, 2013 at 05:35

Clive,

I'm using stm32F407 for quadrature encoder counter.

encoder counter is two by using TIM2 and TIM5 for 32bit timer count.

the gpio port are  gpioA15, gpioB3 for TIM2 and gpioA0, gpio A1 for TIM5.

I need to get the encoder count data up to X4.

My target linear scale encoder makes pulses every 0.5um and the moving speed is 1000mm/s.

When I tested, the count number is OK on 200mm/s speed. but the count number is not correct when the speed is 250mm/s.

So, I would like to the stm32f407's quadrature encoder counting ability.

Any Idears?

please let me have advice to solve this problem.

Thank you.

Here is the code

--------------------------------------------------------------------------

/* 

* definitions for the quadrature encoder pins 

*/

// Encoder 1. Channels 

#define ENCLA_PIN GPIO_Pin_15 

#define ENCLA_GPIO_PORT GPIOA 

#define ENCLA_GPIO_CLK RCC_AHB1Periph_GPIOA 

#define ENCLA_SOURCE GPIO_PinSource15 

#define ENCLA_AF GPIO_AF_TIM2

#define ENCLB_PIN GPIO_Pin_3 

#define ENCLB_GPIO_PORT GPIOB 

#define ENCLB_GPIO_CLK RCC_AHB1Periph_GPIOB 

#define ENCLB_SOURCE GPIO_PinSource3 

#define ENCLB_AF GPIO_AF_TIM2

// Encoder 2. Channels 

#define ENCRA_PIN GPIO_Pin_0 //GPIO_Pin_6 

#define ENCRA_GPIO_PORT GPIOA //GPIOB 

#define ENCRA_GPIO_CLK RCC_AHB1Periph_GPIOA 

#define ENCRA_SOURCE GPIO_PinSource0 

#define ENCRA_AF GPIO_AF_TIM5

#define ENCRB_PIN GPIO_Pin_1 //GPIO_Pin_7 

#define ENCRB_GPIO_PORT GPIOA //GPIOB 

#define ENCRB_GPIO_CLK RCC_AHB1Periph_GPIOA 

#define ENCRB_SOURCE GPIO_PinSource1 

#define ENCRB_AF GPIO_AF_TIM5

// determine the timers to use 

#define ENCL_TIMER TIM2 

#define ENCL_TIMER_CLK RCC_APB1Periph_TIM2 

#define ENCR_TIMER TIM5 

#define ENCR_TIMER_CLK RCC_APB1Periph_TIM5 

void main()

{

EncodersInit

( );

while();

}

void EncodersInit (void)

{

//GPIO_InitTypeDef GPIO_InitStructure; 

// turn on the clocks for each of the ports needed 

RCC_AHB1PeriphClockCmd (ENCLA_GPIO_CLK, ENABLE); 

RCC_AHB1PeriphClockCmd (ENCLB_GPIO_CLK, ENABLE); 

RCC_AHB1PeriphClockCmd (ENCRA_GPIO_CLK, ENABLE); 

RCC_AHB1PeriphClockCmd (ENCRB_GPIO_CLK, ENABLE);

// now configure the pins themselves 

// they are all going to be inputs with pullups 

GPIO_StructInit (&GPIO_InitStructure); 

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 

GPIO_InitStructure.GPIO_Pin = ENCLA_PIN;

GPIO_Init (ENCLA_GPIO_PORT, &GPIO_InitStructure); 

GPIO_InitStructure.GPIO_Pin = ENCLB_PIN; 

GPIO_Init (ENCLB_GPIO_PORT, &GPIO_InitStructure); 

GPIO_InitStructure.GPIO_Pin = ENCRA_PIN; 

GPIO_Init (ENCRA_GPIO_PORT, &GPIO_InitStructure); 

GPIO_InitStructure.GPIO_Pin = ENCRB_PIN; 

GPIO_Init (ENCRB_GPIO_PORT, &GPIO_InitStructure);

// Connect the pins to their Alternate Functions 

GPIO_PinAFConfig (ENCLA_GPIO_PORT, ENCLA_SOURCE, ENCLA_AF); 

GPIO_PinAFConfig (ENCLB_GPIO_PORT, ENCLB_SOURCE, ENCLB_AF); 

GPIO_PinAFConfig (ENCRA_GPIO_PORT, ENCRA_SOURCE, ENCRA_AF); 

GPIO_PinAFConfig (ENCRB_GPIO_PORT, ENCRB_SOURCE, ENCRB_AF);

// Timer peripheral clock enable 

RCC_APB1PeriphClockCmd (ENCL_TIMER_CLK, ENABLE); 

RCC_APB1PeriphClockCmd (ENCR_TIMER_CLK, ENABLE);

// set them up as encoder inputs 

// set both inputs to rising polarity to let it use both edges 

TIM_EncoderInterfaceConfig (ENCL_TIMER, TIM_EncoderMode_TI12, 

TIM_ICPolarity_Rising,

TIM_ICPolarity_Rising);

TIM_SetAutoreload (ENCL_TIMER, 0xFFFFFFFF);

TIM_EncoderInterfaceConfig (ENCR_TIMER, TIM_EncoderMode_TI12, 

                              TIM_ICPolarity_Rising, 

                              TIM_ICPolarity_Rising);

TIM_SetAutoreload (ENCR_TIMER, 0xFFFFFFFF);

// turn on the timer/counters 

TIM_Cmd (ENCL_TIMER, ENABLE); 

TIM_Cmd (ENCR_TIMER, ENABLE); 

EncodersReset();

}

void EncodersReset (void) 

__disable_irq(); 

TIM_SetCounter (ENCL_TIMER, 0); 

TIM_SetCounter (ENCR_TIMER, 0); 

__enable_irq(); 

}

zzdz2
Associate II
Posted on June 13, 2013 at 11:50

You can try to use some other TIM to produce pulses and connect those pulses to TIM2/TIM5 to test encoding.

If it works well it would mean something is wrong outside of MCU, perhaps sensor or cables.

Posted on June 13, 2013 at 12:01

A quick scan looks to be reasonable.

What kind of signal is the encoder providing, a Push-Pull, or Open-Collector/Drain? Have you observed the nature of the signal on a scope at these higher rates, and confirmed a clean phase relationship?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jpeacock2399
Associate II
Posted on June 13, 2013 at 15:45

Are you using single-ended or differential encoders?  At those speeds I wouldn't be surprised if you lost data with single-ended encoders.  How long is the cable from the STM32 to the encoder?

Is the encoder spec'ed to run at those frequencies?

  Jack Peacock
kongisme
Associate II
Posted on June 20, 2013 at 10:28

Dear Everyone,

Thank you for your kind advice.

I investigated and tested during few days.

And I found that there was signal noise problem.

I made new board for a clean signal wave to CPU port.

As a result, It works well on the speed of 3Mhz pulse wave.

I think STM32F4 has good qualities to the quadrature encoder calculation.

By the way, I have another question as bellow.

There is one count different value compared with the main reference machine.

But if the scaler encoder move back to the start point, the value(from stm32) become 0(zero).

I think it's not because of noise factor but some register setting for encoder on stm32F4.

Is there any idea?

Thank you in advance.

zzdz2
Associate II
Posted on June 20, 2013 at 12:38

Try to swap encoder lines and count it backwards, I think it could cause +-1 step difference.

Edit: You can also try inverting the input polarity, ref manual says: CC1P and CC2P bits in the TIMx_CCER register.