前言:
stm32如何去控制无感无刷电机?
首先我们先要知道无刷电机的工作原理是什么,这样我们才能针对实际需求,对stm32 进行点对点的内部资源的调用,从而进行程序编写。
我相信能搜到这个Blog的同学都对无刷电机有一个大概的了解,但是具体的使用细节和原理,可能不太清楚。
在这里给大家讲解一下写程序时几个关键的点,在清楚了无刷电机控制的同时,也就明白了程序该如何写。
硬件使用的是KY_Motor的开发板。
链接:KY_Motor开发板
无刷电机控制的比较重要的地方就是换向,而无感无刷最重要的知识点就是零点检测。
1、电机换向和零点检测。
零点检测电路
//PA5 引脚中断,计算换相时刻
void EXTI9_5_IRQHandler(void)
{
Zero=GPIO_ReadInputData(GPIOA);
Zero=Zero&0x0038;
Zero=Zero>>3;//过零点信号,513264
if(!Direction)Zero=7-Zero;
Zero_SW();
counter1++;
if(EXTI_GetITStatus(EXTI_Line5)!= RESET)
{
EXTI_ClearITPendingBit(EXTI_Line5);
}
}
在这里通过检测U、V、W三相哪一路导通,进而通过比较器来判断哪一路导通。
在这里解释一下zero = zero & 0x0038 是什么意思,在硬件上我们采用了 PA3、PA4、PA5三个引脚作为零点检测引脚,0x0038的二进制为 xx 0011 1000,就是说 PA3、PA4、PA5与 111相与,进而得出哪一路导通的值。
再将zero的值右移3位,就能得出过零点信号 513264,将513264也相应的换算成二进制数,就明白如何获取到过零点信号的值了。
在程序中我们分别对PA3、PA4、PA5三个引脚进行了中断处理,程序都一样,只是中短线不一样,大家自行改一下程序。
我们在取得过零点信号后需要对取到的信号用于电机换相,也就是下面这个经典的六臂全桥驱动电路。
取其中两路导通,实现方法我们通过如下方法进行实现。
//过零点换相函数
void Zero_SW(void)
{
switch(Zero)
{
case 5:
TIM1->CCR2=0; //AB
TIM1->CCR1 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
break;
case 1:
TIM1->CCR2=0; //AC
TIM1->CCR1 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case 3:
TIM1->CCR1=0; //BC
TIM1->CCR2 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case 2:
TIM1->CCR1=0; //BA
TIM1->CCR2 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_14 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
break;
case 6:
TIM1->CCR2=0;//CA
TIM1->CCR3 = My_PWM;
TIM1->CCR1=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_14 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
break;
case 4:
TIM1->CCR2=0; //CB
TIM1->CCR3 = My_PWM;
TIM1->CCR1=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
break;
default:
break;
}
}
这段程序很好理解,就不做过多解释。
========================================================================
到这,无感无刷电机驱动的比较重要的两部分程序就讲解完了。我们接下来看一下启动函数。
//启动函数
void START_UP(void)
{
switch(phase)
{
case 1:
TIM1->CCR2=0; //AB
TIM1->CCR1 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
break;
case 2:
TIM1->CCR2=0; //AC
TIM1->CCR1 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case 3:
TIM1->CCR1=0; //BC
TIM1->CCR2 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);
GPIO_SetBits(GPIOB, GPIO_Pin_15);
break;
case 4:
TIM1->CCR1=0; //BA
TIM1->CCR2 = My_PWM;
TIM1->CCR3=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_14 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
break;
case 5:
TIM1->CCR2=0;//CA
TIM1->CCR3 = My_PWM;
TIM1->CCR1=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_14 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_13);
break;
case 6:
TIM1->CCR2=0; //CB
TIM1->CCR3 = My_PWM;
TIM1->CCR1=0;
GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
break;
default:
break;
}
}
细心的同学会发现,启动函数和零点换相函数一样。
因为电机在启动的时候程序无法判断哪一个点在零点,因此需要先让电机导通,当导通后,便会产生反向电动势,也就可以采集到零点信号,因此知道哪一路导通。
在程序中加的用户接口程序就不在这罗列了,这个程序通过按键控制电机启动,分别对应加速和减速按键,对电机速度进行控制。下面视频测试了航模无刷电机12v、1400KV。程序花了点事件优化,无感无刷的电机启动的很流畅。
stm32无刷电机驱动器_按键调速
网上有些例程代码只能适配一种电机,换一个新电机便不能流畅的转动了,因此我把手头的电机都试了一遍,目前我手里的这些电机都可以流畅的启动,以前总玩航模,手头的电机也大都是航模用的电机。
启动算法优化优化的比较理想,可以移植到国产的32位单片机上做一个航模无刷电调,今年会陆续把剩下的工作都做完,
感谢大家收看,关注我,定期更新无刷电机干货。