STM32F407编码器测速

  采用STM32F407VE开发板,通过计算总圈数加上最后一圈所转的角度除以时间来进行测速。设置TIM2为编码器模式,并在TIM3定时器的中断函数中进行速度解算输出当前速度值。

举个例子,比如你的编码器一圈一百二十个脉冲,对于一圈三百六十度而言,CNT测得的值再乘以三就能表示当前的角度(一圈的脉冲数越多测量的偏差越小)。角度加上圈数除以时间再乘以轮子的周长便是速度,下面是实现的方法。

目录

配置定时器

测量圈数

速度解算

配置定时器

void TIM2_config(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef ENCODER;
	TIM_ICInitTypeDef FLITER;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM2);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM2);
	
	ENCODER.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1;
	ENCODER.GPIO_Mode=GPIO_Mode_AF;
	ENCODER.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_Init(GPIOA,&ENCODER);
	
    TIM_TimeBaseInitStructure.TIM_Period = 660-1; 	   
	TIM_TimeBaseInitStructure.TIM_Prescaler=2-1;  
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; 
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Falling,TIM_ICPolarity_Falling);
	TIM_ICStructInit(&FLITER);
    FLITER.TIM_Channel=TIM_Channel_1 | TIM_Channel_2;
	TIM_ICInit(TIM2,&FLITER);
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02; 
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE);
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); 
    TIM2->CNT=0;
	TIM_Cmd(TIM2,ENABLE); 
	motor1.motor_turns=0;
    motor2.motor_turns=0;
}

定时器的预分频系数及预装载值需要根据自己电机的编码器状况决定,使能输出比较的中断用于后文判断旋转的方向。由于上电后已经转过的圈数会直接显示-1,所以在配置的函数中首先将圈数清零。(这块也不知道问题出在哪里,就直接用了个最笨的方法。)

测量圈数

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET)
	{
		TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);
	  motor1.direction=(TIM2->CR1&0x10)>>4;
	}
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) 
	{
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);  
    if(motor1.direction) 
    {motor1.motor_turns+=1;}
    else 
    {motor1.motor_turns-=1;}
	}
}

通过CR1的值来判断正反转,然后统计圈数为后面速度解算做准备。

速度解算

float solution(motor *motor1)
{
motor1->real_angle=motor1->temp-motor1->motor_last_angle/precision;
if(motor1->real_angle<0) 
{motor1->motor_turns--;
motor1->real_angle=pluses_number-motor1->real_angle;}
else{}
if(motor1->motor_turns<0) 
{motor1->motor_location=(motor1->motor_turns+1)*pluses_number*precision-((pluses_number-motor1->real_angle)*precision);}
else 
{motor1->motor_location=motor1->motor_turns*pluses_number*precision+motor1->real_angle*precision;}
motor1->motor_abs_angle=motor1->temp*precision;
motor1->motor_speed=(motor1->motor_location/pluses_number)*length_every_round;
motor1->motor_last_angle=motor1->motor_abs_angle;
motor1->motor_turns=0;
motor1->motor_location=0;
return motor1->motor_speed;
}

速度解算通过判断两次的角度差来判断是否转足了一圈,若不是,则圈数减一,此次计算完成后保留这次的角度然后将总的路程清零以便下一次解算。motor->temp的值就是CNT读取到的值。

对于测取到的速度可酌情加入合适的滤波,比如滑动均值滤波等等。

你可能感兴趣的:(stm32,单片机,嵌入式硬件)