简介:这份源码工程基于STM32F103实现无刷直流电机(BLDC)控制,同时支持无感反电动势检测与带霍尔传感器两种方式,并采用方波PID闭环算法,兼顾平稳启动与稳定运行。工程按功能划分为电机控制、PID算法、串口通信、OLED显示等独立模块,代码结构清晰,十分适合嵌入式开发者、电机控制初学者及需要快速搭建BLDC驱动方案的项目人员参考。资源包共202个文件,以C源码与头文件(86个)为主,附带编译生成的hex/axf固件、调试映射文件及工程配置,压缩包仅5.69MB,便于直接导入Keil工程查看运行。目前已有3723人学习下载。通过阅读源码可掌握无感/有感BLDC的启动、换相与PID调速细节,并能基于模块化代码快速移植到实际项目中,是一份兼具学习与工程参考价值的完整方案。 做无刷电机控制这几年,我见过不少人和我当初一样,手里有STM32F103最小系统板,也有一个无刷直流电机,但就是不知道软件上第一步该干嘛。这个基于STM32F103的无感/有感无刷直流电机方波PID闭环控制源码工程,就是解决这个问题的。工程把无刷电机最经典的方波驱动方案做成了完整可运行的形态:支持霍尔传感器参与的有感模式,也支持靠反电动势检测的无感模式,底层是六步换向加PWM合成,上层用PID做速度闭环,整套代码跑在一颗F103上。
这个工程适合谁?一是刚接触BLDC控制的学生和工程师,想从零跑通一套驱动;二是手头有硬件、想在现有项目中移植一套成熟框架的人。它会告诉你换向表怎么建、PWM怎么和换向配合、无感启动怎么拉起来、PID参数怎么调到一个能用的状态。下面我会从方案选型到实现细节,再到调试中踩过的坑,把这套工程的思路完整拆开。
1. 项目整体设计与方案选型
1.1 为什么要选STM32F103这颗老片子
很多人问,F103都多少年了,为什么还用它做电机控制。我的回答是:F103的定时器资源对于方波控制来说几乎是为这个场景准备的。TIM1是高级定时器,自带互补PWM输出、死区插入和刹车功能,不用额外IC就能驱动三相半桥的六路MOS管;另外还有通用定时器可以捕获霍尔信号或者做速度测量,ADC又够快,DMA能把采集结果连续搬进内存。对六步方波控制这种节奏来说,几百kHz的ADC采样完全够用,一颗便宜的F103C8T6就能把整个控制环路跑完。
另外一个现实原因是环境成熟。F103的库函数和参考工程非常多,不管是标准外设库还是HAL库,网上都有大量现成代码。对于新手来说,出问题之后能找到参考资料,这比芯片本身性能强弱重要得多。当然,如果你后续要做FOC高转速或者带编码器的伺服控制,F103会显得吃力,但在方波BLDC这个定位上,它性价比高、够稳定、资料多,作为入门和原型验证非常合适。
1.2 有感与无感模式的选择逻辑
有感模式依赖霍尔传感器,电机内部安装三个霍尔元件,每转60度电角度输出一组三位的状态组合,换向表直接查霍尔组合就能确定通电相。它的优点是低速性能和启动可靠性好,完全不怕负载突变,适合起步阶段或者用在需要精确控制的场合。缺点是电机必须带霍尔线,多一根线束,电机成本也更高。
无感模式则通过检测不导通相的反电动势过零点来推算转子位置,不需要任何额外的传感器,机械结构更简单,电机成本低,适合泵、风扇、小型电动工具这类对启动要求不苛刻的负载。它的难点在于电机静止时没有反电动势,所以启动必须要用特殊方式拉起来,低速重载下也容易失步。这套工程把两种模式都做进去了,实际使用中我一般建议:能上有感就上有感,调试省心很多;必须无感时,优先保证中高速工况稳定,再慢慢完善启动逻辑。做产品选型时这个判断顺序能帮你少走很多弯路,毕竟控制算法的复杂度最终会转成你的调试时间成本。
2. 方波控制的底层逻辑与换向实现
2.1 六步换向是怎么一回事
无刷直流电机的本质是三相绕组加永磁转子,要让转子持续转起来,必须让定子磁场始终领先转子磁场一定角度。方波控制用"六步"来描述一个电周期内的六次通电状态,每60度电角度切换一次通电相组合,每次让电机内部形成特定方向的定子磁场,拉着转子往前走。这六个状态按顺序循环,每个状态持续60度电角度,一圈电周期下来正好六个状态。
具体到三相桥的开关动作,每步只有两个管子导通,一个上桥一个下桥,构成电流通路。比如霍尔状态对应的通电逻辑可以查下表整理,这里以常见的120度间隔的霍尔安装方式为例,实际相序以电机手册为准:
| 霍尔组合 H3 H2 H1 | 通电相(上桥/下桥) |
|---|---|
| 001 | A+ B- |
| 101 | A+ C- |
| 100 | B+ C- |
| 110 | B+ A- |
| 010 | C+ A- |
| 011 | C+ B- |
这张表看起来简单,但它是整个换向程序的核心。你只需要每次读取霍尔状态,按表找到应该导通的管子,然后更新定时器比较值,别的交给TIM1的硬件去完成。调试的时候如果电机反转或者抖动,第一反应就是检查这张表是否和实际相序匹配,把任意两相电机线对调,或者把表顺序反过来,通常就能解决。我见过太多人在PID参数上折腾半天,最后发现只是换向表顺序错了,这类低级错误排查起来其实最快。
2.2 无感模式的反电动势过零检测
无感方案去掉霍尔之后,位置信息全靠反电动势。所谓反电动势,就是转子永磁体转动时在三相绕组里感应出来的电压。当某相绕组处于不导通状态时,这一相端口的电压就可以被用来检测转子位置。理论上,反电动势过零点对应转子磁极经过该相绕组中性的位置,再过30度电角度,就是该相的换向点。
工程里常用"虚拟中性点法":用三个电阻连成星形,接到三相端线上,产生一个人造的中点电压,再用比较器或者ADC比较该相端电压和虚拟中点电压,检测过零。工程代码里采用ADC采集端电压做软件过零判断的写法,好处是不需要额外加比较器硬件,只需要三个分压电阻加三个采样点。实际检测时要处理好滤波延时,因为从检测到过零到真正换向之间还有30度电角度要走,而这30度对应的时间是随转速变化的,所以必须根据当前转速动态计算延时,通常用一个定时器做软件延时换向。这个延时计算直接决定了无感模式的高速性能上限,延时偏差过大会导致换向点偏移、电流增大、效率下降。
2.3 无感启动强制换向与闭环切换
电机静止时反电动势为零,检测不到过零,所以无感启动必须走一段"开环强拉"流程。工程里的做法是三步:第一步是定位,随便给一个通电状态,持续三五十毫秒,让转子被定子磁场吸到确定位置;第二步是强拉,按照一个预设的换向周期T,强制按顺序切换六个通电状态,每次切换时间逐渐缩短,让转子逐步加速;第三步是切换,当检测到反电动势过零信号连续稳定出现若干次后,把控制权交给反电动势检测逻辑,正式进入闭环运行。
这里有一个很重要的细节:强拉时间不能太短,否则转子来不及跟上换向节奏,电流会很大但电机不动;也不能太长,否则加速太慢影响启动速度。我实测下来,拿常见的2212航模电机和12V电源,初始换向周期从30ms开始,每步减少0.5ms到1ms,电机能比较平稳地拉起来。如果负载重,初始周期和定位时间都要适当加长。这个参数没有通用值,需要针对你的电机和负载去标定,这也是无感方案比较依赖经验的地方。
3. PID闭环控制的实现与参数调节
3.1 控制结构:速度环还是位置环
这套工程的核心控制目标就是调速,所以主干是速度环PID。速度环的输入是目标转速和实际转速的偏差,输出是PWM的占空比目标值。实际转速在有感模式下可以由霍尔信号计算,比如用定时器捕获两个换向沿之间的时间,换算出机械转速;无感模式下则用换向周期倒推转速,因为一个电周期对应固定的机械角度,换向频率和转速是线性关系。
如果只做方波调速,一个速度环就够了。但如果你希望动态响应更好,可以在这个基础上增加内环电流环,变成速度-电流双闭环。外环速度PID输出作为内环电流目标,内环对母线电流做快速PID调节。双环的好处是限流方便、抗负载扰动强,但调试复杂度也会上升。工程里保留的是单速度环加限幅的形式,对大多数泵、风扇类应用已经够用。做双环时要注意两个环的带宽拉开差距,速度环频率低、电流环频率高,否则两个环会互相影响,系统容易出现低频振荡。
3.2 PID参数怎么调出稳定值
PID调参我自己的习惯是先去掉积分和微分,只留比例。设置一个较低的目标转速,逐步加大Kp,观察转速波形,直到出现等幅震荡,记录下这个临界增益和震荡周期。然后用经验公式计算一组初始参数,再微调。实际工程中增量式PID更常用,因为它只输出控制量的增量,天然带限幅,而且不会因为积分饱和产生大幅超调。
typedef struct { float kp; float ki; float kd; float target; float output; float err_prev; float err_prev2; } PID_Handle_t; float PID_Incremental(PID_Handle_t* pid, float current) { float err = pid->target - current; float delta = pid->kp * (err - pid->err_prev) + pid->ki * err + pid->kd * (err - 2.0f * pid->err_prev + pid->err_prev2); pid->err_prev2 = pid->err_prev; pid->err_prev = err; pid->output += delta; if (pid->output > PWM_PERIOD) pid->output = PWM_PERIOD; if (pid->output < 0) pid->output = 0; return pid->output; }这里有个容易踩的坑:速度反馈不能直接用原始换向周期抖动值,要加低通滤波或者多周期平均,否则PID会跟着测量噪声一起抖。我的做法是维护一个长度16的环形缓冲区做滑动平均,每毫秒更新一次转速反馈。Kp先调到系统临界稳定,再按经典整定公式折算,Ki取Kp的几分之一,Kd一般很小或者干脆不用。具体数值要看电机和负载,但我建议不要盲目照抄别人工程里的参数,那是针对别人的硬件标定的,直接搬过来大概率会震荡。
3.3 换向与PWM的软件衔接
PWM输出和换向在软件里是两件必须配合好的事。这个工程用TIM1的高级定时器生成六路互补PWM,三个通道分别对应A/B/C三相的上桥和下桥。换向只管一件事:决定当前周期哪两个管子处于PWM调制状态,其余管子要么全关要么全通。常见的调制策略是"上桥PWM、下桥常通"或者"上桥常通、下桥PWM",两者电流纹波特性略有差异,工程里默认用上桥PWM下桥常通。
换向时并不是简单地把新状态写进CCR就不管了。如果新状态和旧状态之间有管子从开变关、从关变开,必须在关断前留出死区时间。TIM1硬件支持互补输出的死区插入,配置好之后它会自动处理上下桥同时导通的危险,这部分一定要配置,否则换向瞬间上下桥直通,电流会瞬间飙升烧掉MOS管。代码里还需要在换向函数里屏蔽中断或者用双缓冲的方式更新比较值,避免换向过程中途被打断导致半桥输出异常。我遇到过一次诡异现象:电机一换向MCU就复位,后来查出来是PWM更新和ADC中断撞在一起,换向瞬间电流突变产生了地弹,把单片机的复位脚打到了低电平。
4. 实操过程与关键环节实现记录
4.1 硬件搭建与信号接线
硬件上,最省事的组合是一块STM32F103C8T6最小系统板加一块现成的三相逆变驱动板。驱动板一般会集成6个MOS管和栅极驱动芯片,输入侧接TIM1的六路PWM,输出侧接电机三相线。接线时注意逻辑地和功率地要单点相连,尽量靠近母线电容的位置,否则功率回路的高频电流会在地线上产生噪声,干扰单片机和霍尔信号。
霍尔信号是开漏输出,必须接上拉电阻到3.3V,不建议直接拉到5V,F103的IO虽然多数引脚兼容5V输入,但霍尔信号线往往离功率线很近,容易把噪声带进MCU的电源域。我给每路霍尔信号加了RC滤波,10k电阻配1nF电容,时间常数在几微秒,可以滤掉大部分开关毛刺又不明显影响换向沿。反电动势检测的采样点也一样,从三相端线通过电阻分压后进ADC,分压比根据母线电压选,确保最高电压不超过ADC参考电压。
4.2 在STM32上配置PWM和ADC采样
PWM配置用TIM1的PWM模式1,输出比较极性可以按驱动板需求设置。死区时间我按驱动器栅极电阻和MOS管的关断特性设置,一般在几百纳秒到2微秒之间。工程里为了调试方便,把PWM频率设在16kHz,这个频率听不到可闻噪声,而且周期小,电流纹波可以接受。配置时还需要打开TIM1的刹车功能,一旦检测到过流信号,硬件直接封锁输出,这个保护在调试初期非常重要,能帮你保住MOS管。
ADC这边要注意触发源的选择。无感模式检测反电动势最好在PWM输出点附近采样,因为下管导通时端电压是母线或地的电平,和采样点重合度直接关系到检测准确率。我的配置是让ADC由TIM1的更新事件触发,每次换向更新后延迟几十微秒启动采样,避免开关瞬间的尖峰耦合到ADC通道。采样结果由DMA自动搬运到内存数组,读到的就是三相端电压经过分压后的值,再在中断里做软件过零判断。实测下来这个结构的中断负载不高,F103完全扛得住。
4.3 用串口和上位机看内部状态
调试电机控制,光靠眼睛看电机转没转远远不够,还得能看见内部数据。工程里留了串口调试通道,每隔固定周期把目标速度、实际速度、PID输出、当前换向状态打包发送出去。我常用的调试上位机是VOFA+,配置好自定义协议后,数据以波形形式实时显示,调PID参数时效率高很多。平时看转速响应曲线,一眼就能分辨是Kp小导致的响应慢还是Kp大导致的振荡。
特别是观察无感启动过程中的换向频率曲线,能直接看到强拉阶段是不是平滑加速、切入闭环瞬间有没有速度跌落。如果切闭环时转速掉了,多半是开环强拉结束时转速和反电动势检测的相位没对齐,可以调整强拉换向周期递减速率,或者延迟切入时机,让它多跑几个周期确认过零稳定再切换。这一步调顺了,无感启动的成功率能提升一大截。
5. 常见问题与排查技巧实录
5.1 无感启动失败或电机抖动
这是无感方案里遇到最多的问题。电机嗡嗡响但不转,或者转一下就停,多半是强拉阶段换向周期和转子实际速度不匹配。转子一开始是被定位到某个位置的,换向太快它会跟不上,换向太慢又会让电流波形畸变。排查时先用示波器看母线电流波形,如果电流每次换向后迅速冲到限幅,说明转子没跟上磁场,调大定位时间,调慢初始换向周期。如果启动前半段正常、到中段突然失步,则重点关注切换点,确认过零检测没有误触发。
5.2 方波输出尖峰毛刺的问题
热词里提到的"方波输出有尖端毛刺",本质是换向瞬间的电流突变和寄生电感产生的感应尖峰。来源有三个:一是上下桥瞬间直通,二是MOS管开关速度太快,三是采样和PWM地线耦合噪声。对应的处理办法也直接:先把死区时间调够,再用示波器查上下桥驱动波形确认无直通;在驱动电阻上串一个小电阻(10欧姆左右)减慢开关斜率;最后检查功率地和逻辑地走线,母线电容尽量靠近逆变桥的电源输入端。这三步下来,毛刺幅度通常能压到可接受范围。如果对毛刺高度特别敏感,还可以在输出端并联一个小容量的吸收电容,但要注意别影响换向沿的陡峭程度。
5.3 PID调节总是不稳定
PID不稳定的原因不外乎两个方向:反馈质量差和控制量输出方式不对。反馈质量差表现为转速波形毛刺大、反馈值跳变,解决方法是加滤波或者换更精确的测速方法,比如用输入捕获测量霍尔周期而不是单纯数脉冲。控制量输出方式不对,最常见的是增量式PID输出直接加到占空比上,没有根据调制策略做映射,导致转速高时占空比饱和、低速时又过小,调参怎么调都不对。我习惯把PID输出限制在一个合理的占空比范围,比如5%到95%,并在程序里加积分限制,避免积分饱和。
提示:如果电机带负载后噪声变大,先不要急着调PID,先确认换向逻辑正确、电流波形正常。很多时候所谓PID问题,其实是换向或者采样的问题在PID里被放大了。
最后再说一个我实际调试中摸索出来的小经验。很多朋友喜欢一上来就上最高转速测试,其实对于方波无感方案,先在低速、轻载条件下把换向和启动流程吃透,再逐步加转速和负载,是最省时间的路线。我自己踩过的最大一个坑,就是以为PID参数万能,结果换了电机之后整个启动流程都要重新标定,后来才明白,方波BLDC控制的上限其实由换向逻辑和启动算法决定,PID只是锦上添花。这个工程把最基础也最核心的通路铺好了,剩下的就是拿着示波器,一项一项验证你的换向表、过零检测和启动参数,跑通之后你会对无刷电机控制有一种非常踏实的掌控感。
本文还有配套的精品资源,点击获取