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读取到的值。

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

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要解决STM32F103中TIM2无法捕获霍尔编码器脉冲计数一直为0的问题,可以按照以下步骤进行排查和解决: 1. 确认引脚配置:检查TIM2的引脚配置是否正确,包括引脚的初始化、复用功能设置等。确保所选引脚与霍尔编码器的输出信号相连接。 2. 配置TIM2模式:通过TIM2的控制寄存器(CR1)和模式寄存器(SMCR)进行配置。确保TIM2的工作模式正确设置,如选择编码器模式,并使能计数器。 3. 使能TIM2中断:检查是否已正确使能TIM2中断,并实现相应的中断处理函数。在中断处理函数中,可以获取计数器的值。 4. 检查霍尔编码器信号:使用示波器或逻辑分析仪检查霍尔编码器的输出信号是否正常。确保编码器的脉冲信号能够正常输入到STM32F103的相应引脚。 5. 检查时钟源和定时器频率:确保时钟源和定时器频率设置正确,以便适应编码器的脉冲频率。 6. 确认硬件连接:检查硬件连接是否正确,如电源、接地和信号线连接是否可靠。 7. 检查程序逻辑:检查代码实现中是否存在错误或逻辑问题。可以尝试使用示例程序进行验证,确保程序逻辑正确。 8. 调试输出:在代码实现中添加调试输出,以便观察编码器脉冲信号、计数器的变化情况。通过观察输出结果,可以判断问题所在。 综上所述,通过对STM32F103的TIM2配置和硬件连接的排查,以及对程序逻辑和脉冲信号的检查,应该可以解决TIM2捕获霍尔编码器脉冲计数一直为0的问题。如果问题仍然存在,可以进一步查阅相关文档和资料,或寻求相关领域专家的帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值