电机特性
- 电机采用的是额定电压为12V,额定功率为4.32W的永磁有刷电机。
- 使用说明上建议电机驱动频率是10kHz,也就是周期为0.1ms,这个后续编程会用到。
电机1号线和6号线分别为电机线-和电机线+,可以接电源VCC和地GND,电机就可以转动起来。当把电源线和地线反接,电机就朝另外一个方向转动。此时电机视为简单的开环电路,不能够控制速度。2-4是编码器的四条线,这四条线可以实现电机的闭环控制。其中要注意的是,编码器电源和编码器地线分别要接VCC和GND,不能像电机线一样随意换,如果接反可能会烧坏驱动模块。
编码器
电机上的编码器采用的是增量式霍尔(磁)编码器,以减速器输出轴测量编码器线数为390,故车轮转一圈,电机可以输出390个脉冲,编码器自带上拉整形,单片机可以直接读取,接口类型为XH2.54(标配连接线)。编码器的额定工作电压是5V。编码器的VCC和GND千万不能接反,否则可能导致编码器永久损坏。
编码器是将信号或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。在这里,编码器就是能够将电机的转动信息(比如转速、转动角度等)转换为脉冲信号的设备。按照原理可分为(常见的)光电编码器(光学式)和霍尔编码器(磁式)。
当电机转动时,通过检测编码器输出的A相和B相正交脉冲信号,就可以获取电机的运动状态。我们可以通过定时器的输入捕获或者GPIO引脚的外部中断来检测边沿变化,以此来检测脉冲数。通过一定的计算,就可以得到电机转动角度、转速等相关信息。
电机驱动模块
实物图
TB6612FNG是一个非常优秀的双电机驱动小板,它有两个完美的接口去驱动两个小型直流电机。两台电机的每个通道有两个方向控制引脚和一个接受PWM输入频率达100Khz的速度控制引脚。
特性
- 最大输入电压:VM = 15V
- 最大输出电流:Iout = 1.2A(平均)/3.2A(峰值)
- 正反转/短路刹车/停机功能模式
- 内置过热保护和低压检测电路
- SSOP24封装
- 无铅封装
引脚说明
引脚名称 | 说明 |
---|---|
PWMA | A电机控制信号输入端 |
AIN2 | A电机输入端2 |
AIN1 | A电机输入端2 |
STBY | 正常工作/待机状态控制端 |
PWMB | B电机控制信号输入端 |
BIN2 | B电机输入端2 |
BIN1 | B电机输入端1 |
GND | 接地 |
VM | 电机驱动电压输入端(4.5V-15V) |
VCC | 逻辑电平输入端(2.7V-5.5V) |
GND | 接地 |
A01 | A电机输出端1 |
A02 | A电机输出端2 |
B01 | B电机输出端1 |
B02 | B电机输出端2 |
GND | 接地 |
VM接的是电机驱动电压输入端,此次试验接12V。
VCC是内部逻辑供电,接3.3V或5V,一般主控板就可以输出对应的电压。
STBY口置0,驱动板停止工作,电机全部停止,置1,靠3个输入管脚驱动电机。
模块的3 个GND 接任意一个即可,因为都是导通的。
直流电机的驱动状态
IN1 | IN2 | 状态 |
---|---|---|
0 | 0 | 制动 |
0 | 1 | 正转 |
1 | 1 | 反转 |
1 | 1 | 制动 |
设置引脚复用
利用PinMux软件设置引脚复用,设置GPIO30和GPIO08信号方向为输出,对应的引脚为P53和P63,将P53与TB6612FNG的AIN2相连,将将P63与TB6612FNG的AIN1相连,用于控制电机的状态。
添加TimerPWM的TimerPWM5,对应的是P64,将P64与TB6612FNG的PWMA相连,然后输出对应文件,进行替换,详细可见《如何使用管脚配置软件PinMux生成CC3200 GPIO口使用文件》
如何确定占空比
系统的时钟是80MHz的,首先确定PWM的周期,开始已经说了周期为0.1ms,据此确定定时器装载的初始值。(0.110的-3次方)/(1/80M) = 8000,也就是说定时器从8000向下计数就是0.1ms。然后我们要考虑占空比可调,我们假定电机速度设置为是0-254一共255个等级,那每个等级之间的步长就是8000/255约等于32,不能除尽。所以我们调节定时器的初值为25532=8160,十六进制为1FE0,这样就可以达到255等级,每个等级步长均为32。
#define TIMER_INTERVAL_RELOAD 8160 /* =(255*32)*/
#define DUTYCYCLE_GRANULARITY 32
在程序当中修改对应的宏定义。
编写代码
在CC3200 SDK工具包中有一个引脚写入的函数,是可以直接引用的,那剩下的问题就是如何找到对应引脚的参数。
- ulPort是GPIO端口基地址。
- ucPins:GPIO引脚位权,
- ucVal:GPIO引脚要输出的值,1或者0。
void
GPIOPinWrite(unsigned long ulPort, unsigned char ucPins, unsigned char ucVal)
{
//
// Check the arguments.
//
ASSERT(GPIOBaseValid(ulPort));
//
// Write the pins.
//
HWREG(ulPort + (GPIO_O_GPIO_DATA + (ucPins << 2))) = ucVal;
}
如何获得GPIO的端口地址和引脚位权
首先将Blinky程序的gpio_if.c文件复制到pwm程序之下,因为里面有一些很好用的程序可以借用一下。
void
GPIO_IF_GetPortNPin(unsigned char ucPin,
unsigned int *puiGPIOPort,
unsigned char *pucGPIOPin)
{
*pucGPIOPin = 1 << (ucPin % 8); //组内序号从0开始,按此计算得到组内位权
*puiGPIOPort = (ucPin / 8);
*puiGPIOPort = ulReg[*puiGPIOPort];
}
*pucGPIOPin:GPIO引脚位权指针,引脚位权是1左移0-7位,4个GPIO组(GPIOA0-3)中8个GPIO的引脚位权从低到高依次是0x01、0x02、0x04、0x08、0x10、0x20、0x40、0x80。左移位数是引脚名称号ucPin余除8,取值为0-7。
以GPIO23为例,它是GPIOA2组的第8个,按照规定位权应当是0x80。我们来看看算得对不对。23除8余7,把1左移7位就是0x80,所以算法是对的。实际应用中,直接用就行了,这里讲解一下也是方便大家理解。
*puiGPIOPort:GPIO端口基地址指针,端口基地址通过数组ulReg[]获得,数组下标是引脚名称号ucPin整除8,取值为0-4,对应GPIO0-4。
通过以上函数可以根据名称号获取端口基地址和引脚位权。
修改gpio_if.c中的GPIO_IF_LEDConfigure()函数,记得同时把gpio_if.h和main.c的对应函数进行更换。用函数获取GPIO30和GPIO08的端口及地址和引脚位权。
unsigned int ulPort_AIN1 = 0,ulPort_AIN2 = 0;//定义端口基地址
unsigned char ucPins_AIN1,ucPins_AIN2;//定义引脚位权
#define GPIO_AIN2 30//定义引脚名称
#define GPIO_AIN1 08
void
GPIO_IF_MotorConfigure()
{
GPIO_IF_GetPortNPin(GPIO_AIN2,
&ulPort_AIN2,
&ucPins_AIN2);
GPIO_IF_GetPortNPin(GPIO_AIN1,
&ulPort_AIN1,
&ucPins_AIN1);
}
如何向引脚写入我们想要的值
GPIO_IF_Set是gpio_if.c文件一个函数,我们新建一个Forward函数,AIN1为0,AIN2为1,驱动电机正转。
void Forward()
{
GPIO_IF_Set(GPIO_AIN1, ulPort_AIN1, ucPins_AIN1, 0);
GPIO_IF_Set(GPIO_AIN2, ulPort_AIN2, ucPins_AIN2, 1);
}
void
GPIO_IF_Set(unsigned char ucPin,
unsigned int uiGPIOPort,
unsigned char ucGPIOPin,
unsigned char ucGPIOValue)
{
ucGPIOValue = ucGPIOValue << (ucPin % 8);
MAP_GPIOPinWrite(uiGPIOPort,ucGPIOPin,ucGPIOValue);
}
参考文章:
【1】《带编码器的直流减速电机——基于STM32F407》
【2】 《平衡小车—TB6612FNG与直流电机控制教程》
【3】《带编码器的减速直流电机、tb6612驱动模块在硬件方面的经验》