电机驱动的总结和实战
一、电机介绍
有刷电机(碳刷电机): 传统电动工具常用。其转子上有线圈,定子是永磁体。通过物理的“电刷”和“换向器”接触,来不断改变转子线圈中的电流方向,从而产生旋转磁场驱动转子转动。
-
缺点: 电刷摩擦产生损耗、火花、噪音和电磁干扰,效率较低,寿命较短。
无刷电机: 现代高端电动工具的主流。其结构相反——转子是永磁体,定子是线圈。由于没有电刷,需要通过外部的电子控制器来精确控制给定子线圈供电的顺序和时间,从而驱动转子转动。这个过程称为“电子换相”。
二、为什么电动工具青睐无刷电机
- 高效率与长续航: 无电刷摩擦损耗,能量转换效率更高(通常提升20%以上),意味着同样电池下工作时间更长,或同样功率下电池更轻。
-
高功率密度与动力强劲: 转子是永磁体,更轻,可以实现更高的转速和瞬时扭矩,启动和过载能力更强。
-
长寿命与免维护: 没有易磨损的电刷,电机本体寿命极长,可靠性高。
-
静音与低干扰: 无换向火花,运行更安静,电磁干扰小。
-
智能控制: 易于与电子控制器集成,实现速度精确控制、负载保护、软启动等高级功能。
三、无刷电机驱动的核心组成
一个完整的电动工具无刷驱动系统包括三个核心部分:
无刷直流电机: 核心执行机构。
转子位置传感器: 告诉控制器当前转子的位置,以便进行正确的换相。
-
霍尔传感器:最常用,提供数字信号,成本低,精度满足要求。
-
无传感器技术:通过检测电机反电动势来推算转子位置,省去了传感器和连线,更可靠,但在极低速或静止时无法检测。
电子控制器: 系统的“大脑”,通常是一块PCB板,集成了:
-
MCU: 负责算法运算、信号处理和控制逻辑。
-
驱动电路: 将MCU发出的弱电信号放大,去驱动功率MOSFET。
-
功率逆变桥: 通常由6个MOSFET组成三相全桥电路,将电池的直流电转换成三相交流电供给电机。
-
保护电路: 如过流、过压、欠压、过热保护等。
四、电机驱动方法
1. 基本工作原理:六步换相法
这是驱动无刷电机最经典和常用的方法,也称为“梯形波控制”。
步骤:
-
获取位置: 通过霍尔传感器或反电动势计算,获知转子磁极的位置。
-
确定通电相: 根据转子位置,控制器决定三相定子线圈(U, V, W)中哪两相通电。例如,让电流从U相流入,从V相流出。
-
产生磁场: 通电的两相线圈会产生一个合成的定子磁场。
-
磁极吸引: 转子(永磁体)的磁场会受到定子磁场的吸引或排斥,从而产生扭矩并转动。
循环切换: 转子每转过60电角度,控制器就根据新的位置信息,切换到下一组线圈通电。一个电气周期内共有6种不同的通电组合,因此得名“六步换相”。
如何控制速度?
-
通过PWM(脉冲宽度调制) 技术。控制器通过快速开关MOSFET,改变施加在线圈上的平均电压。PWM的占空比越高,平均电压越高,电机电流越大,转速就越快。
如何控制转向?
-
只需改变换相的顺序即可。例如,正转是 U->V->W,反转则是 U->W->V。
2. 驱动技术的进阶:FOC(磁场定向控制)
为了追求极致的性能和平顺性,高端电动工具开始采用FOC技术。
核心思想: 模仿直流电机的控制方式。它将三相电流通过数学变换(克拉克变换和帕克变换)分解为两个分量:
-
励磁电流: 用于产生磁场的分量。
-
扭矩电流: 用于产生扭矩的分量。
优势:
-
极致平稳: 运行非常平滑,震动和噪音极小,尤其在低速时。
-
高效率: 始终保持励磁和扭矩的最佳夹角(90°),实现“单位功率因数”控制,效率最大化。
-
高动态响应: 扭矩控制精准,响应快。
实现方法:
-
需要更强大的MCU来进行复杂的数学运算。
-
需要高精度的电流采样电路来反馈三相电流。
-
算法复杂度远高于六步换相法。
| 特性 | 六步换相法(带霍尔) | 六步换相法(无传感器) | FOC(磁场定向控制) |
|---|---|---|---|
| 成本 | 低 | 最低 | 高 |
| 复杂度 | 中等 | 中等 | 高 |
| 性能 | 良好 | 良好(但启动和低速性能差) | 优秀(全速域平稳、高效) |
| 可靠性 | 高(依赖传感器) | 最高(无传感器) | 高 |
| 适用场景 | 大多数主流电动工具 | 风扇、水泵、角磨机等对启动要求不高的工具 | 高端电钻、扳手、锯等要求高精度和平稳性的工具 |
五、实际项目案例
电池使用18V电池组。该驱动板具有欠压保护、过压保护、过流保护、堵转保护、电量检测、正反转切换,刹车等功能。可广泛应用于各类无刷电机的控制。
它由一个电动马达和一个可充电电池组成。这个电动马达通过传递旋转动力给机头上的钻头,从而实现钻孔、螺丝拧紧、切割或打磨等任务。
-
电动马达:它是手电钻的核心部件,负责产生动力并驱动钻头旋转。不同型号的手电钻功率不同。高功率的电动马达可以提供更大的扭矩和更高的转速,适用于处理坚硬材料或需要更快速度的工作。
-
钻头:钻头是安装在手电钻机头上的可更换配件,用于进行钻孔或切割操作。钻头的尺寸和类型根据不同的工作需求而变化,例如木材钻头、金属钻头、混凝土钻头等。一些手电钻还可以配备其他类型的机头,如螺丝刀头、砂轮切割头等。
-
电池:电钻通常使用可充电电池供电,这样可以使其更加便携和灵活。电池容量的大小决定了工作时间的长短,较大容量的电池可以提供更长时间的使用。一些电钻还支持快速充电功能,在短时间内充满电池以提高工作效率。
-
手柄和握把:电钻通常具有一个手柄和一个握把,使操作更加稳定和舒适。手柄是保持平衡和稳定的主要手部支撑,而握把则用于按下触发器按钮和控制手电钻的方向。
六、项目中反电动势检测
根据法拉第电磁感应定律和楞次定律,转子旋转的时候会在定子绕组中产生感应电势,该感应电势的方向与绕组的电压相反,极性与励磁电压相反,故一般称为反电动势或反电势。

七、项目代码
在while循环中,状态机是整个程序里面的核心部分。
状态机代码
switch(MOTORSTATE)
{case STATESTARTCHECK: MotorStartCheck(); // 电机开始状态检测 break;case STATESTARTDELAY:xxxx=0;MotorStartDealy(); // 启动延时DirCheck();break;case STATESTARTPID:MotorStartPID(); // 开始状态DirCheck();break; case STATERUNPID: MotorRunPID(); // 运行状态DirCheck();break;case STATEBREAK: MotorBreak();break;//刹车case STATESTOP: MotorStop();break; // 电机停止运转case STATEERROR: MotorError();break;//错误处理case STATEERROROVER: MotorErrorOver();break;// 错误处理完成case STATWAITSTART:WaitStart();break;//等待状态
}
电机启动代码
void MotorStartPID(void)
{ if(MOTORSTATE==STATEERROR)return; if(SetSpeed==0) // 如果设定速度为0,则退出启动{if(CanshuSTC==1){MOTORSTATE=STATEBREAK;SCFlag=1;}else MOTORSTATE=STATESTOP; }if(TargS1==0) // 目标速度为0,{ TargS1=MINSPEED;// 启动过程中缓加速步进值的计算if(CanshuSTT<10)CanshuSTT=10;SpeedD=MAXSPEED/(CanshuSTT/10);if(SpeedD<1)SpeedD=1;TargS1+=SpeedD; if(TargS1>SetSpeed)TargS1=SetSpeed;MOTOR_STOP0();OutPwmValue=0;HALL_MOTOR_START(); //电机启动PID_init(); // PID参数初始化PIDcompute(TargS1,0);TimeCountStartUP=0;TimeCountPID=0;HALLcountTemp=0;RealS1=0;}else if(TargS1<SetSpeed&&TimeCountStartUP>=10){TimeCountStartUP=0; TargS1+=SpeedD;if(TargS1>=SetSpeed){TargS1=SetSpeed;}}else if(TargS1>=SetSpeed){TargS1=SetSpeed;} if(TimeCountPID>=20)//计算实时速度并时行PID运算{TimeCountPID=0;RealS1=HALLcountTemp*500/MPolePairs;//HALLcount*50*60/6/POLEPAIRS; PIDcompute(TargS1,RealS1); } if(RealS1>=SetSpeed){TargS1=SetSpeed;MOTORSTATE=STATERUNPID;}//达到设定速度了,才认为启动成功,进入正常PID控制。}
电机运行代码
void ADCS_chuli(void)
{ static unsigned char cou=0;unsigned char hx=0;unsigned int thre=0;if(Sta!=2)return; BEMFConvertedValue =SampleData[TAB_BEMFChannel[Dir][bHallStartStep1]];RisingFalling=TAB_RFling[Dir][bHallStartStep1];if(Tonoroff==0) thre=10;//248; //OFF时刻采集。0.2V阀值248else thre=SampleData[2]; if(RisingFalling==FALLING)//下降沿{ if(BEMFConvertedValue<thre){cou++;if(cou>=2){cou=0; Sta=3; StCountComm++;//正确检测到第三相反电动势 FFlag=1;hx=1;}}else {cou=0;}}else if(RisingFalling==RISING){if(BEMFConvertedValue>thre){cou++;if(cou>=2){cou=0; Sta=3; StCountComm++;//正确检测到第三相反电动势 FFlag=1;hx=1;}}else {cou=0;}} if(StCountComm>=STCount&&StOk==0)//连续检测到固定数量的过零时,认为启动成功{StOk=1;} if(StOk==1&&hx==1){hx=0; if(StepTime>50){ BTIM_SetAutoreload(CW_BTIM3,StepTime/10); BTIM_SetCounter(CW_BTIM3,0);BTIM_Cmd(CW_BTIM3, ENABLE);}else{if(Dir==1){bHallStartStep1++;if(bHallStartStep1>=6)bHallStartStep1=0;}else {if(bHallStartStep1==0)bHallStartStep1=5;else bHallStartStep1--;} Commutation(bHallStartStep1,Motor_Start_F); }}
}
