历史上的今天
今天是:2025年06月28日(星期六)
2021年06月28日 | 【单片机】DIY无刷电机驱动器 1
2021-06-28 来源:eefocus
参考文章:《【机械自动化】BLDC驱动器ESC》。
控制直流无刷电机和控制直流有刷电机的最大区别有两点:
1、有刷直流电机使用用两个驱动桥臂,无刷直流电机需要使用三个驱动桥臂。
2、有刷直流电机使用碳刷换相,无刷直流电机需要外部控制换相。
这里为了简化,没有使用霍尔传感器以及参考文章中介绍的反电势法(BEMF)原理进行换相检测,这里使用的方法是“猜”,“猜”法很简单,就是我觉得该换相了,就换相,如果换相快了,转子跟不上就会抖动,如果换相慢了,转子会跟着转得慢而已,那么就控制换相速度稍微慢点就行了。
核心电路图如下:
上图中使用的是PMOS加NMOS组成单个桥臂,PMOS的缺点是内阻较NMOS大,所以可能会发热较严重,但是控制方便,使用一个小的NMOS或者NPN三极管就可以驱动,但是如果上桥臂的MOS管使用NMOS的话,正常工作的时候NMOS的漏极电压会很高,导致栅极需要更高的电压才能导通NMOS,这时候需要比较复杂的控制电路或者半桥栅极驱动器IC(如IR2104STRPBF)完成这个功能。我的实验电机不需要很高的电流,这里还是选择了控制简单的PMOS作为上桥臂。但是注意电路中的R12、R13、R14在实际焊接的时候使用1K或者0欧,这样会让Vgs的绝对值较大,这时候MOS管的内阻Rds会较小,驱动电流大,MOS管自身发热量小,但是如果电机的工作电压很大的话(12V、24V),需要适当调整R12、R13、R14的大小,防止Vgs的值过大烧坏MOS管,具体值参考MOS管的数据手册,这里我使用的是集成PMOS+NMOS管的AO4606或者AO4616芯片:

PCB打样回来了:

焊接完3相桥臂和IO接口:

与3D模型对比:

电路板上面的是MCU部分,没有使用,直接把IO_A1、IO_A2、IO_B1、IO_B2、IO_C1、IO_C2使用排针引出来,直接使用开发板测试就行了,懒得焊接。
IO_A1、IO_A2、IO_B1、IO_B2、IO_C1、IO_C2是分别控制三个桥臂的信号,注意IO_X1和IO_X2信号不可以同时为高,否则会导致桥臂短路,容易烧坏MOS管,同时在程序中最好先将为0的信号先设置为0,然后再设置不为0的信号,这样可以避免短路。同时为了可以精确控制,所有IO_X1和IO_X2信号都是使用PWM驱动,因为我想实现类似步进电机的功能,可以精确控制无刷电机的转动角度。
无刷电机的换相顺序如下图,一周期总共需要6次换相,分为6个状态,分别为导通顺序分别为AB、AC、BC、BA、CA、CB,按道理软件上只要这样的换相顺序就能让电机转动。

PWM通道设置以及测试代码:
volatile unsigned int *A1 = &TIM1 ->CCR3;
volatile unsigned int *A2 = &TIM1 ->CCR2;
volatile unsigned int *B1 = &TIM3 ->CCR4;
volatile unsigned int *B2 = &TIM3 ->CCR2;
volatile unsigned int *C1 = &TIM3 ->CCR1;
volatile unsigned int *C2 = &TIM14->CCR1;
1.
2.
3.
4.
5.
6.
登录后复制
//设置所有桥臂为无输出。注意IO_X1和IO_X2信号不可以同时为高,
//否则会导致桥臂短路,容易烧坏MOS管,同时在程序中最好先将为0的
//信号先设置为0,然后再设置不为0的信号,这样可以避免短路。
*A1 = 0;
*A2 = 0;
*B1 = 0;
*B2 = 0;
*C1 = 0;
*C2 = 0;
#define INTERVAL 5 //换相间隔时间
#define PWM1 255 //上桥臂PWM占空比,为了防止产生“共振”现象,设置一端的PWM
//占空比为100%或者0%,调整另一端的PWM占空比大小。
#define PWM2 100 //下桥臂PWM占空比
//处于t0状态,并维持一段时间,保证可靠处于t0状态
printf("Readyrn");
{ //t0:AB
*C1 = 0;
*C2 = 0;
*A2 = 0;
*A1 = PWM1;
*B1 = 0;
*B2 = PWM2;
}
delay_ms(1000);
//进入换相主循环
printf("Startrn");
while(1)
{
{ //t0:AB
printf("t0:ABrn");
*C1 = 0;
*C2 = 0;
*A1 = PWM1;
*A2 = 0;
*B1 = 0;
*B2 = PWM2;
}
delay_ms(INTERVAL);
{ //t1:AC
printf("t1:ACrn");
*B1 = 0;
*B2 = 0;
*A1 = PWM1;
*A2 = 0;
*C1 = 0;
*C2 = PWM2;
}
delay_ms(INTERVAL);
{ //t2:BC
printf("t2:BCrn");
*A1 = 0;
*A2 = 0;
*B1 = PWM1;
*B2 = 0;
*C1 = 0;
*C2 = PWM2;
}
delay_ms(INTERVAL);
{ //t3:BA
printf("t3:BArn");
*C1 = 0;
*C2 = 0;
*B1 = PWM1;
*B2 = 0;
*A1 = 0;
*A2 = PWM2;
}
delay_ms(INTERVAL);
{ //t4:CA
printf("t4:CArn");
*B1 = 0;
*B2 = 0;
*C1 = PWM1;
*C2 = 0;
*A1 = 0;
*A2 = PWM2;
}
delay_ms(INTERVAL);
{ //t5:CB
printf("t5:CBrn");
*A1 = 0;
*A2 = 0;
*C1 = PWM1;
*C2 = 0;
*B1 = 0;
*B2 = PWM2;
}
delay_ms(INTERVAL);
}
测试结果电机可以正常转动,且扭矩还不错(和电流大小有关,一开始R12、R13、R14焊接的是10K导致电流不足,转动不流畅),通过调整PWM1和PWM2可以调整相电流大小,为了防止产生“共振”现象,就是由于使用PWM控制时,当A桥臂的上桥臂为1时,B桥臂的下桥臂正好为0,这时候是没有电流的,这种重叠的时间最大可以是整个周期都是重叠的,这时候虽然两边的PWM占空比都大于零,但是产生了谐振降低了驱动电流,解决办法为设置一端的PWM占空比为100%或者0%,调整另一端的PWM占空比大小,例如这里我将PWM1设置成255,调整PWM2来调整驱动电流大小即可。通过调整INTERVAL的值改变转动速度,但是INTERVAL太小的话电机抖动,这时候就是没有使用霍尔传感器或者反电势法(BEMF)的最大缺点了。暂时不会做gif图:

这套电路可以很方便地改成启动那个带霍尔传感器的无刷电机,直接将霍尔传感器的三个信号接到单片机的IO口,根据霍尔信号进行换相,而不是使用延时进行换相即可,一般带霍尔无刷电机接线如下图:

但是这里还没有用到PWM的真正功能,就是平缓换相过程,也是角度控制功能。
上一篇:单片机MCU相关基础知识整理篇
下一篇:单片机异常复位后如何保存变量数据
史海拾趣
|
现在公司需要这个板子做项目,重新画了一下。 为了以后能用,是使用系统小板的模式 带sdram flash sd卡 usb接口 外接线基本上都接出了。 基本上是合众达板子的电路图了。找到它的图就可以了。 由于没有在原 ...… 查看全部问答> |
|
鸿远信通GPS“物流车”车辆管理系统是根据目前物流行业信息化管理需求开发的车辆管理系统,达到物流车辆及货物实时定位跟踪,从而将运输行业中的货主、货运代理及司机各环节的信息有效、充分地结合起来,降低空车率,最大限度的调配车辆,以显示 ...… 查看全部问答> |
|
利用flash224下载bootrom到arm9开发板,超级终端能连接并显示运行信息,网口的指示灯也是亮的,ping不通时为什么啊,望各位大哥大姐大虾大神不吝赐教。急!!… 查看全部问答> |
|
nWAIT [Input] nWAIT requests to prolong a current bus cycle. As long as nWAIT is L, th current bus cycle cannot be completed. ----- nWAIT PIN OPERATION If the WAIT bit(WSn bit in BWSCON) corresponding to each memory bank is en ...… 查看全部问答> |
|
我快急死了。大哥们帮一下小兄吧怎么读取PCI配置空间信息呀下面的程序不行呀 #include \"stdafx.h\" #include \"stdio.h\" #include \"windows.h\" DWORD DWORD_In(WORD io_Port) { DWORD val; _asm { mov dx,io_Port &nb ...… 查看全部问答> |
|
想给一个255系统下载程序,可惜没有下载线,能不能自己做个简单的,像wiggler那样的? email:ldqmoon@163.com 做成后百分相送~… 查看全部问答> |




