去年冬天我把手里一套PMSM无感FOC项目从V1.0推到重来,重新搭了控制框架、重画了驱动板、把转子初始位置检测和无感启动策略全部换掉。这个版本我在内部代号叫FOC-P2-DRAFT_V2.0,P2是第二阶段的缩写,DRAFT说明它还带着草稿性质,但到目前为止,它是我调试过的最顺的一版FOC代码。如果你正在做无感FOC入门、被转子初始位置检测和启动策略卡住,或者纠结于FOC仿真怎么落地到STM32实物,这篇内容应该能帮你少走不少弯路。我会把从Simulink仿真到电路板改版、再到波形调试的完整链路记录下来,重点讲那些文档里不会写的判断依据和试错过程。
1. 为什么P2选择推翻重来:V1.0遗留的三大顽疾
1.1 V1.0的启动失败与过流保护误触发
V1.0其实已经能转,但只在台架空载情况下能转。接上负载之后,启动阶段大概率失败,表现是电机先抖动两下,然后过流保护直接跳掉。我最初以为是电流环PI参数太激进,把Kp和Ki往小了调了好几轮,结果发现治标不治本。后来抓波形才明白,问题不在电流环,而在转子角度估算在零速和低速区间完全不可用。无感FOC的核心逻辑是“坐标变换依赖转子角度”,角度不准,电流环再准也没意义。
另一个顽疾是过流保护误触发。V1.0的硬件保护只做了母线侧采样,没有对相电流做逐周期比较。启动瞬间电流尖峰很大,母线电容充电、IGBT开关过程、以及死区时间内续流管反向恢复,都会让母线电流采样值出现几百纳秒的毛刺。这些毛刺一旦超过比较器阈值,驱动芯片直接封锁输出。我当时查了很久才发现,软件上已经做了消抖,但硬件比较器没有加RC滤波,等于软件消抖形同虚设。
1.2 V2.0的目标定位:不追求指标,追求可控
重构之前我列了一个问题清单,逐条对应V1.0的故障现象,然后给V2.0定了三条硬性目标。
| 目标 | 对应V1.0问题 | 验证方式 |
|---|---|---|
| 转子初始位置检测误差在电角度15度以内 | 启动抖动、反转 | 锁住电机轴,对比编码器读数 |
| 零速到额定转速全程不丢步 | 带载启动失败 | 逐步增加负载扭矩测试 |
| 相电流采样毛刺不触发硬件保护 | 过流误触发 | 连续启停100次统计误触发次数 |
这个阶段我没有执着于效率和弱磁扩展,先把“可控”做好。FOC调试最怕的是多个问题叠加在一起,你不知道该调谁。所以V2.0的目标刻意收窄,每个版本只解决一类问题。
1.3 一个反直觉的结论:代码结构比算法选型更重要
V1.0的算法选型其实不算差,用的也是滑模观测器加锁相环。但代码写成了一个大循环里塞了三千行,所有状态变量堆在全局区,调试的时候改一个参数要全局搜索好几处。V2.0我做的第一件事不是改算法,而是把代码按模块拆开:电流采样、坐标变换、PI控制器、SVPWM、观测器、启动状态机各自独立成文件,每个模块的输入输出结构体明确定义。这看起来不增加任何技术含量,但对调试效率的提升是决定性的。后面我定位波形异常,基本靠看各个模块的输入输出中间量就能缩小范围。建议大家在做FOC项目时,先把代码结构理清楚再谈算法,不要让状态变量满天飞。
2. Simulink仿真不是走形式:参数整定和边界摸底
2.1 电机参数的辨识方法
很多入门教程会直接给一套PMSM参数,让你拿进去跑仿真。但真做项目你会发现,电机铭牌参数和实际参数差别不小,尤其是Ld、Lq和永磁磁链。V2.0仿真阶段我花了整三天时间做参数辨识,方法不高级但很实用。
- 直流伏安法测相电阻:给两相之间加直流电压,记录稳态电流,R = U / (2I)。
- 高频电压注入测电感:定子通入高频电压,测量高频电流幅值,通过阻抗三角形分离出电感值。
- 反电动势法测磁链:用另一台电机拖动被测电机到额定转速,用示波器测线反电动势峰值,Ke = E / (转速 × 极对数)。
这几个方法在教科书里都有,但实操时有两个坑需要提醒。第一,直流伏安法测出来的电阻包含了线路电阻和MOSFET导通电阻,估算PI参数时要把这部分误差算进去;第二,高频注入测电感时要保证转子固定不动,否则高频电流中会混入运动反电动势,测出来的电感值偏大。我起初没注意转子固定,测出来Ld比实际大了将近30%,导致电流环带宽估算严重偏高。
2.2 电流环PI参数的计算与仿真验证
FOC控制器的电流环是内环,速度环是外环。电流环PI参数我习惯用频域法整定,简单说就是先确定想要的电流环带宽ωc,然后按公式计算PI参数。
对于表贴式PMSM,Ld约等于Lq,电流环被控对象近似为一阶惯性环节加积分特性。PI参数计算可以按这个思路:Kp = L × ωc,Ki = R × ωc。这里的L和R是相电感和相电阻,ωc是期望的电流环截止角频率。实际工程中,ωc一般取开关频率的1/10到1/20。我用的开关频率是16kHz,电流环带宽取1.5kHz左右,折合角频率约9424rad/s。把辨识出来的L=0.42mH、R=0.35Ω代进去,Kp≈3.96,Ki≈3298。这套参数进Simulink跑阶跃响应,超调量大约12%,调节时间约0.5ms,符合预期。
有个细节容易被忽略:Ki的单位和离散化方式。在Simulink里直接用连续域PI,下到STM32是离散域,必须做前向欧拉或双线性变换。如果离散周期是62.5us(16kHz),Ki离散化后要乘以采样周期,数值会小很多。很多人在仿真里调好的参数搬到单片机就发散,十有八九是离散化单位没转换对。
2.3 仿真模型的速度环与启动逻辑模拟
Simulink模型里我搭了完整的FOC闭环:转速外环加电流内环,SVPWM调制,逆变器用理想开关模型。速度环PI参数用ITAE最优法做初值,然后在阶跃响应基础上手动微调。仿真最大的价值不在于把参数调到最优,而在于把启动逻辑跑通。我专门搭了一个状态机,模拟“预定位→开环强拖→切换闭环”的全过程。这个阶段验证了切换判据的合理性:转速超过额定5%且角度误差连续50个控制周期小于10度才允许切换。这个判据在仿真环境里很好使,但到了实际硬件上,角度误差的获取本身就有噪声,后面我又加了滞回和超时保护。
2.4 仿真与实物的差距认知
Simulink仿真跑得再漂亮,也不能直接代表实物结果。最明显的差距在于逆变器非理想特性:死区时间会导致输出电压畸变,开关管压降会让输出电压偏低,采样噪声在仿真里根本不存在。所以我的做法是,仿真只用来确定参数初值和验证逻辑正确性,真正的调参必须回到实物上。你在仿真里花一个月把参数优化到0.1%误差,不如实物上认真调半天。这个认知帮我省了很多时间。
3. 电路板改版:采样、驱动、保护三件事一次做对
3.1 驱动方案与自举电容的选型细节
V2.0驱动板的主控选了STM32G431系列,内置比较器和运放,做FOC很合适。驱动芯片用的是DRV8353RS,内置三个半桥驱动和电流采样放大器,外围电路比分立方案简单很多。电源架构上,12V输入经降压给MCU供电,电机母线直接接电池电压,栅极驱动采用自举供电。
自举电容的取值我吃了不少亏。初期按数据手册推荐选了100nF,结果占空比接近100%时上管驱动电压掉到不足以完全导通,电机高速时突然抖动。后来换成1uF低ESR陶瓷电容,问题消失。这个细节特别提醒一下:FOC运行中PWM占空比是实时变化的,自举电容电荷补充时间窗口不固定,电容容量太小会在高占空比时出现驱动欠压。选1uF是权衡了充电速度和电荷维持能力之后的结果。另外自举二极管的反向恢复时间要短,否则上管关断时会出现瞬间直通。
3.2 三电阻采样方案与采样窗口约束
相电流采样我用了三电阻方案,三个低阻值采样电阻分别串联在逆变器下管源极和地之间,通过运放放大后送STM32的ADC。三电阻方案可以在任意时刻重构三相电流,配合中心对齐PWM最容易实现。但这里有个硬性限制:PWM有效脉宽必须大于ADC采样窗口时间和死区时间之和。以16kHz开关频率、62.5us周期为例,如果死区设置500ns,ADC采样窗口1us,那么最小有效占空比至少要保证1.5us以上,低于这个值电流采样会落入死区或干扰区间,测出来的电流完全是错的。
高速运行时占空比可能逼近0或100%,单靠三电阻方案很难保证全程精确采样。我在这版没有做单电阻重构,而是加了限制:当采样窗口不足时,保持上一周期的电流值作为PI输入,同时在观测器输入侧对这个值做低通处理。这个办法不完美,但工程上够用。
3.3 PCB Layout的三个关键点
电路板Layout决定采样精度,这个环节出问题的概率非常大。我总结三个最关键的注意点。
- 采样电阻到运放的走线必须采用开尔文连接,即采样电阻两端分别走两根线到运放输入端,避免采样电流流经地线产生压降误差。
- 功率地和控制地单点连接,连接点放在母线电容负极端。不要让功率地的开关噪声串入控制地,否则ADC采样值会周期性波动。
- 驱动芯片的Bootstrap引脚到自举电容的距离要尽量短,寄生电感过大会在瞬间充放电时产生振铃,振铃幅度可能超过驱动芯片的绝对最大额定值。
这三个点V1.0全部踩过。V1.0的板子是手工飞线搭的,采样误差大到我一度怀疑运放坏了,后来用万用表测运放输入引脚,发现地线压降达到了20mV级别,折算到采样电流误差大约0.5A,这在低速堵转时足以导致观测器输出异常。
3.4 硬件保护与软件保护的分工
V2.0把过流保护分成两级。硬件级:驱动芯片的比较器检测相电流,超过阈值直接封锁PWM输出,不经过MCU,响应时间在1us以内。软件级:MCU的ADC在每个控制周期读取电流值,超过设定阈值时主动关断PWM,响应时间在一个开关周期以内。硬件保护负责防烧毁,软件保护负责精细控制(比如堵转检测、过热降额)。硬件保护阈值要设置得比软件保护高20%左右,避免启动瞬间的正常尖峰误触发硬件保护。
这个设计解决了V1.0的误触发问题。硬件保护本身带RC滤波,时间常数设置为200ns左右,滤掉开关尖峰而不影响对真实过流的响应。实测下来,连续启停100次,误触发次数从之前的十几次降到了零。
4. 转子初始位置检测:无感FOC最容易翻车的环节
4.1 为什么零速必须知道初始角度
FOC坐标变换依赖转子电角度。如果初始角度误差大,Clark变换和Park变换得到的d/q轴电流就不是真正的励磁和转矩分量。启动瞬间如果角度偏差超过90度电角度,电流产生的力矩方向可能完全反了,电机表现为抖动或者反转。低速无感方案在零速时反电动势为零,无法通过反电动势估算角度,所以必须用其他手段获取初始位置。
4.2 高频注入法的原理与实现细节
V2.0采用的方案是脉振高频电压注入法,基本原理是在估算d轴上叠加一个高频正弦电压,然后检测q轴高频电流响应。由于PMSM的凸极效应(Ld和Lq不相等),转子角度偏差会导致q轴高频电流幅值变化,通过锁相环收敛到偏差为零的状态。
具体实现时,我注入的频率是1kHz,幅值约为母线电压的5%。高频电流提取用的是带通滤波器加乘法解调,再经过低通滤波器得到角度误差信号。这里有几个参数可调:注入频率、注入幅值、带通滤波器Q值、锁相环带宽。
调试时最直观的问题是角度收敛时间。我把锁相环带宽设得较高时,收敛时间能压到50ms以内,但抗噪声能力变差,角度会有持续的小幅振荡。带宽降低以后角度稳定了,收敛时间却拉长到200ms左右。最终折中在100ms收敛,稳态角度波动控制在3度以内。对于大多数启动场景,100ms完全可以接受。
4.3 高频注入的边界:不适合所有电机
高频注入依赖显极性,也就是Ld和Lq之间的差值。内嵌式PMSM(IPMSM)差异明显,效果很好;但表贴式PMSM(SPMSM)如果设计上没有刻意增大凸极率,Ld和Lq几乎相等,高频电流响应里几乎没有能用来收敛的角度信息,这个方法会失效。
V2.0的电机是表贴式结构,我测量它的Ld/Lq差值只有约8%,注入1kHz高频电压解调出来的误差信号信噪比很低。为了撑过这个坑,我做了两件事:一是把注入频率提高到2kHz,避开电流环PI带宽附近的高增益区;二是在锁相环输入端加了一个中心频率跟踪的窄带滤波器,把带外噪声抑制住。实测在这个电机上角度收敛稳态误差能控制在8度电角度以内,够用但没有余量。
4.4 备选方案:预定位与开环强拖
如果高频注入效果不理想,另一个务实方案是预定位加开环强拖。预定位的思路很简单:给一个固定的d轴电流矢量,让转子转到已知角度。比如给定d轴电流方向为0度电角度,转子会被拉扯到接近0度的位置,然后把这个角度作为FOC的初始角度。
这个方法有一个致命缺陷:如果负载扭矩大于定位扭矩,转子无法转到目标位置,初始角度就不可信。定位扭矩等于1.5倍极对数乘以磁链乘以d轴电流,理论上可以靠加大电流提高定位扭矩,但电流过大会导致电机发热甚至退磁。V2.0的妥协方案是:先做一次短时大电流预定位(电流限幅3A,持续200ms),然后做高频注入微调。两者结合既保证了抗负载能力,又能修正预定位残留的误差。
提示:预定位时如果电流方向给反了,转子会反转180度,这个方向反着转的问题在代码里必须有保护逻辑,我最早调试时电机突然反转把台架上的联轴器都甩断了。
5. 波形调试实录:四个最折磨人的问题及排查链路
5.1 相电流波形畸变:采样点偏移是元凶
第一次让电机转起来后,我用示波器抓了A相电流波形,发现正弦波顶部有平顶畸变,而且每个电周期出现两次。这个现象我排查了将近两天,最终定位到ADC采样时刻上。
问题出在中心对齐PWM的采样触发点。三电阻采样需要在PWM计数器的周期中点触发ADC,这时候下管导通时间最充分,采样窗口最大。但我在配置定时器时把ADC触发点设置在计数器上溢事件,实际上应该设置在下溢事件或比较匹配事件。差一个计数周期在62.5us的PWM周期里看似不多,但正好落在死区切换的噪声窗口内,导致采样值混入了开关噪声。修正触发点后,电流波形立刻变得干净,THD从之前的15%降到了约4%。
这里给新入门的读者一个判断方法:把示波器探头放在采样电阻两端,看有没有高频振铃。如果振铃出现在ADC采样时刻附近,那波形畸变的根源十有八九在采样时刻选择不对。
5.2 观测器角度漂移:滑模增益的整定逻辑
V2.0的转速估算用的是滑模观测器加锁相环。滑模观测器提取反电动势,锁相环从反电动势中提取角度和转速。调试中最常见的问题是角度在中高速阶段周期性漂移,表现为d轴电流分量不再是纯直流,而是叠加了一个6倍频波动。
这个现象的本质是反电动势观测中出现了谐波。滑模观测器的开关增益设置过高时,反电动势估算值里会混入较多的高频分量,锁相环虽然能滤掉一部分,但在6倍频附近仍有残余。而PMSM的反电动势本身含有3次和5次谐波,经过Clark变换后会体现在6倍频谱上。
我最终的调法是降低滑模增益到略高于反电动势幅值最大值的水平,同时加大锁相环的环路滤波器带宽到200Hz。这一步调完之后,角度波动从原来的15度降到了4度。大家调FOC波形时一定要记住,观测器参数不是越大越好,增益过大反而会让估算值引入噪声,最优值往往在临界值附近。
5.3 启动阶段角度跳变与电流冲击
无感FOC从开环强拖切换到闭环估算时,最容易出现的问题是角度跳变导致电流冲击。开环强拖阶段,我们认为转子角度是积分得到的(其实就是人为给定的斜坡角度),而闭环阶段角度来自观测器。两者在切换瞬间不可能完全一致,如果直接切换,角度差会导致电流环输出剧烈波动,表现为电流冲击。
我的解决思路是切换前做渐进过渡:在切换窗口内(约200ms),开放比重从开环角度线性过渡到观测器角度,相当于给系统一个“软着陆”的过程,而不是硬切。过渡期间FOC的电流环输出和SVPWM调制都连续变化,电流冲击被明显抑制。实测切换时刻母线电压跌落从之前的3V降到0.8V。
5.4 过流保护偶尔复现:空满载状态下的阈值自适应
即使做了硬件滤波,过流保护在特定工况下还是会偶发。主要集中在满载启动和突然加减载时,电流尖峰持续时间很短(几微秒到几十微秒),但幅度超过了硬件保护阈值。解决思路不是继续加大滤波深度(那样会拖慢真实过流响应),而是让硬件保护阈值随运行状态自适应:启动阶段和稳态阶段使用不同的阈值,启动阶段阈值比稳态高30%,这样既保证启动不误触发,也保证稳态过流能被及时捕获。
这个改动在V1.0时完全不敢想,因为硬件比较器阈值是模拟电阻配置的。V2.0用了STM32G431内置可编程比较器,阈值可以直接通过DAC设置,软件改阈值非常方便。如果你用的驱动芯片不支持比较器阈值编程,可以通过外部分压电阻和模拟开关实现类似功能。
6. 边界工况与版本收尾:我在V2.0实验记录里写了什么
6.1 实验记录表格的价值
项目调试阶段,我坚持每天写实验记录,内容包括:电机型号、母线电压、环境温度、控制器参数(电流环Kp/Ki、速度环Kp/Ki、观测器增益、注入频率)、测得的电流波形图、角度误差、启停次数、失败现象描述。这套记录在最后收尾时起到了决定性作用——我可以精确回溯每个参数是在什么状态下修改的,而不是靠记忆猜测。
这不是工作习惯问题,而是工程效率问题。FOC参数之间有强耦合,一次只改一个参数并记录结果,才能建立可靠的因果链。我见过很多人调试时同时改三个参数,调好了不知道是哪个起的作用,调坏了也不知道是谁的锅。实验记录的意义就在于打破这种混沌状态。
6.2 边界工况测试清单
收尾阶段我按以下清单做了一轮完整的边界测试:
| 测试项 | 工况 | 预期结果 |
|---|---|---|
| 低压启动 | 母线电压降至额定60% | 正常启动无失步 |
| 空载高速 | 电流环无负载 | 转速闭环无超调 |
| 满载爬坡 | 加载到额定扭矩的120% | 不丢步不过流 |
| 频繁启停 | 1秒间隔连续启停100次 | 误触发不超过2次 |
| 温度漂移 | 连续运行1小时 | 角度误差不随温度发散 |
每项测试都要记录实测值,与预期结果对照。特别是温度漂移这项,很多项目忽略。电机发热后永磁体磁链会下降,同样的电流产生的力矩变小,导致速度环需要更大的电流输出。如果观测器参数对磁链变化敏感,温度升高后角度估算误差会放大,最终表现为持续运行的后期出现异响或抖动。
我在这轮测试中发现,V2.0在连续运行40分钟后,q轴电流缓慢增加了约8%,但角度误差仍控制在5度以内,说明观测器对磁链变化有一定鲁棒性。如果角度误差随温度明显扩大,下一步就需要考虑在线磁链辨识或温度补偿。
6.3 DRAFT版本遗留的问题清单
V2.0虽然整体稳定,但仍有几项遗留问题,我明确记录下来留给下个版本处理。
第一,高频注入在2kHz注入频率下,可闻噪声比较明显,站在台架旁边能听到吱吱声。有条件的方案可以尝试将注入频率提升到20kHz以上,进入超声频段后听不见,但对采样率和运放带宽要求更高。
第二,堵转检测的阈值需要针对不同负载惯量标定,目前是一个固定阈值适应所有工况,存在一定的误报概率。下一版打算把堵转检测改为基于电流变化率和转速变化率的联合判断。
第三,弱磁控制尚未实现。V2.0最高运行在额定转速附近,如果要往更高转速扩展,必须引入弱磁电流分配策略。这个功能对电池供电的移动平台场景尤其重要,因为电池电压随电量下降,不弱磁就上不了高速。
这些问题我在代码注释里都做了标记,每个标记都附带复现条件、可能原因和初步解决思路。这也是我把这个版本叫DRAFT的原因——它可用,但还远谈不上完美。
结尾:关于FOC-P2-DRAFT_V2.0这次迭代,我个人最大的体会是:无感FOC的难点不在某个单点算法有多高深,而在于各个模块之间的耦合关系。转子位置检测影响启动,启动策略影响电流冲击,电流冲击影响保护逻辑,保护逻辑又反过来限制启动策略的边界。调试时如果没有全局视野,很容易在一个局部问题里打转。我自己的经验是,遇到问题先不要急着改参数,先把从采样到SVPWM的整条信号链摸一遍,确定哪一级的中间变量偏离了预期,再针对性地调整。V2.0的代码和驱动板目前已经跑通,下一步我会把弱磁和在线参数辨识补上,有进展再来更新。如果你也在调无感FOC,欢迎对照这篇内容里的排查思路去检查自己的系统,特别是采样触发时刻和自举电容这两处,往往能帮你省下好几个通宵。