
1. 从一次电流环啸叫说起PI参数到底在调什么很多刚接触FOC磁场定向控制的朋友第一次把电机转起来之后最容易被吓到的一幕就是电机没转几圈就开始发出尖锐的啸叫电流波形在示波器上像一团毛线采样电阻上的电压信号抖得根本看不出正弦。这时候你去问有经验的人十有八九会得到一句PI参数没调好。但问题是PI参数到底在调什么为什么同样的电机别人给的参数能跑你抄过来就炸我在做永磁同步电机PMSM电流环调试的这些年里踩过的坑基本都集中在PI参数设计这一块。电流环是FOC三环结构里最内层、带宽最高的那一环它的响应速度直接决定了整个系统的动态性能。速度环和位置环都是建立在电流环已经稳定的前提上如果电流环本身就在振荡外环再怎么调都是白搭。所以这篇文章我想把电流环PI参数设计这件事从头到尾讲透包括它背后的物理意义、离散化实现、参数计算、实测整定以及那些文档里不会写的坑。先明确一下适用对象如果你正在用STM32F103RCT6、DSP28379这类主控做无刷电机或永磁同步电机的FOC驱动已经能跑通SVPWM和转子位置检测但电流环一上电就抖或者响应软绵绵那这篇内容就是写给你的。如果你还在纠结FOC算法原理建议先把坐标变换和SVPWM搞明白再回来看。电流环的本质是把电机定子电流分解成d轴和q轴两个直流量去控制。d轴管励磁q轴管转矩。因为经过Park变换之后交流量变成了直流量理论上用PI控制器就能实现无静差跟踪。但理论上能和实际能之间隔着采样延迟、PWM更新延迟、数字量化误差、死区效应这一堆东西。PI参数设计的核心任务就是在这些非理想因素存在的前提下让电流环既有足够快的响应又不至于因为相位裕度不足而振荡。我见过太多人调PI就是先给个Kp试试不行就加还不行就减这种盲调方式在小功率、低转速场合可能碰巧能跑但一旦换电机、换母线电压、换开关频率参数就全废了。真正靠谱的做法是从被控对象的数学模型出发先算出一组理论参数再在这个基础上做微调。下面我就按这个思路一层一层往下拆。2. 电流环被控对象的数学建模为什么PI参数能算出来2.1 电机定子绕组的等效电路要算PI参数首先得知道你在控制一个什么样的对象。PMSM的定子绕组在d-q坐标系下可以近似看成一个电阻加一个电感的串联回路。d轴和q轴的电压方程在稳态附近可以写成ud R * id Ld * did/dt - ωe * Lq * iq uq R * iq Lq * diq/dt ωe * Ld * id ωe * ψf其中R是定子相电阻Ld和Lq是d轴和q轴电感ωe是电角速度ψf是永磁体磁链。对于表贴式PMSMLd约等于Lq可以统一记作L。交叉耦合项含ωe的那些项在电流环带宽远高于电频率时可以暂时忽略或者通过前馈补偿掉。忽略耦合项之后d轴和q轴的被控对象就变成了一个标准的一阶惯性环节Gp(s) 1 / (R L*s) (1/R) / (1 (L/R)*s)这里L/R就是绕组的电气时间常数记作Te。比如一个典型的云台电机R10欧姆L5mH那Te就是0.5ms。这个时间常数决定了电流环能跑多快——你不可能让电流环的响应速度比绕组自身的时间常数还快很多否则需要的电压会超出母线能提供的范围。2.2 采样与PWM带来的延迟光有电机模型还不够数字控制系统里还有两个绕不开的延迟一个是电流采样到PWM更新之间的计算延迟一个是PWM本身的零阶保持效应。在常见的中心对齐PWM模式下如果采样时刻在PWM计数器过零点那么从采样到新占空比生效平均延迟大约是1.5个PWM周期。这个延迟在频域上表现为一个相位滞后会吃掉电流环的相位裕度。把延迟近似成一阶惯性环节或者纯延迟环节整个被控对象的开环传递函数就变成了Gopen(s) Kp * (1 1/(Ti*s)) * (1/R) / (1 Te*s) * 1/(1 Td*s)其中Td是等效延迟时间通常取1.5倍的PWM周期。Kp是比例增益Ti是积分时间常数。PI控制器的传递函数写成Kp*(1 1/(Ti*s))这是并联形式也有串联形式Kp Ki/s两者可以互相转换Ki Kp/Ti。2.3 用消零极点法算出理论参数既然被控对象有一个极点s -1/Te那最自然的想法就是让PI控制器的零点去抵消这个极点。令Ti Te这样开环传递函数就简化成了Gopen(s) Kp * (1/(R*Te*s)) * 1/(1 Td*s) Kp/(R*Te*s*(1Td*s))这是一个典型的I型系统一个积分环节加一个惯性环节。对于I型系统截止频率ωc和相位裕度的关系很清晰。如果希望相位裕度在45度左右可以令截止频率ωc 1/Td此时Kp的取值满足|Gopen(j*ωc)| 1 Kp / (R*Te*ωc) * 1/sqrt(1(ωc*Td)^2) 1代入ωc 1/Td得到Kp R*Te/Td * sqrt(2)。再结合Ti Te就能算出一组理论参数。举个具体例子R10ΩL5mHTe0.5msPWM频率10kHzTd1.50.1ms0.15ms。那么Ti0.5msKp 100.0005/0.00015*1.414 ≈ 47。这个Kp是连续域的值实际写进代码还要做离散化和标幺化处理。注意这套计算假设了电流采样和PWM更新是同步的且延迟固定。如果你的采样时刻不固定或者用了非中心对齐模式Td要重新估算否则算出来的参数会偏激进。2.4 为什么不能只靠算模型误差的来源理论计算能给你一个很好的起点但直接拿来用往往会偏。原因有几个第一电感L随电流饱和会变化大电流下L可能掉30%以上第二电阻R随温度变化冷态和热态能差一倍第三母线电压波动会影响实际能输出的最大电压进而影响大信号响应第四死区效应和管压降会引入非线性误差。所以理论参数只是起点最终一定要在实物上整定。但有了这个起点你的整定范围会小很多不用从零开始瞎试。3. 离散化实现从连续域公式到DSP里的那几行代码3.1 位置式PI和增量式PI的选择在电机电流环里我强烈建议用位置式PI而不是增量式。原因很简单电流环需要无静差跟踪直流量位置式PI的积分项直接对应输出电压物理意义清晰抗积分饱和也好处理。增量式PI虽然在某些场合能省一次乘法但在电流环这种高动态场合增量式的积分漂移问题更麻烦。位置式PI的离散形式u(k) Kp * e(k) Ki * Ts * sum(e(0)...e(k))其中Ts是控制周期e(k)是当前电流误差。实际写代码时积分项用累加器实现// 电流环PI控制器位置式 typedef struct { float Kp; float Ki; float Ts; float integral; float out_max; float out_min; } PI_Controller; float PI_Update(PI_Controller *pi, float error) { float p_term pi-Kp * error; pi-integral pi-Ki * pi-Ts * error; // 抗积分饱和输出限幅时停止积分 float out p_term pi-integral; if (out pi-out_max) { out pi-out_max; pi-integral - pi-Ki * pi-Ts * error; // 回退积分 } else if (out pi-out_min) { out pi-out_min; pi-integral - pi-Ki * pi-Ts * error; } return out; }这段代码里有两个关键点一是积分项在输出饱和时要回退否则积分器会windup导致退饱和时响应迟钝二是Ki Kp/Ti所以如果你先算出了Kp和TiKi就自然确定了。3.2 标幺化为什么你的Kp看起来和别人差几百倍很多新手会困惑为什么网上有人给的Kp是0.5有人给的是50还有人给的是5000这大概率是标幺化基准不同。电流环的PI输出是电压输入是电流误差。如果你的电流采样经过归一化变成了-1到1之间的小数电压输出也归一化成-1到1那Kp的量纲就是归一化电压/归一化电流数值会很小。如果你用的是实际安培和实际伏特Kp就是伏特/安培数值会大很多。我个人的习惯是电流用安培电压用伏特PI输出直接是Vd和Vq的伏特值然后再除以母线电压的一半做归一化去生成占空比。这样Kp的物理意义就是每安培误差对应多少伏特输出量纲清晰换电机时也好迁移。比如前面算的Kp47意思就是电流差1A比例项输出47V对于母线电压24V的系统来说这个增益其实偏大实际整定时可能要降到10到20之间。3.3 控制周期Ts的选择Ts就是电流环的执行周期通常等于PWM频率。比如PWM 10kHzTs就是100微秒。Ts越小延迟越小能跑的带宽越高但对CPU算力要求也越高。STM32F103RCT6跑FOC主频72MHz10kHz电流环加SVPWM基本能跑满再高就吃力了。DSP28379这种带浮点单元和CLA的芯片可以轻松跑到20kHz甚至更高。Ts的选择还要考虑采样时机。我一般用PWM计数器下溢中断触发ADC采样然后在同一个中断里完成Clarke、Park、PI、反Park、SVPWM全部计算下一个PWM周期生效。这样延迟就是1.5个Ts和前面建模一致。3.4 积分限幅和输出限幅的配合输出限幅是必须的因为母线电压有限Vd和Vq的合成矢量幅值不能超过母线电压除以根号3SVPWM线性调制区。但积分限幅和输出限幅要配合好如果只限输出不限积分积分器会一直累加到很大退饱和时会有明显的过冲。我通常把积分限幅设成输出限幅的0.8倍左右给比例项留一点空间。提示在启动瞬间电流误差可能很大积分器会快速饱和。可以在启动前几个周期先禁用积分等电流接近参考值再使能这样能避免启动过流。4. 实测整定从理论值到能跑的参数4.1 整定前的准备工作在动PI参数之前有几件事必须先确认否则你调的不是PI是在调一堆别的问题。第一电流采样要准。用示波器看采样电阻上的波形确认运放输出没有偏置、没有振荡、量程合适。第二转子位置要准。如果编码器或霍尔的角度有偏差Park变换出来的id和iq会串电流环永远调不好。第三SVPWM输出要正常。开环给一个固定电压矢量看三相电流是否对称。我遇到过好几次有人抱怨电流环振荡最后发现是采样电阻的运放带宽不够电流波形被滤得面目全非PI看到的是失真的反馈当然调不好。所以整定前先用示波器把信号链看一遍能省掉后面大量返工。4.2 先调Kp再调Ki整定的顺序很重要。我的做法是先把Ki设为0只留Kp然后给q轴一个阶跃电流参考比如从0跳到额定电流的20%看电流响应。逐步增大Kp直到响应开始出现明显超调或者振荡然后回退到振荡点的60%到70%。这时候系统是纯比例控制会有稳态误差但响应形状已经能看出来了。然后加入Ki从小到大加。Ki的作用是消除稳态误差但加太大会引入低频振荡。观察阶跃响应的尾部如果电流在参考值附近缓慢摆动说明Ki偏大如果到达参考值太慢说明Ki偏小。理想情况下电流应该在几个控制周期内快速上升然后平稳地贴在参考值上没有明显过冲和振荡。4.3 用示波器看什么调PI的时候示波器是最好的朋友。我一般同时看三路信号q轴电流参考、q轴电流反馈、q轴电压输出。通过观察这三者的关系能快速判断问题所在。现象可能原因调整方向电流反馈高频抖动Kp过大或采样噪声大降Kp检查采样滤波电流上升慢无超调Kp过小适当加Kp电流到达参考后缓慢爬升Ki过小加Ki电流低频摆动Ki过大降Ki电流超调后长时间恢复积分饱和检查抗饱和逻辑大电流时振荡小电流正常电感饱和降低大电流下的Kp或做增益调度这张表是我自己调试时总结的基本覆盖了八成以上的常见问题。但要注意现象和原因不是一一对应的有时候多个问题叠加需要逐项排除。4.4 带宽和相位裕度的实测验证理论算出来的截止频率实际能不能达到要用频率响应测试来验证。方法很简单给q轴电流参考叠加一个小幅正弦扰动频率从10Hz扫到1kHz记录反馈幅值和相位画出伯德图。截止频率处增益为0dB相位裕度是相位曲线在截止频率处距离-180度的差值。我一般希望相位裕度在45度到60度之间低于45度容易振荡高于60度响应偏慢。如果没有频率响应分析仪也可以用阶跃响应粗略估计。阶跃响应的上升时间tr和带宽的关系大约是BW ≈ 0.35/tr。比如上升时间1ms带宽大约350Hz。这个方法不精确但够用。4.5 不同电机参数下的迁移换电机的时候PI参数不能直接抄。但如果你是按消零极点法算的迁移就有章可循。新电机的R和L变了Te变了Ti跟着变Kp按R*Te/Td的比例变。比如新电机电感是原来的两倍Te翻倍Ti翻倍Kp也大约翻倍。实际再微调一下就行。这比盲目试凑高效得多。5. 那些文档里不会写的坑5.1 死区补偿没做好PI怎么调都白搭死区是为了防止上下桥臂直通但死区会导致输出电压和占空比不成正比尤其在电流过零附近波形会畸变。这种畸变对PI来说就是扰动PI会试图去补偿但补偿的结果是电流波形出现平顶或者毛刺。如果死区时间设得太大比如超过1微秒而PWM周期又短畸变会非常明显。我的经验是死区时间在保证安全的前提下尽量小同时加上死区补偿。补偿的方法是根据电流方向给占空比加一个偏置。补偿量要实测不同管子和驱动电路不一样。补偿做好了电流波形会干净很多PI参数也能调得更激进。5.2 电流采样时刻和PWM更新的相位关系前面提到采样到更新的延迟是1.5个Ts但这个前提是采样时刻在PWM计数器过零点。如果你用的是其他触发方式比如计数器峰值触发延迟会变成0.5个Ts这时候理论参数要重新算。更麻烦的是如果采样时刻和PWM更新不同步延迟会随占空比变化导致PI在不同工作点表现不一致。我建议统一用下溢中断触发采样这样延迟固定模型简单。有些芯片支持PWM和ADC硬件联动能进一步减小抖动有条件的话用上。5.3 弱磁和MTPA对电流环的影响当电机跑到基速以上需要弱磁d轴电流不再为零而是负值。这时候d轴和q轴的交叉耦合不能忽略了如果PI里没有解耦前馈d轴和q轴会互相干扰电流跟踪变差。MTPA控制也是类似id和iq有特定关系电流环要同时跟踪两个参考值。解决办法是加前馈解耦项在d轴输出上减去ωeLqiq在q轴输出上加上ωeLdid加ωe*ψf。这样PI只需要处理误差耦合项由前馈直接补偿。加了前馈之后PI参数可以按单轴模型来设计简单很多。5.4 母线电压波动和过调制电池供电的系统母线电压会随电量下降。如果PI参数是按满电电压整定的电压降下来之后同样的Kp可能导致输出饱和动态变差。可以在PI输出限幅里根据实际母线电压动态调整或者做增益调度。过调制区更要小心SVPWM进入过调制后输出电压和占空比严重非线性PI容易失控。一般建议留10%到15%的电压裕量不要跑到过调制区。5.5 编码器延迟和角度补偿高转速下从编码器读数到Park变换用的角度中间有计算延迟。如果转速很高这个延迟对应的角度误差不能忽略。比如10kHz控制周期1000Hz电频率一个周期就是36度电角度延迟1.5个周期就是54度这足以让电流环完全失控。解决办法是用转速乘以延迟时间做角度前馈补偿或者提高控制频率。6. 一套可复现的电流环PI整定流程把前面所有内容串起来我给出一套我自己常用的整定流程你可以直接照着做。第一步确认硬件信号链正常。示波器看三相电流采样确认无偏置、无振荡、量程合适。确认编码器角度正确可以开环拖动看角度变化是否线性。第二步测量电机参数。R用万用表测相电阻L用电感表测或者用阶跃电压法测电流上升斜率。记录母线电压和PWM频率。第三步计算理论参数。Te L/RTd 1.5/PWM频率Ti TeKp RTe/Tdsqrt(2)。把Kp和Ki Kp/Ti写进代码注意标幺化。第四步空载整定。Ki先设0给q轴阶跃参考从小Kp开始加观察电流响应。找到临界振荡点回退到60%。然后加Ki观察稳态误差和低频振荡找到合适的值。第五步加载验证。加上负载重复阶跃测试观察大电流下的响应。如果大电流振荡适当降Kp或做增益调度。第六步频率响应测试。扫频验证带宽和相位裕度确保在45度以上。第七步动态工况测试。让电机正反转、加减速观察电流跟踪是否平稳有没有过流或失步。这套流程走下来基本能覆盖大部分应用场景。当然具体参数还要根据实际波形微调但大方向不会错。注意整定过程中如果出现持续过流或电机异响立即断电检查不要硬调。很多时候问题不在PI而在硬件或角度。7. 写在最后的一点个人体会调电流环PI这件事最忌讳的就是把它当成一个纯调参问题。参数只是表象背后是模型、延迟、非线性、采样质量这一整套东西。我刚开始做FOC的时候也曾经对着一个振荡的电流环调了整整两天最后发现是采样电阻的走线太长引入了开关噪声。从那以后我养成了一个习惯每次调PI之前先花半小时把信号链和角度确认一遍这半小时能省掉后面几天的返工。另外理论计算真的很有用。很多人觉得算出来的不准不如直接试但我的经验是算出来的参数至少能让你在正确的数量级上开始试而不是从0.001试到10000。尤其是换电机的时候按比例迁移比重新盲调快得多。最后说一句关于工具的话。如果你用的是STM32F103RCT6这类没有浮点单元的芯片PI计算尽量用定点或者Q格式注意溢出和精度。如果用DSP28379或者带FPU的M4/M7直接浮点就行代码清晰调试也方便。工具选对了很多坑自然就少了。