公司动态

STM32F103无刷电机方波控制:有感无感与PID闭环实现详解

📅 2026/9/1 12:55:34
STM32F103无刷电机方波控制:有感无感与PID闭环实现详解
简介这份源码工程基于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通电相上桥/下桥001A B-101A C-100B C-110B A-010C A-011C 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不建议直接拉到5VF103的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只是锦上添花。这个工程把最基础也最核心的通路铺好了剩下的就是拿着示波器一项一项验证你的换向表、过零检测和启动参数跑通之后你会对无刷电机控制有一种非常踏实的掌控感。本文还有配套的精品资源点击获取