简介:
电机调速需要使用到STM32的PWM输出控制电机驱动器从而完成电机调速功能。
1、实现的工具
starrobot底层开发板、12V 5200ma锂电池、GB37-520减速电机、USB数据线、Keil5
starrobot底层开发板板载了A4950电机驱动器,预留和电机相同线序的XH2.54-6P接口,即插即用。电机转动主要使用到电机线+、电机线-两根线,编码器GND、编码器B相、编码器A相、编码器5V主要用于测速,这个下一章节通过编码器获取电机转速值会进行讲解。A4950电机驱动芯片支持8~25V、最大电流3A的输出,可以满足常用的GB37-520减速电机驱动。驱动芯片原理如下:
选择PWM互补输出,PWM互补输出IN1和IN2都是PWM,只是同一时刻的值是相反的,如下图:
假设黄色是IN1、蓝色是IN2同一时刻IN1为高电平,IN2则为低电平,从而使电机进行转动,只需要两个引脚即可。
2、代码分享
首先我们要知道,STM32单片机引脚PWM电压输出为0~3.3V。PWM一个周期内有高电平和低电平,高低电平时间的不同就可以得到不同的占空比。STM32中影响PWM的主要有两个参数:
1、预分频值psc,决定定时器的时钟频率
2、自动重载值arr,范围在0~65535之间,决定了定时器溢出的时间。
本文使用STM32F4定时器1的时钟频率为168M:如果psc = 168,arr = 1000,那么PWM频率 f = (168/168)M/1000 = 1kHz
void MotorInit(uint32_t arr_,uint32_t psc_)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
RCC_AHB1PeriphClockCmd(MOTOR_A_PORT_CLK[this->motor_] |MOTOR_B_PORT_CLK[this->motor_], ENABLE);
RCC_APB2PeriphClockCmd(MOTOR_TIM_CLK[this->motor_], ENABLE);
/** init motor_ gpio **/
GPIO_InitStructure.GPIO_Pin = MOTOR_A_PIN[this->motor_];
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_Init(MOTOR_A_PORT[this->motor_], &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = MOTOR_B_PIN[this->motor_];
GPIO_Init(MOTOR_B_PORT[this->motor_], &GPIO_InitStructure);
GPIO_PinAFConfig(MOTOR_A_PORT[this->motor_],MOTOR_A_PINSOU[this->motor_],MOTOR_AF_TIM[this->motor_]); //GPIOA8复用为定时器1
GPIO_PinAFConfig(MOTOR_B_PORT[this->motor_],MOTOR_B_PINSOU[this->motor_],MOTOR_AF_TIM[this->motor_]); //GPIOA7复用为定时器1
TIM_DeInit(MOTOR_TIM[this->motor_]);
TIM_TimeBaseInitStructure.TIM_Period = arr_; //arr 自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler = psc_; //psc 定时器分频
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(MOTOR_TIM[this->motor_], &TIM_TimeBaseInitStructure);
TIM_ARRPreloadConfig(MOTOR_TIM[this->motor_],ENABLE);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; //互补输出允许
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //High为占空比高极性,此时占空比为50%,Low则为反极性,占空比为50%
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //互补输出,与以上相反
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; //
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; //
if(MOTOR_TIM[this->motor_] != STARBOT_MOTOR4_TIM)
{
TIM_OC1Init(MOTOR_TIM[this->motor_], &TIM_OCInitStructure);
TIM_OC1PreloadConfig(MOTOR_TIM[this->motor_],TIM_OCPreload_Enable);
TIM_OC2Init(MOTOR_TIM[this->motor_], &TIM_OCInitStructure);
TIM_OC2PreloadConfig(MOTOR_TIM[this->motor_],TIM_OCPreload_Enable);
TIM_OC3Init(MOTOR_TIM[this->motor_], &TIM_OCInitStructure);
TIM_OC3PreloadConfig(MOTOR_TIM[this->motor_],TIM_OCPreload_Enable);
}
else
{
TIM_OC3Init(MOTOR_TIM[this->motor_], &TIM_OCInitStructure);
TIM_OC3PreloadConfig(MOTOR_TIM[this->motor_],TIM_OCPreload_Enable);
}
// TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
// TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
// TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
// TIM_BDTRInitStructure.TIM_DeadTime = 0x90;
// TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
// TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
// TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
// TIM_BDTRConfig(MOTOR_TIM[this->motor_], &TIM_BDTRInitStructure);
TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;
TIM_BDTRInitStructure.TIM_Break=TIM_Break_Disable;//TIM_Break_Enable;
TIM_BDTRInitStructure.TIM_BreakPolarity=TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_DeadTime=28;
TIM_BDTRInitStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_OSSIState=TIM_OSSIState_Disable;//TIM_OSSIState_Disable;//TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_OSSRState=TIM_OSSRState_Disable;//TIM_OSSRState_Disable;//TIM_OSSRState_Enable;
TIM_BDTRConfig(MOTOR_TIM[this->motor_],&TIM_BDTRInitStructure);
TIM_ARRPreloadConfig(MOTOR_TIM[this->motor_], ENABLE);
//TIM_CCPreloadControl(MOTOR_TIM[this->motor_],ENABLE);
TIM_Cmd(MOTOR_TIM[this->motor_], ENABLE);
TIM_CtrlPWMOutputs(MOTOR_TIM[this->motor_], ENABLE);
}
void Motor_spin(int pwm)
{
if(this->motor == MOTOR4){
if(pwm < 0){
TIM_CCxCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCx_Enable);
TIM_CCxNCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCxN_Disable);
}else if(pwm > 0) {
TIM_CCxCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCx_Disable);
TIM_CCxNCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCxN_Enable);
}
}
if((this->motor == MOTOR1) || (this->motor == MOTOR3) || (this->motor == MOTOR2)){
if(pwm > 0){
TIM_CCxCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCx_Enable);
TIM_CCxNCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCxN_Disable);
}else if(pwm < 0) {
TIM_CCxCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCx_Disable);
TIM_CCxNCmd(MOTOR_TIM[this->motor], MOTOR_CHANNEL[this->motor], TIM_CCxN_Enable);
}
}
if(MOTOR_CHANNEL[this->motor] == TIM_Channel_1){
TIM_SetCompare1(MOTOR_TIM[this->motor], abs(pwm));
}
if(MOTOR_CHANNEL[this->motor] == TIM_Channel_2){
TIM_SetCompare2(MOTOR_TIM[this->motor], abs(pwm));
}
if(MOTOR_CHANNEL[this->motor] == TIM_Channel_3){
TIM_SetCompare3(MOTOR_TIM[this->motor], abs(pwm));
}
}
3、总结
电机的调速主要使用到STM32 PWM输出进行驱动电机驱动器,从而对电机进行调速,大概思路就是这样。