前言:之前做arduino小车的时候使用的是L298N电机,没有用过编码器,这次第一次用编码器,还是比较懵圈,记录一下学的整个过程。
1.编码器的简介
霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。
霍尔编码器是由霍尔码盘(磁环)和霍尔元件组成。
霍尔码盘是在一定直径的圆板上等分地布置有不同的磁极。霍尔码盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相位差的方波信号
编码器为了获得每一圈的脉冲数,通过公式可以将其转化为当前电机的转速,从而达到测速的目的。
2.接线方式:
我买的是tb6612的一个综合体驱动模块,这样接线比较方便。
v---5v电源 G----GND【接地】 A和B则是编码器的A,B相。
M1和M2则和电机的E1A和E1B相连接
3.编码器的倍频原理
正常的情况都是去捕获一个相位的上升沿或者下降沿,这样每个周期只能捕获一次
编码器的四倍频技术就是,单个周期内,同时捕获A和B的上升沿和下降沿,这样单个周期内就可以捕获四次,翻了四倍,当A因为跳变触发了外部中断,在中断里面判断B是什么电平,从而来判断当前轮子是正转还是反转。
4.编码器的计数原理
编码器选择的是四倍频技术,即在T1和T2同时进行计数。
借助这个计数,可以算出固定周期内的编码器的脉冲数,借助M测速法,算出当前的电机的速度。
同时根据图可以发现,A相在前就是轮子正转,B相在前就是轮子反转。
5.编码器代码理解
设置为65536,为了增大计数周期,且计数频率加快,保证了系统的不管轮子转速多块都可以检测到当前的脉冲次数
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
第一个:定时器的选择
第二个:选择是T1和T2,进行双通道的上下沿计数。
第三,四个:反相or不反相
不反相:正转,计数++,反转,计数--。
反相:正转,计数--,反转,计数++。
这里将其中的一个脉冲值的读入前面加入负号,因为两个轮子安装是相反的,这样是为了保持极性的一致。
此时计数器的数值便是在TIM4定时器单个周期内,计算左右轮子的脉冲数。
某乎的这张图很清晰的介绍了霍尔编码器的运行方式。
6.PWM输出使能
设置定时器的通道PWM输出使能,然后设置IO口控制电平的输出。
设置输出通道的极性,和PWM输出模式。
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能
//设置该引脚为复用输出功能,输出TIM1 CH1 CH4的PWM脉冲波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11; //TIM_CH1 //TIM_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_Pulse = arr >> 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
TIM_OC4Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH4预装载使能
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
设置IO口进行电平的输出。
void Motor_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50MHZ
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
AIN1=0,AIN2=0;
BIN1=0,BIN1=0;
}
通过设置AIN进行轮子的正转和反转。