2013-07-25 08:16 PM
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-timers2013-07-25 09:39 PM
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¤tviews=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 */
}
2013-08-31 07:13 AM
I was able to make a PID position controller using the counter to get current position.
thanks clive1. Appreciate it.2014-06-12 09:22 PM
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.2014-06-13 11:11 AM
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.2016-06-23 08:44 PM
#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