最近开始做智能小车相关项目,需要测试小车行走时两电动机的速度,来控制小车的走向。
我用STM32+L298N电机驱动板,后来又在淘宝上买了两个光偶装在两电机旁边的木质轮子上(20个空槽),从而组成一个类似光电开关的传感器,之后硬件调试完全OK,在示波器上可以清晰的看到左右轮子的方波,结果显示一个轮子的频率大概在90hz左右,而另一个轮子的频率只有70hz,那么确定电机转速的确是有问题的。于是我就开始了小车测速方面的驱动调试(代码主要是各位大神的)
先上timer3相关代码
#include "encoder.h"
#include "stm32f10x.h"
[mw_shl_code=c,true]extern u16 v_counter;
extern float v;
#define TIMx_PRE_EMPTION_PRIORITY 0 //2
#define TIMx_SUB_PRIORITY 0
#define ENCODER_TIMER TIM3 // Encoder unit connected to TIM3
#define ENCODER_PPR (u16)(1000) // number of pulses per revolution
#define ICx_FILTER (u8) 6 // 6<-> 670nsec
#define COUNTER_RESET (u16)0
#define U16_MAX ((u16)65535u)
static volatile u16 hEncoder_Timer_Overflow;
void ENC_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
/* Encoder unit connected to TIM3, 4X mode */
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3 clock source enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3时钟
/* Enable GPIOA, clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOB时钟
GPIO_StructInit(&GPIO_InitStructure);
/* Configure PB.8 as encoder input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 pin6 pin7
/* Enable the TIM4 Update Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM4中断
/*中断一级优先级设置*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY; //先占优先级0级
/*中断二级优先级设置*/
NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY; //从优先级 0级
/*中断使能*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
/*中断赋值*/
NVIC_Init(&NVIC_InitStructure);
/* Timer configuration in Encoder mode */
TIM_DeInit(ENCODER_TIMER);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
/*不需要任何预分频*/ //Tout=(arr+1)*(psc+1)/Tclk;
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // No prescaling
TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1; //设定计数器重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割 T_dts = T_ck_int
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数
TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);
/*设置为编码器模式*/
TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式4
/*filter设置*/
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;//选择输入比较滤波器 /*TIM_ICFilter选择输入比较滤波器。该参数取值在0x0和0xF之间*/
TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);
// Clear all pending interrupts
TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
/*开启编码器溢出中断*/
TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);
//Reset counter /*复位编码器*/
TIM3->CNT = COUNTER_RESET;
/*使能编码器*/
TIM_Cmd(ENCODER_TIMER, ENABLE);
}
/*******************************************************************************
Timer3的Update中断处理程序
* Function Name : TIM3_IRQHandler
* Description : This function handles TIMx Update interrupt request.
Encoder unit connected to TIM2
* Input : None
* Output : None
* Return : None
*******************************************************************************/
/*中断溢出处理(测速),这里是网上找的,和我的20格木质...不匹配*/
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
v_counter=TIM_GetCounter(TIM3);
TIM_SetCounter(TIM3, 0);
v=(float)v_counter*120/400; //定时为0.5s
v_counter=v;
}
}
void TIM_Init(void)
{
ENC_Init();
}
[/mw_shl_code]
主函数
[mw_shl_code=c,true]u16 v=0;
u16 v_counter=0;
volatile s16 encoder_num;
volatile s16 encoder_num1;
volatile s16 encoder_num2;
//volatile s16 encoder_num;
int main(void)
{
SystemInit(); //系统时钟配置函数通过不同的定义 来选择不同的主频 这里设置是72m
LED_GPIO_Init(); //初始化与LED连接的硬件I/O接口
Motor_GPIO_Init(); //初始化与电机连接的硬件I/O接口
/**********************************************************/
TIM_Init(); //定时器初始化,以后集中到一起!!!!!!!!!
/**********************************************************/
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置中断优先级分组
uart_init(9600); //串口初始化为9600
while(1)
{
TIM_SetCompare2(TIM2,0);//定时器2的通道1和2来驱动左右两个电机 [/mw_shl_code]
[mw_shl_code=c,true] encoder_num=TIM_GetCounter(TIM3);//定时器3捕捉那个... 算是比较的信号(我也不太懂)
printf("\r\nR_编码器计数值为:%d\n",encoder_num);
TIM_SetCompare1(TIM2,0);//定时器2的通道1和2来驱动左右两个电机 encoder_num1=TIM_GetCounter(TIM3);
printf("\r\nL_编码器计数值为:%d\n",encoder_num1);
encoder_num2=TIM_GetCounter(TIM2);
printf("\r\ntest_编码器计数值为:%d\n",encoder_num2);
}
}[/mw_shl_code]
小车(程序运行)后,
encoder_num ,encoder_num1 数字一个偏大,一个偏小(因为中断处理原因,都小于150)
1.这就算是定时器3的计数值吗?
2.那么我要必出两个小电机的转速不同,该怎么办?
3.还有这两个10进制的数换成二进制形式,是不是我从示波器上扑捉到的那个高低电平,那个平率很快,感觉那个高低电平应该是叠加上去后,才打印出现在这样的十进制数(我的猜测对不对)?
encoder_num2,这个是我心血来潮加上去了,然后得出的结果整个人都凌乱了,有个规律就是一只高,一只低,这该是两个电机不同的频率问题了,可问题是,对于定时器2,关于编码驱动的问题我什么都没做,就出现这样的结果了,(用示波器测量不像测速度那样高低都有,都只能看到高电平)
PS:
还有我看各位一直说编码器的问题,请问编码器是怎么定义的,我的那个小车电机上的两个20格木质转盘+两个光电传感器组成的光电开关(电机转动时,上面的光电传感器会闪烁,这个大家应该都清楚的)算不算编码器?这个网上居然搜索不到,又不想糊糊涂涂项目做完还不知道,所以就确定一下。
由于这方面是第一次搞,加上接触的时间不多,所以求各位大神帮忙解答一下疑惑,谢了!
|