FOC电机控制实战:从坐标变换到SVPWM与电流环调参

发布时间:2026/10/5 1:31:16
FOC电机控制实战:从坐标变换到SVPWM与电流环调参 第一次把FOC代码烧进自己的驱动板按下启动键那几秒我的手心全是汗。母线电容“啪”地一声鼓包IGBT模块冒出一缕白烟整套板子当场报废。那时候我刚从六步换相方波驱动转到永磁同步电机的FOC磁场定向控制以为只要移植开源代码、配好PID就能让电机安静平滑地转起来结果第一课是用元器件冒烟换来的FOC不是套一个PI环就行它的坐标系变换、采样时序、转子角度任何一个环节出问题最后都会变成硬件上的灾难。这两年我把FOC原理反复啃了几遍也帮几个朋友把出问题的板子救回来过。这篇文章就用大白话把FOC的原理、坐标变换、电流环、SVPWM这些讲清楚尽量不堆公式而是讲明白“它在干什么、为什么这么干”。适合刚接触FOC的嵌入式工程师、备赛学生以及所有被“磁场定向控制”这个名字吓住的人。看完你至少能回答三个问题为什么FOC要把三相电流变成id和iqSVPWM到底在算什么东西电机能转但你调不稳问题最可能出在哪一环1. 为什么说FOC是“把交流电机当直流电机用”1.1 直流电机的控制为什么那么省心先想一个很简单的例子你手上有个普通的有刷直流电机两根线给电压就转反接就反转控制逻辑几乎是个人都会。原因是直流电机内部有碳刷和换向器它们把外部输入的直流电流自动切到转子绕组里正确的方向。不管你转子转到哪个角度电枢电流产生的磁场和定子磁场的夹角基本始终保持在90度附近而这个90度正是产生最大转矩的角度。所以直流电机有个特别漂亮的性质转矩和电流近似成正比T Kt × I控制电流就等于控制转矩。你不需要知道转子现在转到哪不用管磁场在哪个方向给多大电流就是多大转矩简单粗暴。这也是为什么老派伺服系统很多都直接用直流电机控制回路里一个PI环就够了。但直流电机的缺点也很明显碳刷会磨损、换向器会打火、转速做不高、功率做不大。工业上要长期跑、高速跑、大功率跑绕不开无刷结构的电机。而无刷电机没有换向器天然就需要电力电子装置配合控制算法来干“换向”这个活。1.2 永磁同步电机麻烦在哪磁场一直在转我们这篇文章主角是永磁同步电机PMSM转子是永磁体定子上有三相绕组相位差120度。想让转子连续转起来得让定子绕组产生一个旋转磁场拉着转子磁钢同步跑。旋转磁场由三相电流合成合成磁场矢量的方向取决于三相电流的瞬时比例而三相电流本身是正弦变化的也就是说磁场矢量不是定着的而是一直在转。问题就在这直流电机的磁场方向和电流方向天然保持90度而PMSM里定子合成磁场方向和转子磁钢方向的夹角是随转子位置实时变化的转矩公式里带一个sinθ。你想让电机一直输出最大转矩就得让合成磁场和转子磁场一直保持垂直但转子在转磁场也在转你得每秒成百上千次地算出当前到底该给三相各通多少电流才能保证那个夹角始终是90度。如果你直接用三相正弦电流去驱动电机在某一瞬间可能夹角恰好合适下一瞬间夹角就偏了转矩跟着剧烈波动严重时甚至会产生制动力矩电机嗡嗡响、发热、效率极低。六步换相法方波驱动就是这个问题的一个妥协方案它借助霍尔传感器知道转子大概在哪个60度区间然后用六个开关状态阶梯式地逼近旋转磁场。它能让电机转起来但转矩脉动大低速时噪音大控制精度也上不去。1.3 FOC的底层思路换个坐标系看世界FOC的解法非常巧妙既然三相坐标系里的电流都是旋转的交流量那干脆“跳到转子上去看”把坐标系固定到转子上。站在转子坐标系里原本旋转的磁场分量全部变静止三个交流量变成两个直流量此时再用传统的PI控制就能精确控制。具体做法是分两步坐标变换第一步叫Clarke变换把三相静止坐标系的电流变成两相静止坐标系αβ轴第二步叫Park变换把两相静止坐标系旋转到转子坐标系dq轴旋转角度就是当前的转子电角度这个角度来自编码器、霍尔或者无感观测器。换了参考系之后d轴和转子的磁极方向重合q轴正好超前d轴90度。因为转子磁极方向和d轴是重合的所以控制d轴电流等于控制励磁磁场控制q轴电流等于控制力矩。对于表贴式永磁同步电机d轴和q轴电感基本相等转矩就一句话T 1.5 × p × ψf × iq和直流电机的转矩公式长得一模一样。这就是“FOC把交流电机当直流电机用”说法的来源。2. Clarke变换与Park变换两把降维的钥匙2.1 Clarke变换三相不平等的电流其实可以合并成两个量先别被变换矩阵吓住Clarke变换做的事用一句话说就是把一个时刻的三相电流值转换成两个正交分量iα和iβ合成起来就是同一时刻的电流空间矢量。三相绕组在空间里差120度你把ia、ib、ic当成三个方向的向量用平行四边形法则合成等价于用两个互相垂直的轴来表示。如果电机是星形连接且没有中线三相电流满足ia ib ic 0只用采两相就能算第三相这也是驱动板上常见两路电流采样就能跑FOC的原因。变换公式有多种系数版本最常见的是等幅值变换系数2/3体现为// Clarke变换三相电流 - 两相静止坐标 float iAlpha ia; float iBeta (1.0f / SQRT3) * (ib - ic);注意这里省去了3/2系数因为等幅值变换和等功率变换在工程中都能用但等幅值变换配合SVPWM调制度计算更直观大多数开源FOC代码都采用这个约定。2.2 Park变换跳上转子这块“旋转木马”Clarke变换得到iα和iβ依然是交流量转子每转一圈它们也正弦变化一个完整周期。这时做Park变换把αβ坐标系旋转到电角度θ所在的dq坐标系。数学上一看就是旋转矩阵// Park变换静止坐标 - 旋转坐标 float id iAlpha * cos(theta) iBeta * sin(theta); float iq -iAlpha * sin(theta) iBeta * cos(theta);这里的θ必须是用电角度机械角度乘上极对数p。旋转之后如果θ捕捉准确id和iq就变成稳定的直流量iq对应转矩id对应励磁。一个很形象的类比是旋转木马你站在地面上看木马它一直在绕圈位置每时每刻都在变你跳上旋转木马跟着它一起转眼前的木马就是静止的。Park变换就是那个起跳动作。2.3 变换之后d轴和q轴各算什么d轴和转子永磁体磁极方向重合所以id是“励磁电流”表贴式电机里它不产生有效转矩只会增加铜损所以常规控制都把id的目标值默认设成0让电流全部花在产生转矩的iq上。q轴超前d轴90度控制iq最直接地影响输出转矩。你控制电流环时实际就是在调vd和vq两个电压指令经过逆Park变换和SVPWM生成三相PWM占空比。但注意内置式永磁同步电机IPM的情况略有不同Ld小于Lq公式里多出磁阻转矩项1.5 × p × (Ld - Lq) × id × iq这时会让id走一些负值来利用磁阻转矩提高效率这就是MTPA最大转矩电流比控制的核心思路。对初学者先别管MTPA先把id0跑稳再说。2.4 能直接用的变换代码与常见错误实际工程里在中断里就是反复执行“采样电流→Clarke→Park→PI→逆Park→SVPWM→更新PWM”这个循环。逆Park变换和正变换方向相反// 逆Park变换dq电压 - αβ电压 float vAlpha vd * cos(theta) - vq * sin(theta); float vBeta vd * sin(theta) vq * cos(theta);常见错误有几个。第一θ用的是弧度还是角度很多新手转换时忘了统一单位导致电流反馈乱跳。第二编码器计数方向反了θ在递减此时dq轴参考系方向反了id和iq会完全错乱电机剧烈抖动。第三极对数p忘记乘把机械角度直接当电角度用反馈电流出现周期性振荡。第四浮点三角函数的调用频率要跟控制周期匹配曾经见过有人把三角函数写进中断里每次调用10kHz中断里跑高精度cos计算导致中断时间超了控制周期乱掉。3. 电流环与PI整定电机扭矩质量的决定性环节3.1 电流环是在环什么id和iq的分工整个FOC系统是三环嵌套结构电流环最内层速度环包着电流环位置环再包着速度环。最内层的电流环是整个系统的基础因为电机输出转矩和电流直接相关电流没控制好外面两层做得再花哨也没用。电流环的任务是让id和iq的实际值快速准确地跟随两个参考值。id参考值默认设0它天生就爱捣乱所以你需要一个PI控制器把它“摁”在0上iq参考值来自速度环输出它决定转矩。两个PI控制器分别称之为d轴PI和q轴PI它们的输出是vd和vq电压指令再送给逆Park变换。为什么电流环必须用PI因为电流环被控对象是电机的定子绕组本质是一个电阻加电感的RL回路可以用PI控制器把它校正成一阶惯性系统实现无静差跟踪。P项负责快速响应I项负责消除稳态误差就这么简单。3.2 电流采样时间点比采样电阻精度更关键硬件上最常见的电流采样方案是三个采样电阻配合运放或者两相采样、母线采样。很多新手把注意力全放在采样电阻精度上实际上采样瞬间的选择才最要命。FOC用的是PWM调制同一个桥臂的上管和下管在一个周期内交替导通电流不是一直流经采样电阻的。只有在特定时间窗口内PWM下桥臂导通时电流才会完整流过下管和采样电阻此时采样才能采到真实的相电流。这个窗口通常选PWM计数器在中心位置也就是三角载波的顶点或底点此时所有开关状态处于最对称的位置采样值最稳。工程上还要避开的坑是死区效应上下管切换瞬间有一段死区时间此时桥臂输出处于高阻态电流可能流经续流二极管采样电阻上的电压会有毛刺。所以ADC触发时刻要稍微延后于死区结束留出足够的建立时间。现实中很多“电流波形毛刺多”的问题根源不是运放不好而是采样时刻踩在了死区或开关振荡区间。3.3 PI参数整定的工程套路先从理论推一手。电机定子绕组的电气方程可以简化成一阶RL模型电流环PI参数和电流环希望达到的带宽ωc之间存在近似关系Kp L × ωcKi R × ωc。这里的L是电枢电感R是相电阻ωc是目标带宽的弧度值。用这个方法可以快速得到一组初值再细调。举个例子一个表贴式电机相电感L0.5mH相电阻R0.3Ω开关频率和电流环频率都是20kHz目标电流环带宽fc2kHz对应ωc2π×2000≈12566rad/s。那么在连续域理想情况下Kp≈0.0005×12566≈6.3Ki≈0.3×12566≈3770。注意这是连续域值离散化之后还要乘或换算成与采样周期匹配的形式各家代码的PI结构并联式还是串联式也不一样所以理论值只能当起点。真正调试时我习惯的做法是先只给q轴一个很小的固定电流参考值比如额定电流的5%到10%然后Kp从0开始慢慢加观察iq反馈是否能跟上。Kp太小见反应慢Kp加到反馈开始抖动或者有高频啸叫时退回一点。Ki从0开始加观察稳态误差是否被消除大概取Kp的1/10到1/5再微调。表贴式电机d轴和q轴的L、R基本相同所以两个PI参数可以一致起步带弱磁的IPM则要分开调。3.4 一个带参数的具体算例再具体一点。假设目标电流环带宽是1kHz而不是2kHz因为有些项目IGBT开关频率不高或者散热限制不敢把带宽做太高。ωc2π×1000≈6283rad/sKp0.0005×6283≈3.1Ki0.3×6283≈1885。如果你上来就把Kp调到6会发现电流反馈过冲明显甚至带一点振荡原因就是带宽超过了你硬件能承受的范围。速度环的带宽按经验取电流环的1/10到1/5也就是100到200Hz左右。速度环PI的初始值可以让Kp小一些Ki更小因为速度环被控对象包含机械转动惯量响应慢。速度环调太猛会导致电流环参考值抖动电机嗡嗡响。调试过程中强烈建议把id和iq的实际值通过DAC输出或者虚拟示波器显示出来。我在实际项目里就用一个STM32开发板的DAC引脚把iq映射成电压接到了示波器上。这样你能直观看到电流环的阶跃响应、PI振荡、超调等所有细节比看串口打印数据直观得多。4. SVPWM调制从dq电压指令到三相PWM占空比4.1 先说说SPWM为什么不够用逆Park变换输出的是两相静止坐标系里的电压指令vα和vβ接下来要把它变成三相PWM占空比。最简单的思路是SPWM用正弦波和三角载波比较产生三路PWM三相相位各差120度。但SPWM有个明显短板母线电压利用率低。正弦相电压峰值最大只能做到母线电压的一半折算到线电压就是0.866倍的母线电压这意味着电机的最高转速和最大输出功率都被限制住了。SVPWM不用三相分别调制而是从“让合成电压矢量逼近目标矢量”的角度来做。它充分利用了六个非零开关矢量和两个零矢量让输出电压矢量的最大幅值可以达到Udc/√3比SPWM高出约15.5%。这个差距在电池供电的机器人、电动车里太明显了所以基本上现在所有正经FOC方案都走SVPWM。4.2 八个开关状态、六个扇区和一个圆三相桥臂的上下管组合共有八种状态。上管导通记1下管导通记0A、B、C三相组合出从000到111共八种编码。其中000和111两种状态下三相输出都是同时接母线或同时接地合成电压矢量为零称为零矢量。其余六个非零矢量100、110、010、011、001、101在空间上把电压平面均分成六个60度的扇区。SVPWM的目标是合成任意方向和幅值的电压矢量。一个PWM周期内用这个矢量所在扇区的两条边界矢量各作用一段时间再填上零矢量把剩余时间补满只要PWM频率足够高电机绕组上的等效电压就是这个目标矢量的时间平均值。4.3 每周期的矢量合成伏秒平衡与零矢量比如目标矢量落在第一扇区即vα大于0且vβ大于0且角度在0到60度之间那么相邻的两个基本矢量就是100和110。如果让100作用T1时间110作用T2时间剩下时间T0由两个零矢量平分满足T1 T2 T0 T就能用伏秒平衡公式保证合成的平均电压等于目标矢量。零矢量的分配有讲究。七段式SVPWM在一个周期里把零矢量V0和V7各分配一半插在序列开头、中间和结尾这样做出的PWM波形对称谐波小电流采样点也落在周期中心。典型的第一扇区输出序列是000、100、110、111、110、100、000对应的开关次数最少开关损耗也低。4.4 代码思路扇区判断与七段式输出实际代码分三步走。第一步判断vα和vβ落在哪个扇区工程上常用三值法判断根据vβ、√3/2vα-1/2vβ、-√3/2vα-1/2vβ的正负组合查表。第二步计算相邻两个基本矢量的作用时间T1和T2公式里会出现母线电压的倒数所以母线电压的采样值不能太脏。第三步计算三相占空比// 第一扇区示例 float T1 vαβ合成的相邻矢量作用时间; float T2 第二个相邻矢量作用时间; float T0 T - T1 - T2; float Ta T0 / 4.0f; // 000阶段 float Tb Ta T1 / 2.0f; // 100阶段 float Tc Tb T2 / 2.0f; // 110阶段 // 111阶段对称无需再算之后把Ta、Tb、Tc根据扇区映射到A、B、C三相对应的比较寄存器。写代码时最容易错的地方就是扇区判断和占空比映射表对不上导致转矩方向反了或者电流波形完全畸形。建议先在仿真或者带灯泡的假负载上验证SVPWM波形再上电机。5. 转子位置从哪来有传感器与无感FOC的现实差距5.1 编码器方案零位标定是第一个大坑带编码器的FOC理论上角度是直接读出来的似乎没难度但真正上手会发现第一大坑是编码器机械安装偏角。编码器零位和电机转子磁极零位通常不是对齐的如果拿编码器原始读数直接当电角度用id和iq轴的方向就是错的电流环会乱成一片。常规标定方法很朴素给一个固定的电压矢量让转子转到和A相磁链对齐的位置然后读编码器当前值把这个值记为offset。之后电角度就等于编码器读数减去offset再乘以极对数方向因子。实际项目里我会让电机在上电时自己走一步这个“定位”动作记录offset省去手动对齐的麻烦。方向问题也要小心。编码器正转时计数值递增电角度也跟着加一旦电机接线或者安装方向不同计数值递减你就要对θ取反。很多“电机转了但电流环发散”的bug都出在这里。5.2 霍尔方案60度分辨率怎么补出连续角度霍尔传感器只有六个换相点天然的电气分辨率只有60度。直接拿霍尔值当电角度用显然不够会导致电流突变、转矩脉动。工程上常见的做法是分两段在霍尔边沿之间假设转速恒定或者加速度恒定用时间积分插值出一个近似的转子角度霍尔换相处强制更新角度。这种方案低速时有误差但胜在成本低、传感器抗振动。还有一种做法是霍尔信号配合滑模观测器或者龙伯格观测器用霍尔信号做约束条件得到连续高分辨率的角度估计。如果只是入门学习先把插值方案跑通就够了。5.3 无感FOC的启动流程与切换时刻无感FOC是另一个大话题这里只讲清楚启动链路。电机静止时反电动势为零任何基于反电动势的观测器都没有有效输入所以无感FOC必须经过“预定位→开环强拖→切换闭环”三个过程。预定位就是上面说的给一个固定的电压矢量把转子拉到已知位置。开环强拖是这个阶段最容易失败的电流小拖不动电流大会把转子拖飞或者发热。一般是用I/f开环启动电流按斜坡增大频率按斜坡上升让转子跟上一个虚拟旋转坐标系。等转速升到反电动势足够大的切换点比如额定转速的10%到20%观测器开始工作把角度切换成闭环估算角度电流环也切入闭环。切换瞬间角度差必须足够小否则转子会剧烈抖动甚至失步。初始位置检测是另一个深坑。对于表贴式电机有高频注入法、脉冲电压矢量法等。高频注入利用电机凸极效应或者磁饱和特性在d轴上注入高频电压信号从高频电流响应里解出转子位置。这个算法在零速低速有效但噪声大、整定复杂新手不建议一上来就折腾。5.4 一个容易被忽略的同步问题角度和电流要一起采跑通FOC之后你会发现角度和电流的采样时刻如果不一致也会引入误差。因为电流环里的Park变换需要用到电角度如果电流在t1时刻采角度在t2时刻才读中间转子转了一点角度dq轴系的参照就不对了。尤其在高转速下几个微秒的时间差对应的角度差就足够让整个电流环性能退化。所以工程上一般都用PWM中心中断作为控制节拍在这个中断里同时触发ADC采样和读取编码器计数保证两者是同一个时刻的快照。这也解释了为什么很多高性能FOC代码对中断响应时间抠得那么死——任何阶段性的延迟都会等效成角度误差。6. 调不出来分享我踩过的坑和排查顺序6.1 现象一上电就过流保护别急着怀疑芯片一次我把新板子接上母线还没给任何电流指令驱动板直接过流报警。第一反应怀疑采样运放坏了后来一步一步排查发现是PWM互补输出的极性配反了上下管同时导通母线直通短路。查看芯片手册发现驱动器的输入极性是高有效还是低有效和MCU定时器输出的极性没配对。上电就过流排查链路应该是先断开功率级只测PWM波形确认互补信号没有同时为高再测死区时间死区太短或者没有IGBT和MOS在开关瞬间直通母线瞬间短路最后查电流采样零漂运放输出有直流偏置软件里又没做零漂校准一上电就误判过流。顺序很重要先把功率部分排除掉再去动软件采样逻辑。6.2 现象二电机能转但力矩忽大忽小多半是角度线圈的问题“能转”不代表FOC跑对了。我遇到过一次电机空转看起来正常但用手一捏轴感觉转矩一波一波地跳。查了电流环、电压环都没问题最后发现是编码器A/B相接反了软件里电角度方向反了dq轴解算出来的不是真正的磁场方向只是“碰巧”还能维持电机转。排查方法很简单给一个固定iq指令同时把id反馈打印出来。id的零均值控制做得好的话硬件虚位、方向错误、offset不准这些问题都会反映在id的波动上。如果iq固定但id均值明显不是0或者id波形有规律地震荡优先查角度方向、相序和offset而不是先调PI参数。6.3 现象三一带载电流就乱先查采样窗口再看带宽空转一切正常一带负载电流波形就乱成麻花这是调FOC很折磨人的一个问题。常见原因有两个一是电流采样落在了死区或开关噪声区空转时电流小还不明显带载时电流大、续流时间长、噪声干扰大采样值就被污染了二是电流环带宽太低负载扰动来了跟不上。我的处理经验是先把示波器探头接到电流采样运放输出端观察在PWM触发信号附近波形是否干净。如果采样点附近有暴振毛刺就把ADC触发时刻往死区后移如果波形干净把电流环Kp往上加一两倍看看反馈跟随是否变好。多数情况下是采样窗口问题。6.4 我现在带人调FOC的固定顺序踩过几次坑之后我现在不管项目多急都是按这个顺序来先把开环电流建立起来确认电流环本身工作正常再用编码器把角度闭环跑起来然后是速度和位置环最后才碰无感。每一步都在确认上一层的正确性之后再进行下一层这样排查问题时的范围就被严格控制住了。调电流环时只调电流环不要同时动速度环调速度环时抓住电流环的响应曲线别盯着速度波动发呆。FOC本身是个嵌套系统每一层都足够复杂跳步调试只会让问题像滚雪球一样叠加。最后再分享一个小技巧所有PI参数、变换公式、采样触发配置第一次跑通时全部写在注释和表格里每改一个参数记录对应的波形现象。一圈下来你会发现那些看起来很玄的“手感”其实全都有迹可循。