资讯动态

FPGA实现永磁同步电机双闭环FOC:从坐标变换到SVPWM的硬件实践

发布时间:2026/10/20 15:52:28 来源:尧图企业网站定制
1. 为什么把双闭环FOC放进FPGA先回答“划算不划算”做永磁同步电机PMSM的矢量控制绝大多数工程师的第一反应是选MCU或者DSP毕竟生态成熟、例程多、上手快。我之前也一直这么干直到在一个需要同时控制四台电机而且电流环带宽要求很高的项目里发现单片机的中断嵌套和串行执行开始拖后腿才认真考虑把整个双闭环控制系统搬进FPGA。做完之后回头想这个选择到底划不划算值得好好捋一捋。1.1 先看三套方案的底层差异矢量控制本身是一个明确的算法链采样三相电流、坐标变换、PI调节、反变换、SVPWM输出。这套算法在MCU/DSP里是“串行跑”的在FPGA里则是“并行搭”的。差别不在算得快不快而在延迟和确定性。MCU方案靠定时器中断触发ADC采样然后在中断服务函数里依次执行变换和PI运算。优点是开发快、改参数方便缺点是中断响应时间受其他中断影响环路频率做高了之后CPU占用率飙升。DSP方案专门为电机控制优化过单周期乘加、三角函数加速是目前工业伺服的主流。但如果要多轴同步控制DSP的串行架构意味着环路频率会随着轴数增加而下降。FPGA方案整个控制环路用硬件描述语言搭成组合逻辑加寄存器流水线每个时钟周期都能吞吐数据多台电机就是多套并行模块互不抢占。从纯性能角度看FPGA在同等成本档位下可以把电流环频率做得很高并且环路延时是固定的、可计算的不像MCU那样受分支预测和中断优先级影响。这对要求低相移、高动态响应的应用场景很关键。1.2 什么项目真正需要FPGA做FOC不是说FPGA做FOC一定比DSP高端得看场景。我总结下来以下三类项目是FPGA真正能发挥优势的地方第一类多电机同步控制。比如纺织机械、机器人关节群、多轴转台电机之间需要严格的相位同步。用FPGA的并行特性四台电机的SVPWM可以在同一时刻更新占空比轴间同步误差能做到微秒级。第二类电流环带宽要求极高的场合。比如某些高频注入的无传感器方案、高刚度伺服系统电流环要跑到20kHz甚至更高。MCU在20kHz环路下剩余时间已经很少而FPGA里电流环就是一条固定延迟的流水线10kHz和50kHz只是时钟分频的事。第三类需要和功率级深度耦合的系统。FPGA可以轻松把PWM死区补偿、硬件过流保护、ADC触发时序、编码器解码全部纳入同一个时序域做到纳秒级的确定性。1.3 资源评估用一个什么规模的FPGA才够很多初学者上来就想用最高端的FPGA做电机控制其实是资源浪费。PMSM双闭环FOC的硬件消耗并不高。我用的是一块中低端逻辑规模的芯片主要消耗在以下几块坐标变换模块几个乘法器加加减法器组合逻辑为主Park变换需要的正余弦函数我选了CORDIC硬核或查表大概几百个逻辑单元三个PI调节器d轴、q轴、速度环每个就是一组乘加、积分累加、限幅比较SVPWM模块扇区判断和占空比计算纯组合逻辑加少量寄存器编码器解码模块正交解码加Z脉冲捕获如果FPGA内部没有ADC还要外挂并行ADC或SPI接口ADC的控制时序。总的LUT消耗通常不到五千个Block RAM很少用DSP乘法器用掉几个。也就是说一片入门级FPGA就足够跑完整的双闭环FOC还能剩余资源做通信、保护逻辑甚至第二台电机的控制。这也是这项技术的优势——入门门槛并没有想象中那么高。2. 坐标变换在硬件里的正确打开方式Clark到Park的全链路细节项目标题里特意提到了“坐标”这确实是整个FPGA实现FOC里最容易出错的一块。坐标系变换在C语言里就是几行浮点运算但在硬件里每一处都要考虑位宽、定点格式和运算顺序。我调试时有一大半时间都花在这上面。2.1 Clark变换看似简单位宽扩张是第一个坑三相电流采样进来之后第一步是Clark变换把abc三相静止坐标系映射到αβ两相静止坐标系。公式不复杂i_alpha i_ai_beta (i_a 2 * i_b) / √3工程上经常做电流采样如果ADC是12位采样值经过符号扩展后是16位有符号数。这时做乘加运算位宽要预留足够的增长空间。2 * i_b是一个17位数加上i_a后可能变成18位再做一次除以√3的有符号乘法等价于乘以1/√3的定点数结果又需要扩展。我在调试时就踩过一次alpha轴直接取了i_a没有做任何处理beta轴却做了一通乘法除法运算结果两路数值范围不一致后续Park变换出来的id和iq偏得离谱电机低速时还能转一加速就开始抖动。后来统一把两路都做了一次全精度的乘加处理再将结果截断到统一位宽问题才消失。2.2 sin/cos从哪来查表还是CORDICPark变换需要转子电角度θ的正余弦值。在FPGA里获取正余弦有两种主流做法查表法LUT和CORDIC算法。查表法最简单把0到2π分成2048或4096个点每个点存一份sin值和cos值用θ的量化值查表。好处是延迟固定、资源少坏处是角度分辨率受表大小限制。电机极对数多、转速高的时候每个PWM周期内电角度增量很大如果表分辨率不够低速时就会出现明显的转矩脉动。CORDIC算法不需要大表只需要移位和加减运算通过迭代旋转来逼近目标角度精度可以做到很高。缺点是迭代次数和流水线深度成正比延迟相对大一些但电机控制里一个电流环周期有几十微秒多出几十个时钟周期的流水线延迟完全可以接受。我实际采用的是折中方案使用CORDIC做主运算路径同时在角度值的低几位做dither扰动避免低速时的量化噪声集中在某个固定频点。这个做法在听感上类似数字音频的抖动处理效果非常明显电流波形的高频毛刺明显变平滑。2.3 角度对齐Z脉冲和编码器零点的摆放坐标变换用得再好如果角度来源本身不对一切白搭。增量编码器的ABZ信号里Z脉冲才是“绝对位置”的基准。我遇到过换上新编码器之后电机转动噪声大、电流有效值偏高的问题排查了很久才发现是机械安装时把编码器零点转了30度而软件里没有做对齐校准。FPGA实现时建议在编码器解码模块里对Z脉冲捕捉做特殊处理Z脉冲到来时记录当前计数器值并把它和电角度初始偏置做减法得到真正的角度零点。同时Z脉冲要加数字滤波避免机械抖动造成多次触发。这一步如果做扎实后面速度环和位置环的调试会顺畅很多。3. 双闭环的时序架构电流环多快、速度环多慢才算合理双闭环是电流内环加速度外环这个架构在理论上很成熟但到了FPGA里“时序”被赋予了新的含义不仅要考虑环路频率还要考虑硬件模块之间固定的流水线延时。3.1 电流环频率是设计主轴PMSM矢量控制中电流环是整个系统的基石它的带宽决定了转矩响应的速度也限制了速度环能有多快。工程上一般取电流环频率在10kHz到20kHz之间速度环取1kHz到5kHz。在FPGA里我不再用定时器中断来区分环路而是用一个统一的时钟基准通过使能脉冲分频来触发不同环路的运算每个PWM周期比如10kHz的开关频率对应100微秒周期触发一次电流环运算每5个或10个电流环周期触发一次速度环运算速度环输出的q轴电流给定通过寄存器传递给电流环两边天然解耦。这种基于使能脉冲的调度方式本质上就是把原来的“中断嵌套”变成了“并行同步”所有模块共享同一个时基不会出现电流环跑到一半被速度环抢占的情况。3.2 电流环总延时的计算电流环从ADC采样到SVPWM更新中间经过Clark、Park、PI、反Park、SVPWM每个模块都有固定的流水线时钟数。我当时的流水线总延迟大约是1.5微秒在100MHz主频下这个延迟要远小于电流环周期100微秒所以对控制性能的影响很小。但如果使用浮点IP核或者复杂的CORDIC延迟会成倍增加。调试时可以通过仿真工具精确查看每个模块的延迟然后统一做延迟补偿。一个经验是反Park变换使用的角度值要比当前采样时刻的角度滞后半个PWM周期如果直接在采样时刻的同一个周期内更新PWM会导致相位滞后在高转速下表现为d轴电流耦合增加。3.3 标幺制让速度环和电流环的参数统一双闭环的PI参数调试很多资料直接给“先调内环再调外环”但实际做的时候会遇到量纲不匹配的问题电流环的反馈是安培速度环的反馈是转每分钟PI参数的量纲完全不同。在FPGA实现中我建议统一采用标幺制per-unit来表示所有物理量。电流基准取额定电流对应的ADC满量程值速度基准取额定转速对应的编码器频率这样两个环路的PI输出都在同一个数值范围内便于定点和调参。标幺制还有另一个好处PI参数在不同的电机之间可以直接复用只需要修改基值。4. SVPWM和PI的定点实现从公式到可综合代码的转化算法模型里用的是浮点数FPGA里要转成定点数。如何选择定点格式、如何处理除法、如何避免溢出这些才是硬件实现和软件实现最大的分水岭。4.1 Q格式选择和动态范围我采用的是Q14格式表示角度和电流反馈值即1位符号位加1位整数位加14位小数位。这样数值范围在-2.0到2.0之间对于归一化的电流范围足够。PI输出和SVPWM的中间变量也保持Q14仅在最终生成PWM占空比时转换到对应的定时器比较寄存器值。需要考虑的是乘法的位宽扩张两个Q14数相乘会得到Q28需要截回Q14。截断之前一定要加舍入处理最简单的做法是加上0x20001/2的最小量化步长再右移14位这样比直接截断的精度稳定得多。还有一点容易忽略PI积分项在连续几个PWM周期内持续累加即使限幅了积分器内部位宽也要比输出位宽多几位否则会出现“限幅之后内部还在悄悄溢出”的隐性异常。我当时给积分项预留了8位额外扩展位并在限幅时同时钳位积分器内部值彻底解决了积分饱和带来的超调问题。4.2 SVPWM的除法怎么避开经典SVPWM算法需要计算矢量作用时间其中涉及除以直流母线电压的除法。硬件里除法很昂贵业内常见做法是把除法转换成乘法预先计算1/Udc的定点倒数然后在运行时做一次乘法。具体实现时还要注意母线电压可能波动如果1/Udc是固定常数电压跌落时输出的电压调制比会偏高导致电流畸变。我的做法是每个PWM周期采样一次母线电压用查找表方式更新倒数保证在宽电压输入下调制比始终准确。扇区判断逻辑我用的是三路比较器并联几个时钟周期内就能完成整个SVPWM模块只有几十行RTL代码。七段式调制是首选它的开关次数固定谐波集中在载波频率附近方便后续的EMI滤波。五段式虽然能降低开关损耗但谐波含量更大除非温升约束很严否则我不推荐直接上。4.3 从空载到带载的调试顺序FPGA写完之后调试流程和MCU不太一样。之前DSP调试时可以用仿真器在线修改PI参数FPGA要么重新综合要么把PI参数做成寄存器通过串口或JTAG实时修改。我建议从设计之初就把PI的Kp、Ki、限幅值全部做成参数寄存器这样在实验室调试时可以直接在线调整省去反复综合的等待时间。实际调试顺序上先把PWM输出锁定在50%占空比确认逆变器ABC三相输出对称然后开环给一个固定的q轴电压矢量让电机转起来这一步验证坐标变换方向是否正确之后才切入电流闭环先给0电流给定看是否能稳住再逐步加大给定最后才是速度闭环。顺序不能跳每步都涉及不同的延期调试。5. 实测中翻过车的四个细节波形异常和根因排查最后想分享几个实测中真实的翻车经历。这些问题在仿真里很难暴露全是硬件层面的“物理坑”如果直接沿用MCU时代的操作习惯FPGA方案的调试周期可能会被拉得很长。5.1 ADC采样时刻不对电流波形满屏毛刺第一次上电实测时电流波形在过零处有大量尖刺频谱上出现明显的边带噪声。最初的怀疑是互感器精度不够换了好几个传感器还是老样子最后定位到问题出在ADC采样触发时刻上——我在PWM周期的起点采样正好赶上IGBT开关边沿的振铃区。正确做法是把采样触发点安排在PWM波形的中间时刻也就是互补PWM同时为低电平的死区之外、开关状态最稳定的窗口内。FPGA的优势在这里体现得很彻底触发ADC采样的信号可以由PWM模块精确生成任意时钟周期级对齐不需要像MCU那样靠延迟循环去“凑”。调整之后电流波形毛刺立刻下降了一个数量级。5.2 编码器Z信号毛刺导致角度跳变运行过程中偶尔出现电机瞬间顿挫查逻辑分析仪发现Z脉冲信号有毛刺导致角度零点被重新加载速度环反馈值瞬间跳变。这个问题在FPGA里非常容易犯Z信号直接进了异步逻辑没有任何同步处理。修复方式是在编码器模块前端加两级寄存器做时钟域同步再配合边沿检测。同时给Z信号加了几个微秒的消抖窗口把毛刺彻底滤掉。实测故障率直接降到零。5.3 PI积分饱和在限幅前的隐性溢出有个阶段电机在低速带载时出现低频振荡速度波形是三角波而不是平滑波动。用逻辑分析仪抓PI输出发现速度环的积分项已经跑到正常值的几十倍但限幅电路看起来又是正常的。后来查RTL代码才发现积分器的内部累加器是32位有符号数虽然PI输出限幅了但积分器内部的累加值没有同步限幅导致PI输出从正满幅突然跳到负满幅。解决办法是实现“条件积分”逻辑当PI输出处于正限幅时如果误差为正则冻结积分累加不允许它继续增大其他方向同理。这是工业PID控制器常见的抗积分饱和结构很多人写MCU时用过但在FPGA里一忙就容易忽略。加上这个逻辑之后低速振荡彻底消失。5.4 IGBT死区时间带来的电流过零畸变带载波形正弦度变差谐波变大录制和频谱分析都指向一个问题逆变器死区时间引起的电压误差。我用的是2微秒死区在低压大电流工况下这个误差占比不小。最终的处理是对死区效应做了补偿根据电流方向在SVPWM计算出来的占空比上补偿一个与死区时间对应的电压修正量。需要特别注意电流方向检测的准确性——接近过零时方向判断会抖动所以我给电流方向判断加了迟滞防止补偿值在两个方向之间来回切换导致新的振荡。这些细节在仿真模型里基本看不出来因为理想开关模型没有死区、没有采样噪声、没有毛刺。FPGA方案相对MCU方案在硬件层面上更贴近底层这些坑也几乎是必须走一遍的。但从另一个角度看正是因为整个环路都在同一片可编程逻辑里定位和分析这些问题反而比MCU时代更容易——一切信号都在内部有没有毛刺、在哪里发生一抓一个准。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑