cancel
Showing results for 
Search instead for 
Did you mean: 

Encoder Interface STM32F0 Discovery

kasun_duminda92
Associate III
Posted on July 26, 2013 at 05:16

I have a motor with a quadrature encoder and I want to get the relative (absolute after counting from home position) position. I tried getting the encoder count using an interrupt from one channel of the encoder and checking the state of the other channel. But I found that a lot of counts are missed when the encoders are interfaced this way.

Now I have decided to try the Encoder Interface. The Reference manual says that I don't need 'external interface logic' to connect the encoder so I think I can directly connect the encoder channels to the STM32F0 (the channel voltages shift from 0-3V).  I have seen the Encoder mode example for the STM32F0 but cannot fully understand how to implement it.

What is the maximum value the timer can count upto? Should I set this value?

Which pins correspond to the encoder interface?

What register or variable do I read to get the encoder count?

#encoder-interface #advanced-timers
5 REPLIES 5
Posted on July 26, 2013 at 06:39

Answered in [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Stm32%20Encoder%20interface&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/AllItems.aspx&currentviews=1601]duplicate.

Here is a blind port to the STM32F0-Discovery

/* STM32 TIM2 Encoder Decoder (PA.5, PA.2) STM32F0-Discovery sourcer32@gmail.com */
#include ''stm32f0xx.h''
//******************************************************************************
void RCC_Configuration(void)
{
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
}
//******************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// Pins selection from STM32F0-Discovery User Manual UM1525
// and Data Manual
/* GPIOA Configuration: TIM2 on PA5 and PA1 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Or UP for Open-Collector signals
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM2 pin - Alternate Function Assignment from Table 4 Data Manual */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_2); // PA5 TIM2_CH1 / TIM2_ETR
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_2); // PA1 TIM2_CH2
}
//******************************************************************************
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // Maximal
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level.
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_Cmd(TIM2, ENABLE);
}
//******************************************************************************
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
TIM2_Configuration();
// TIM2->CNT contains current position
while(1); /* Infinite loop */
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
kasun_duminda92
Associate III
Posted on August 31, 2013 at 16:13

I was able to make a PID position controller using the counter to get current position.

thanks clive1. Appreciate it.
tuan
Associate II
Posted on June 13, 2014 at 06:22

Hi you,

Can you share your code about PID controller?

I had problem how can define direction of motor  to increase or decrease number of counter of encoder.

Posted on June 13, 2014 at 20:11

I had problem how can define direction of motor  to increase or decrease number of counter of encoder.

I guess because it expects a quadrature type signal where the direction is inferred? If you just have pulses then you're going to want to use an external counter mode, and manual change the up/down configuration of the timer. That or check if the direction is controlled by the state of a direction pin, based on edge(s) of the pulse pin.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
giangxuanhoang
Associate
Posted on June 24, 2016 at 05:44

Hi Clive1

Here is code which count pulse up/down by step and direction use timer1 but this code was wrote in HAL library, now I want to convert to SPL library but I'm newbie so this is so difficult. Can you give me some advice on this then I will try to modify by myself

#include ''mbed.h''

 

#include ''stm32f4xx.h''

 

#include ''stm32f4xx_hal_tim_ex.h''

 

 

TIM_HandleTypeDef timer;

 

TIM_Encoder_InitTypeDef encoder;

 

 

//direction to PA_9 -- step pulse to PA_8

 

 

int main(){

 

     GPIO_InitTypeDef GPIO_InitStruct;

 

        __TIM1_CLK_ENABLE();

 

        __GPIOA_CLK_ENABLE();

 

        GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;

 

        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

 

        GPIO_InitStruct.Pull = GPIO_PULLDOWN;

 

        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

 

        GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;

 

        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 

 

    timer.Instance = TIM1;

 

    timer.Init.Period = 0xffff;

 

    timer.Init.Prescaler = 1;

 

    timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 

    timer.Init.CounterMode = TIM_COUNTERMODE_UP;

 

 

    encoder.EncoderMode = TIM_ENCODERMODE_TI1;

 

    encoder.IC1Filter = 0x0f;

 

    encoder.IC1Polarity = TIM_INPUTCHANNELPOLARITY_RISING;

 

    encoder.IC1Prescaler = TIM_ICPSC_DIV1;

 

    encoder.IC1Selection = TIM_ICSELECTION_DIRECTTI;

 

 

    encoder.IC2Filter = 0x0f;

 

    encoder.IC2Polarity = TIM_INPUTCHANNELPOLARITY_RISING;   

 

    encoder.IC2Prescaler = TIM_ICPSC_DIV1;

 

    encoder.IC2Selection = TIM_ICSELECTION_INDIRECTTI;

 

 

    HAL_TIM_Encoder_Init(&timer, &encoder);

 

    HAL_TIM_Encoder_Start(&timer,TIM_CHANNEL_1);  

 

 

 

    TIM1->EGR = 1;           // Generate an update event

 

    TIM1->CR1 = 1;           // Enable the counter

 

 

 

while (1) {

 

        int16_t count1;

 

        count1=TIM1->CNT;

 

 

        printf(''%d\r\n'', count1);

 

        wait(1.0);

 

 

};

 

}

 Thanks