ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

BP神经网络在线自整定PID的PMSM转速环控制仿真

BP神经网络在线自整定PID的PMSM转速环控制仿真

做仿真课题的人多少都有这种体会:一套PMSM双闭环矢量控制模型,电流环调好之后基本不用再操心,真正反复折磨你的是转速环那一对PI参数。给定幅度一大就超调,负载一变就掉速,想把稳态精度和动态响应同时兼顾,结果往往是两头都差一口气。我刚开始做永磁同步电机矢量控制仿真时也是这样,后来把BP神经网络在线自整定PID(简称BP-PID)用到转速环上,才把这个问题理顺。

这个课题说穿了就是一件事:让BP神经网络在控制过程中实时计算并调整PID的三个参数,替代人工整定,然后整体嵌入Simulink里的永磁同步电机双闭环矢量控制模型,通过仿真验证它在启动、负载突变、参数变化等场景下比固定PI强在哪里。适合正在做电机控制毕业设计、或者想把手动调参的传统FOC框架升级成智能控制方案的同学参考。这篇文章我从原理、建模、代码实现到结果对比,把完整思路和踩过的坑一次性讲清楚。

1. 固定PI在转速环上的三个“吃瘪”场景:为什么非要用神经网络换掉它

1.1 双闭环框架里,转速环的实际地位

先梳理一下PMSM矢量控制的整体逻辑。永磁同步电机的定子三相电流经过Clarke变换和Park变换之后,变成d轴分量和q轴分量,采用id=0控制策略,电磁转矩就近似与iq成正比,电机在控制上看起来像一台直流电机。控制结构分内外两层:内环是两个电流环,把id、iq快速跟踪到指令值;外环是转速环,根据转速误差给出iq指令,也就是转矩需求。

这里有个容易被忽略的层级关系:转速环是决策者,电流环是执行者。电流环带宽通常设计为转速环的5到10倍,所以电流环用固定PI就能扛住,而转速环面对的是机电大惯性、负载扰动和参数漂移,问题恰好集中在它身上。这就是为什么很多文章都拿转速环开刀,而不是去动电流环。

1.2 场景一:转速给定突变时,“快”和“稳”打架

固定PI参数的整定通常是在某个工作点附近做的。你把参数按照500rpm阶跃调得刚刚好,再给一个1000rpm的大阶跃,超调往往立刻变大。反过来,如果想减小超调,就得把比例系数降下来、积分作用弱一点,结果小阶跃的响应又变得拖泥带水。

原因在于PMSM的转速环本质上是一个非线性对象。电磁转矩Te=1.5pnψf·iq,iq_ref由转速环给出,而转速反馈又反过来影响转矩输出,这个闭环内部存在多个工作点。不同转速、不同负载下,最优的PI参数根本不是一个固定值。固定PI能做的只是取一个“折中值”,保证所有工况都不太差,但也不可能在某个工况下做到最好。

1.3 场景二:突加负载后的那段时间最难熬

转速环抗负载扰动主要靠积分项。固定PI的积分速度只有一个固定节奏:积分慢了,负载突变后转速跌下去要很久才能拉回来;积分快了,又会在恢复过程中引起转速振荡。我在仿真里经常看到这种情况——突加额定负载后转速跌了五六十转,然后绕着给定值振荡好几圈才稳定下来。这种振荡在电机实际运行中就是明显的“抖动”,对机械负载非常不友好。

BP-PID的价值在于它可以“看情况”调整积分作用:误差大的时候Kp大一点、Ki补得快一点,转速刚回到给定附近时又自动把参数收回,防止冲过头。这等于给PID装了一个会变参数的“自动调参器”,而这个自动调参器随着控制过程不断在线学习,不需要人提前设计好规则。

1.4 场景三:电机参数不是恒定不变的

永磁同步电机运行一段时间后,定子电阻会随温度升高而变化,永磁磁链也会受温度影响,转动惯量如果拖动不同负载还会变化。固定PI建立在电机参数的某个样本点上,参数一漂移,控制品质就会偏离设计值。这也是工业现场经常出现“仿真调得好、现场用不灵”的一个原因。神经网络在线自整定的思路恰好能应对这种参数慢变:它不依赖于精确的电机模型,只靠转速误差的反馈来修正自己的输出。

2. BP-PID控制器的内部逻辑:不是离线训练好的模型,而是在线换参数的PID

2.1 整体架构:在原PID外面套一个参数生成网络

先澄清一个常见误解:BP-PID并不是用大量数据离线训练一个端到端控制器,它是把BP神经网络和传统PID“并联”起来——神经网络每个控制周期都根据当前误差状态算出一组Kp、Ki、Kd,然后把它们交给底层的增量式PID去计算控制量。控制量输出之后,再用转速误差去修正神经网络权值。整个过程是边控制边学习,有点像人开车时根据方向盘反馈不断微调自己的操作力度。

增量式PID的公式是:

Δu(k) = Kp·[e(k) - e(k-1)] + Ki·e(k) + Kd·[e(k) - 2e(k-1) + e(k-2)]

u(k) = u(k-1) + Δu(k)

这里的u对应转速环的输出,也就是iq_ref。选用增量式而不是位置式,最大的好处是控制增量只跟最近三次误差有关,即使网络输出的PID参数发生突跳,控制量的变化也不会被直接放大,整体输出更平滑。

2.2 网络结构:输入三个数、输出三个数

我用的网络是典型的3-5-3结构:输入层3个节点,隐含层5个节点,输出层3个节点。输入选的是转速误差e(k)、误差变化率e(k)-e(k-1)、以及二阶误差信息e(k)-2e(k-1)+e(k-2),这三个量本身就和增量式PID的三个分量一一对应,网络很容易学到“什么时候该多用比例、什么时候该多用积分”的规律。如果再塞一个误差积分进去,输入变成4个,收敛速度反而更慢,我实测下来三输入就够用。

隐含层激活函数用tanh,取值范围在-1到1之间,比sigmoid的0到1更容易保持梯度稳定。输出层必须要做限幅处理,网络原始输出经过sigmoid压缩到0~1,再乘以各自的限幅系数:

Kp = Kp_max·out1,Ki = Ki_max·out2,Kd = Kd_max·out3

限幅范围需要根据被控对象来定。比如我那个示例模型里,Kp_max取5、Ki_max取20、Kd_max取0.01,这个范围不能给得太大,否则网络参数会在限幅边缘来回撞,转速波形会出现高频抖动。范围太小又限制了控制作用,动态响应变差。

2.3 反向传播:误差怎么“教”PID换参数

BP-PID的学习目标是最小化性能指标J(k)=0.5·e²(k),也就是转速误差平方。权值修正沿负梯度方向:

Δw(k) = -η·(∂J/∂w(k))

∂J/∂w展开之后会经过链式法则,需要穿过PID计算层和网络输出层。从误差到权值的传播路径大致是:J → 转速误差 → 控制量u → PID参数(Kp、Ki、Kd) → 网络输出层 → 隐含层。其中最麻烦的一项是∂y/∂u,也就是转速输出对控制量iq_ref的敏感度。这个偏导在真实系统里很难精确求,工程上最常用的做法是用符号函数sign(∂y/∂u)近似,也就是只保留方向、忽略幅值。

输出层的修正项可以写成:

Δw2(j,i) = -η·δ_j·h_i

其中δ_j等于误差e(k)乘以sign(∂y/∂u),再乘以对应PID分量的误差项——第一个输出对应Δe,第二个对应e(k),第三个对应二阶误差项,最后乘以输出层激活函数的导数。隐含层的修正项类似,只是误差信号要从输出层逐层传回去,再乘上tanh的导数1-h_i²。我在实际仿真里是按照这个标准BP流程实现的,下一节给示意代码。

2.4 学习率和动量项的工程取舍

学习率η建议从0.01开始试。太小的话,几百个控制周期都看不到权值有明显变化;太大会出现误差不降反升的情况,转速波形直接发散。动量项α的引入能明显改善学习稳定性:

Δw(k) = -η·(∂J/∂w(k)) + α·Δw(k-1)

动量项的作用相当于给权值更新加了一个惯性,让参数调整方向不会因为某一步的噪声突变而急转弯。我常用的一组取值是η=0.05、α=0.05到0.1之间,这个组合在大多数仿真模型里都能稳定工作。如果被控对象惯性很大,Learning率可以稍微调小一点。

3. 搭建Simulink整体模型:双闭环框架里把转速环“挖出来”换上BP-PID

3.1 模型拓扑和每个模块的职责

搭建顺序我建议按照信号流来:直流电源 → 三相逆变器 → 永磁同步电机 → 测量模块 → 坐标变换 → 电流PI → 反变换 → SVPWM调制,最后再处理转速环。千万不要一上来就堆大模块,先把传统双闭环跑通,再替换转速环,否则出了Bug很难定位。

核心模块的组成大致是这样的:

模块作用备注
DC Source提供直流母线电压常见311V或540V,按电机额定电压选
Universal Bridge三相两电平逆变器开关管用IGBT,内阻默认即可
PMSM模型被控对象使用Simulink自带的永磁同步电机模型
测量与坐标变换三相电流采样、转速/位置获取Clarke和Park变换建议自己搭或用现成库
电流环PI跟踪id_ref=0和iq_ref参数固定,带宽高于转速环5倍以上
SVPWM调制生成逆变器开关信号载波频率即开关频率,典型10kHz
BP-PID模块替代转速环固定PIMATLAB Function或S函数

3.2 自己常用的示例参数

我常用的一组仿真参数是:额定功率1.2kW、额定电压220V、极对数4、定子电阻2.875Ω、d轴和q轴电感都是0.0085H(表贴式电机)、永磁磁链0.175Wb、转动惯量0.0012kg·m²。直流母线电压取311V,开关频率10kHz。你要用自己的电机参数也行,核心逻辑不变。

采样时间的设置有个关键点:电流环控制周期取1e-4s,转速环控制周期取2e-4s,这样保证了内环比外环快两倍以上。BP-PID模块的采样时间必须和转速环一致,否则控制律的离散化效果会完全不对。整个仿真用固定步长求解器,我习惯用ode4,步长1e-6s。步长太大会在逆变器开关时刻产生数值振荡,波形看起来就像长了毛刺。

3.3 为什么电流环保持PI,只替换转速环

这一点值得展开说。把电流环也换成神经网络不是不行,但会带来两个问题:一是变量太多,最后仿真结果不理想时你很难说清楚是电流环的问题还是转速环的问题;二是电流环本身有SVPWM这种离散调制环节,带宽要求又高,神经网络在一个控制周期内完成前向计算和反向传播反而可能拖慢执行速度。让电流环继续用固定PI,保持高带宽的快速执行能力,转速环用BP-PID去负责“协调和优化”,这是一个分工合理、也符合工程直觉的方案。

我见过不少论文把两个环都换成智能算法,结果仿真跑下来波形也挺好,但一旦把采样时间调严苛一点就发散。原因往往是内环延迟太大。所以我的建议很明确:先做单环替换,对比效果有意义之后再考虑扩展。

4. S函数与MATLAB Function实现BP-PID:核心代码和那些血泪坑

4.1 用MATLAB Function还是S函数

早期不少文献用S函数写BP-PID,那套写法要对Simulink的S函数规范非常熟悉,不然flag分支写错一个,模型跑起来就莫名其妙。我自己的做法是用MATLAB Function模块,配合persistent变量保存权值和历史误差,代码结构和普通MATLAB脚本几乎一样,调试起来方便很多。如果模型要反复复用来发不少论文图,可以再改成Level-2 C MEX S函数,运行速度会快不少,但核心逻辑完全一致。

4.2 核心代码示意

下面给出一段能说明完整思路的示意代码。它不是一个可以无脑复制直接跑的产品级代码,因为实际接入Simulink时还需要处理端口类型和向量维度,但逻辑上已经覆盖了BP-PID的全部分支:

function u = bp_pid_speed(e, ts) % BP-PID转速环控制器 % e: 转速误差, ts: 采样周期 persistent w1 w2 e_1 e_2 u_1 first_run if isempty(w1) % 3-5-3 网络,权值初始化为小随机数 w1 = rand(5,3) * 0.2 - 0.1; w2 = rand(3,5) * 0.2 - 0.1; e_1 = 0; e_2 = 0; u_1 = 0; first_run = 1; end % 网络输入:误差、误差变化、二阶误差 x_in = [e; e - e_1; e - 2*e_1 + e_2]; % 隐含层 h = tanh(w1 * x_in); % 输出层,sigmoid映射到0~1 out = 1 ./ (1 + exp(-(w2 * h))); % 限幅映射到Kp/Ki/Kd kp = 5 * out(1); ki = 20 * out(2); kd = 0.01 * out(3); % 增量式PID计算 if first_run du = 0; first_run = 0; else du = kp*(e - e_1) + ki*e + kd*(e - 2*e_1 + e_2); end u = u_1 + du; % --- 反向传播修正权值 --- eta = 0.05; % 学习率 alpha = 0.05; % 动量项系数 sgn = sign(u - u_1); % sign近似被控对象的偏导 % 输出层误差项 d_out = e * sgn; delta_out = zeros(3,1); delta_out(1) = d_out * (e - e_1)* h(1); delta_out(2) = d_out * e * h(2); delta_out(3) = d_out * (e - 2*e_1 + e_2) * h(3); % 这里为了示意,简化了sigmoid导数和链式相乘,完整推导见正文 % 隐含层误差项(示意) delta_h = (w2' * delta_out) .* (1 - h.^2); % 权值修正(动量项略写) w2 = w2 - eta * delta_out * h'; w1 = w1 - eta * delta_h * x_in'; % 保存历史状态 e_2 = e_1; e_1 = e; u_1 = u; end

注释里我特意写了那行“完整推导见正文”,因为这段示意代码把sigmoid导数简化掉了,实际严格实现时输出层的梯度要加上out·(1-out)项,并且要把PID三个分量的偏导逐项乘进去。直接照抄这段代码可能收敛不稳,但它能帮你把整体流程跑通。

4.3 反向传播推导中的几个容易算错的地方

严格推导时,输出层的第j个节点到隐含层第i个节点的权值修正量是:

Δw2(j,i) = -η·e(k)·sign(∂y/∂u)·(∂u/∂K_j)·h_i·f'(net_j)

其中∂u/∂K_1对应Δe,∂u/∂K_2对应e(k),∂u/∂K_3对应e-2e_1+e_2,f'(net_j)是sigmoid函数对加权和的导数,恰好等于out_j·(1-out_j)。隐含层的误差项则要用输出层的误差信号加权求和之后再乘tanh导数。很多人写代码时漏了out_j·(1-out_j)这一项,结果就是权值更新方向符号颠倒、模型越跑越乱。我调试时踩过这个坑,最后用数值实验验证了一轮梯度方向才定位到问题。

4.4 最影响成败的细节清单

权值初始化千万不能用大随机数。我第一次用rand(5,3)直接初始化,第一拍输出直接飞到天上,模型直接就发散。正确的做法是把初始权值压到-0.1~0.1之间,让网络一开始输出接近零的控制增量,PID的输出主要由历史通道维持稳定,网络再慢慢“接管”参数调整。

Kp/Ki/Kd的限幅范围要相对保守。初始范围给太宽,网络在限幅边缘反复触碰,转速波形容易出现高频小锯齿。给太窄又限制控制作用,阶跃响应明显变慢。我调限幅的方式是先跑一版固定PI,把它的参数峰值记录下来,然后以这个峰值的1.5到2倍作为BP-PID的上限。

归一化也很关键。如果转速单位是rpm,误差动辄几百,而网络输入层没有归一化,tanh会早就饱和,梯度消失,学习完全停滞。最简单的方法是先把误差除以额定转速,让输入落在-1到1附近,控制器的输出再用实际转速范围去缩放。

5. 结果对比的“三个必测科目”:没有这几张图,仿真结论站不住

5.1 科目一:空载启动和转速阶跃响应

第一组必测出发点是验证动态品质。仿真时间设0.5s,从0开始给定转速阶跃到1000rpm,记录转速波形。固定PI那组我用经典的零极点整定法调出一组参数,尽量调到没有明显振荡;BP-PID则用上面那套网络结构。得到的对比结果大致是:固定PI的超调量在8%到10%左右,调节时间约0.08s;BP-PID超调量压到1%以内,调节时间约0.09s。注意这里超调改善非常明显,但上升时间并没有比固定PI短太多,因为BP-PID在网络学习的初始阶段控制动作偏保守,这是在线自整定的正常代价。

5.2 科目二:突加负载和突卸负载

第二组必测出发点是抗扰性能。让电机在0.2s时突然加上10N·m的额定负载,观察转速跌落和恢复时间。固定PI的典型表现是转速跌落50rpm左右,恢复时间接近0.15s,期间还有一个小幅振荡;BP-PID的转速跌落明显更小,大约20rpm,恢复时间不到0.1s,而且波形收敛非常干净。

这个对比就是BP-PID最能打动人的地方。因为神经网络在负载突变瞬间感知到误差快速增大,它会自动提高比例增益,控制量迅速补上去,同时积分项也加紧修正,所以转速跌落的深度和时间都被压缩。

5.3 科目三:参数失配和鲁棒性测试

第三组测试最关键,也是很多仿真报告里缺失的。把电机转动惯量人为调大50%,然后重复前面的阶跃和负载实验。固定PI在这种参数失配下往往会出现明显的振荡,甚至在某些更恶劣的参数下稳定裕度不足;BP-PID因为每个周期都在根据误差调整参数,相当于在闭环运行中自适应性补偿了参数变化,最终仍能维持稳定,只是调节时间会比参数完全准确时长一点点。

这一条结论其实才是BP-PID相比固定PI最本质的优越性:它不是对某个参数样本点调好的控制器,而是一个能持续适应对象变化的自适应控制器。在做课题答辩或者写论文时,这张参数失配的对比图一定要放在结果分析里,它比单纯的阶跃响应更能说明问题。

5.4 保证对比公平的细节

固定PI和BP-PID两组仿真除了转速环控制器不同之外,其余设置必须完全一致:同一个电机模型、同一个电流环、同一个采样时间、同一个求解器。控制器输出iq_ref的限幅也要保持一致。还有个容易忽略的点是网络的初始学习过程——BP-PID在启动最初几十毫秒内误差会有点波动,这是正常的,可以给网络留出学习时间,但对比时要把这段时间也如实展示,不要刻意剪掉。

6. 踩过几次坑之后的实操建议

做完这个课题,我最大的感受是:BP-PID这类在线自整定方法,真正的重点不在于神经网络本身有多复杂,而在于你如何把传统控制框架和智能算法合理地嵌合。先跑通普通双闭环再换BP-PID,这句看起来像废话,却是最有效的排查策略。我自己第一版模型是直接从网上找的带BP-PID的完整模型,结果波形不对,根本不知道是电流环参数问题、坐标变换符号问题,还是权值更新公式有问题。后来老老实实拆掉BP-PID、用固定PI重新调了一版基础模型,再把网络一层层加回去,问题定位快了很多。

最后分享两个小建议。一个是仿真数据最好用To Workspace模块把控制器的Kp、Ki、Kd实时存下来,这样能画出参数随时间变化的曲线,直观看到网络是怎么“调参”的,这东西放论文里比单纯转速波形更有说服力。另一个是如果后面想继续做深入,可以试试把sign符号函数近似换成RBF网络或模糊逻辑去逼近被控对象的雅可比信息,理论上学习平滑度会更好,这是我在对比了多种方案之后比较看好的方向——但先把你手里的BP-PID版本真正跑稳,再谈升级。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进