
做电机驱动和运动控制的工程师应该都见过这种场面转速稳态波形不是平的而是像心电图一样规律地抖FFT一分析基频峰值明晃晃地立在那儿。我最早是在带周期负载的永磁同步电机上撞上这个问题的压缩机曲轴每转一圈负载转矩就狠狠波动一次PI参数调到临界稳定转速波动依然压在头上。后来换成“PI重复控制”的复合结构几个周期内波形就安稳下来效果立竿见影。这篇文章就把这件事从头到尾拆开讲扰动为什么压不住、重复控制凭什么能压住、Simulink里怎么落地、以及我在调参和排坑过程中攒下的经验。具体会覆盖这些内容周期性负载转矩扰动在哪些场景最常见重复控制的内模原理以及怎么从离散角度理解“延迟N拍就是记住上一周期的误差”在Simulink里搭建从被控对象、扰动源到重复控制器的完整仿真模型核心参数Kr、Q、N各自的作用与调参顺序还有我踩过的几个实打实的坑包括延迟周期不匹配、初值漂移和变步长求解器引发的锯齿振荡。适合谁看正在做伺服驱动、机器人关节、机床主轴、压缩机等转动系统的控制工程师以及对重复控制感兴趣、想在Simulink里快速复现的初学者。1. 为什么普通反馈压不住周期性负载转矩扰动1.1 扰动长什么样周期性负载转矩的工程来源周期性负载转矩在转动系统里几乎是无法回避的存在。最常见的几个来源偏心负载比如洗衣机脱水桶、曲柄连杆机构负载转矩随转角变化大致呈现正弦或者多阶谐波叠加的形态。电机本体转矩脉动永磁同步电机的齿槽转矩随转子位置周期性波动频率通常是电机极对数的整数倍。齿轮啮合冲击齿轮箱每转一圈齿与齿的啮合产生一个固定频率的转矩扰动频率等于轴转速乘以齿数。压缩机、泵类负载活塞或叶轮在每个工作周期内受力变化转矩波动频率和旋转周期直接绑定。这类扰动的共性是变化规律确定、周期固定但频率往往远高于转速闭环带宽或者正好落在闭环截止频率附近。PI控制器治理这类扰动本质上是在用比例积分环节去反复“追赶”一个不停变化的扰动信号结果就是相位滞后和幅值不足最终体现为稳态转速波动。我习惯用一句话总结只要扰动频率和电机转速有整数倍关系并且能被看成“周期已知”的信号那就非常适合用重复控制来处理。换句话说这种扰动有规律地在折磨你但它也因此有规律可循。1.2 反馈控制为何无力从误差到输出只有一条迟滞路径常规反馈控制能不能抑制周期性扰动能但有上限。对于一个周期为Tp的扰动把它展开成傅里叶级数它就是一簇基波加谐波。反馈控制系统对扰动的抑制能力取决于该频率处的开环增益。拉高增益确实能压低扰动但增益是有上限的机械谐振、相位延迟、测量噪声、采样离散化这些因素都会限制你最终能加多大的增益。更直观的理解是PID对“下一次出现在同一个位置的扰动”没有任何预判它只能在扰动已经表现为误差之后再去反应。误差先发生控制器后调节相位滞后必然存在。到了周期性扰动面前这种“事后反应”的缺陷被放大你刚把上一周期这一瞬间的误差压下去到下一周期的同一时刻扰动又原样扑过来了。我在仿真里做过一个很直观的对比一个以25Hz周期变化的负载转矩叠加在转速环上PI参数已经调到临界稳定边缘转速波动仍然有±30r/min。这不是PI参数没调好而是它的工作方式决定了它只能做到这个程度。要彻底压低这类稳态波动必须从“误差发生前”做文章这也就自然引出了重复控制。2. 重复控制的内模原理把一个“信号发生器”搬进闭环2.1 内模原理闭环里包含信号的模型才能对它有零稳态误差重复控制的底层逻辑来自内模原理听起来高大上其实一句话就能讲明白如果一个控制器内部“内嵌”了目标信号的数学模型那么这个信号在闭环里就不会产生稳态误差。拿阶跃信号类比。为什么PI控制器的积分环节能消除阶跃误差因为阶跃的模型是1/s而积分器本身就自带这个模型。当被控对象无法直接等于阶跃时积分器会不断调整输出直到误差消失。同样道理正弦信号的模型是s²ω²如果你把等价形式放进控制器你就能对固定频率正弦扰动做到零误差抑制。重复控制就是内模原理在周期信号上的推广它把“周期重复”这个性质本身作为模型放进了控制器所以它对任意波形、任意谐波成分的周期扰动理论上都有全频次的抑制能力。从离散域看更清楚。周期为Tp的信号离散化后用N拍表示它一定满足任意第k拍的值等于第k-N拍的值。因此周期信号的离散模型就带有一个1/(1-z^{-N})的分母。把1/(1-z^{-N})放进闭环就是构造了一个周期内模。这也是重复控制器在Simulink里总是绕不开延迟模块的根本原因它要直译的就是这个数学关系。2.2 离散延迟N重复控制器的“记忆体”与误差累计机制既然周期信号满足x(k)x(k-N)那么控制器内部只需要部署一个N拍的延迟环路就能让信号“自动重放”上一周期的波形再配合误差信号逐步修正形成迭代学习的效果。以最简单的并联型结构为例当误差e出现在输入端时重复控制器的输出u_rc会经历这样的过程第一周期误差第一次出现重复控制器输出基本来自当前误差经增益Kr放大后的值延迟环路里还没存下足够信息修正有限第二周期记忆单元里已经有上一周期同一时刻的输出值它会用“上周期此刻的值”加上“上周期此刻误差的修正量”作为本周期此刻的输出循环往复每个周期都更新记忆值直到误差的各次谐波被逐步抵消记忆单元里的波形稳定下来就等于生成了一个与扰动反相、幅值匹配的“对抗波形”。这里N是灵魂参数N等于扰动基频周期对应的采样拍数即Nfs/fp。比如采样频率10kHz扰动频率25Hz那N10000/25400。只要N精确延迟单元就能在相位上与扰动严格对齐这是整篇文章里最容易出错、也最关键的一个数字。纯内模1/(1-z^{-N})是临界稳定系统对模型不确定性非常敏感工程上几乎不会直接用它而是会在反馈支路里串联一个低通Q(z)把极点从单位圆上拉回圆内。这个Q(z)就是搭建模型时重点处理的一个环节。3. Simulink模型搭建从被控对象到重复控制器一体成型3.1 顶层框架转速环、转矩环简化与被控对象建模先明确我要搭的仿真对象一个典型的永磁同步电机速度控制环。电流环动态相对较快为了聚焦重复控制本身我对电流环做了一定简化直接用比例增益Kt表示电磁转矩常数机械部分用转动惯量J的积分环节表示负载转矩T_L作为扰动输入叠加在电机轴上。在Simulink里我把模型分成四块参考转速与PI控制器给定速度refPI输出作为转矩指令的基准部分重复控制器输入转速误差e输出u_rc叠加到PI输出上共同构成转矩指令被控对象从转矩指令到电磁转矩乘以1/J后积分得到转速周期扰动源T_L通过Gain1/J叠加进同一个积分节点测量与记录转速经To Workspace导出方便后续做FFT分析。使用“PI重复控制”的复合结构而不是纯重复控制是工程上很重要的取舍。重复控制对周期信号抑制能力强但动态响应慢因为它的修正要等满一个周期才能看出效果PI则相反对阶跃和突变响应快。两者并联一个管动态一个管周期稳态误差任务分离互不干扰。刚开始学重复控制的人如果直接上纯重复控制器会发现负载突变时转速动态很拖沓反而容易误判方案不可用。顶层信号流向可以这样描述速度误差分成两条支路一条进PI一条进重复控制器的误差通道PI输出加重复控制输出得到总转矩给定Te*Te*经饱和限幅后乘Kt得到电磁转矩TeTe减去T_L乘1/J积分得到转速omegaomega负反馈回给定端形成闭环误差。3.2 重复控制器内部用Delay、Gain和Filter把内模搭出来重复控制器的内部结构我搭成最经典的“历史记忆误差修正低通滤波”三段式模块选择如下记忆回路使用Discrete Delay模块延迟步数设为N用来存住上一周期的输出值误差修正当前误差e(k)与N拍前的误差e(k-N)做差乘以增益Kr低通滤波Q(z)常见做法是用常数Q0.95放在延迟反馈支路里也可以用一阶低通Discrete Filter实现进一步提高鲁棒性。并联型重复控制的数学形式如下u_rc(k) u_rc(k-N) * Q Kr * ( e(k) - e(k-N) * Q )这里Q是0.95或者低通滤波器的输出Kr是重复控制增益。e(k)-e(k-N)的意义是只有当本周期误差和上一周期同一时刻不一致时才做修正如果完全一致说明记忆波形已经和扰动匹配保持原样输出即可。这就是“误差累计”的直观写法。在Simulink里具体接线拉一个Discrete Delay模块延迟步数填delayN初始条件填0拉一个Gain或者Discrete Filter作为Q这里先用常数Gain0.95举例误差e经过一个Sum模块实现 e(k) - DelayN(e)*Q上述结果乘以Kr再用一个Sum把修正量和DelayN(u_rc)*Q相加得到u_rc在u_rc输出端加Saturation限幅模块限幅值跟随转矩指令限幅设置。这个结构在Simulink里看起来像一个自环很多人第一次搭会担心代数环问题。实际不必担心因为有延迟模块隔开k时刻的输出只依赖k-N时刻的量闭环在时间上被延迟切断不存在代数环直接跑即可。3.3 初始化脚本与参数设置用脚本而不是手填才能复现我强烈建议模型所有关键参数都通过Matlab脚本设置而不是在GUI模块里手填数值。原因很简单采样周期、延迟周期、PI参数、Q系数、扰动频率之间存在耦合关系手填一次就等于埋一个雷改起来极易漏改。我的脚本大概长这样%% 基本参数 Ts 1e-4; % 采样周期 100us fs 1/Ts; % 采样频率 10kHz fp 25; % 负载转矩扰动基频 Hz delayN round(fs/fp); % 延迟拍数 400 %% 被控对象参数 J 0.01; % 转动惯量 kg·m^2 Kt 1.0; % 电磁转矩常数 Nm/A Kp 2.0; % PI比例 Ki 10; % PI积分 %% 重复控制参数 Kr 0.8; Q 0.95; %% 扰动参数 tOn 0.3; % 扰动开始时间 TL_amp 0.5; % 扰动幅值 Nm把脚本跑一遍Simulink模块参数位置直接填变量名。比如Discrete Delay的Delay length填delayNGain填KrPI的P填KpI填Ki。这样一旦扰动频率变化只需要改fp重复控制支路的延迟周期自动跟随。求解器建议选择discrete或fixed-step discrete固定步长等于Ts具体原因等第5节详细说。仿真时长建议设为0.8到1.2秒保证重复控制经历30到50个扰动周期稳态效果才看得清楚。4. 调参与仿真结果分析三个关键参数决定控制品质4.1 Kr、Q、N各自的作用先懂原理再动手调重复控制的三个核心参数作用完全不同不能只盯着一个调。周期延迟N决定内模频率是否准确。N必须是扰动周期的整数拍数原则上越准越好。一旦N有偏差相位对齐就失效谐波压不下去。工程中若转速变化导致扰动频率漂移就需要变周期重复控制或自适应方案。增益Kr决定每个周期误差被“消化多少”。Kr太大会引发振荡甚至发散太小收敛慢。经验工作范围在0.3到1.0之间一般从0.5起步试探。低通Q(z)决定鲁棒性与稳态精度的折中。Q1时是理想内模稳态能力强但鲁棒性差常数Q0.95左右足以限制高频增益、提高稳定性代价是极低频外会有极小残差用低通滤波器更真实但实现更复杂。一个实用的调参顺序是先固定Q0.95Kr从0.3开始每次增加0.1观察转速误差波形直到出现振荡就退回上一个值然后回头微调Q在0.9到0.98之间测试。我个人的经验是只要Kr不超过1就能收敛就没有必要在Q上追求复杂的滤波器结构。常数Q胜在简单、直观、好复现工程调试时能少出很多幺蛾子。4.2 仿真结果怎么看从时域波形到FFT量化仿真的目的不是“跑出一条好看的线”而是量化抑制效果。我建议用To Workspace把转速误差e保存下来扰动加入后取最后若干个周期做FFT。对比项设置两个场景A只有PI控制重复控制支路增益设为0场景BPI重复控制全部启用。同样施加25Hz、0.5Nm的周期扰动结果通常是这样指标纯PIPI重复控制转速波动峰峰值±30 r/min左右±3 r/min以内25Hz基波误差幅值FFT较高下降一个数量级以上50Hz/75Hz谐波尚可见同步大幅下降收敛时间瞬时约0.3到0.5s不要被“收敛时间”吓到这里的收敛慢不是动态响应慢而是“学习”需要时间。前几个周期里重复控制输出还没被修正到合适波形相当于还在离线学习阶段但它不影响PI处理阶跃突变因为PI仍然负责快速动态。这就是复合结构最舒服的地方两者任务分离互不干扰。4.3 稳态精度与鲁棒性的折中限幅和饱和处理不能忘还有一个容易被忽视的点是重复控制输出限幅后的积分饱和问题。由于重复控制器内部存在延迟环路相当于一个慢积分器一旦输出被限幅截断记忆值会继续往饱和方向发展最终导致退出饱和后的大幅过冲。解决办法是在重复控制输出处加限幅同时把限幅值设得比总转矩指令限幅更紧一些。比如总限幅±5Nm重复控制输出限幅±3Nm。这样即使重复控制器饱和它也只是转矩指令的一部分不会让整个环路陷入深度饱和。工程里还可以对u_rc做“记忆值冻结”当误差方向与修正方向长期不一致时暂时关闭误差修正项。初学者先在Simulink里做限幅对比实验就能直观看到差异。5. 这些坑我踩过周期延迟不匹配、初值漂移与仿真步长5.1 周期延迟N算错了谐波抑制直接失效这是重复控制仿真里最容易出现的翻车现场。我在给一个压缩机负载建模时一开始把扰动频率当成“转速×50%”来算N结果谐波抑制一事无成误差波形从平滑正弦变成了毛刺抖动。排查过程其实很简单先对扰动信号自己做一次FFT确定它的真实基频fp再用delayNround(fs/fp)重新计算。但要注意如果扰动频率不是转速基频的整倍数比如齿轮齿数带来的啮合频率这个fp可能是转速的17倍或31倍那就老老实实按啮合频率来设N。仿真的第一步永远是确认“周期到底是多少”而不是“我觉得大概是”。另外如果fp很低导致N很大比如fp5Hz、fs10kHzN2000延迟模块会占用较多内存但Simulink完全可以处理不用特别担心。更需要注意N的浮点舍入round之后要回代检验一下实际对应的频率偏差。偏差小于扰动频率的0.1%基本无感偏差大了就要用更高的采样率或者考虑小数延迟补偿。5.2 初值漂移启动瞬间的“学习冲击”怎么压下去重复控制器的记忆数组初值默认是0。模型一运行误差刚出现时重复控制器会按“误差修正”逻辑在第一个周期内快速输出一个较大的修正量如果Kr偏大转速波形会出现一个尖峰。这不是理论问题是初值处理问题。我的处理习惯有两个在扰动源上加开关让扰动在第0.3秒后才接入。这样前0.3秒内系统已经稳定在给定转速附近误差为零重复控制器的记忆值安稳地保持0不会产生冲击如果扰动必须在0时刻就存在就把重复控制器的使能信号接到一个延迟触发逻辑上等系统进入稳态后再使能。Simulink里用Timer模块或者Step模块做使能条件即可。这两个技巧看着不起眼能省去大量排查“为什么启动瞬间转速过冲”的时间。5.3 求解器与采样率变步长连续仿真为什么会莫名其妙振荡最后一个高频踩坑点是求解器设置。我在初版模型里用了ode45变步长连续求解器跑出来的波形在加入重复控制后出现锯齿状振荡而纯PI完全正常。排查到最后发现问题不在算法而在求解器与离散延迟模块之间的步长失配。Discrete Delay模块的延迟拍数N是基于固定采样周期Ts定义的但连续变步长求解器在动态过程中实际步长会变化模块内部“一拍”对应的真实时间并不恒定导致延迟时间长度在仿真过程中漂移。重复控制对相位异常敏感延迟误差一点点就能破坏抑制效果。解决方案很明确把求解器设为discrete或fixed-step discrete固定步长等于Ts。这样每个采样步严格等间隔延迟模块一拍就是TsN拍的物理时长才恒定等于周期。如果你必须用连续模型也可以用定步长ode4或ode5配合固定步长Ts效果等同。这一点务必在仿真开始时一次设好不要等跑出怪波形才回头查。6. 从仿真到工程应用可以往哪里继续深入6.1 电流环和转速环中重复控制的差异带宽位置决定效果上限仿真模型里我把重复控制加在了转速环这是初学者比较直观的理解方式。但在实际电机驱动里重复控制的安放位置很有讲究。放在转速环优点是误差信号直接反映转速波动物理意义明确缺点是转速环带宽低重复控制能覆盖的频率范围有限对中高频转矩脉动的抑制效果会受到机械滤波作用的遮挡。放在电流环则不一样。电流环响应快重复控制可以覆盖更宽的频率范围对电机本体转矩脉动比如较高的齿槽谐波效果更好。代价是电流环里的扰动数据量更大对延迟周期N的计算要求更高。我的建议是如果是负载周期扰动来自机械负载放转速环如果是电机自身转矩脉动放电流环。仿真时可以把同样的重复控制器复制到两个位置对比一下波形这个对比过程本身就是学习重复控制最好的练习题。6.2 变周期问题当扰动频率随转速变化时怎么办重复控制的内在逻辑要求扰动频率基本恒定但工程中转速往往不是恒定值负载扰动频率会跟着转速变。这个问题有两条工程路径转速前馈同步当转速由指定指令决定时扰动频率可以写成转速的函数实时计算N并同步更新延迟模块。Simulink里可以用Variable Delay模块实现变延迟参数为当前转速下的周期拍数自适应重复控制引入自适应律在线调整N或Q学术文献里很多工程实现稍复杂。对多数应用来说先把前馈同步做好就能解决90%的问题。我自己的建议是初学者先在定转速工况下跑通重复控制理解N的物理含义后再考虑转速变化。一上来就挑战变周期学习曲线陡到容易放弃。6.3 推荐学习路径从仿真复现到单参数扫描如果你准备完整复现这个仿真我推荐一个带有梯度的学习路径从第3章的模型开始跑通PI重复控制的完整闭环分别设置Kr0.1、0.5、1.0用Scope观察误差波形对比收敛快慢与过振荡点把Q改为0.9、0.95、1.0观察稳态误差与鲁棒性变化把fp改成30Hz、50Hz注意N必须同步更新看基波抑制是否依旧有效尝试把扰动源改成“方波周期扰动”验证重复控制对非正弦周期扰动的抑制能力。每一步都要做FFT量化分析不要只看时域。这个流程走下来你对重复控制的理解会比看十篇论文更扎实。关于重复控制仿真我想再多说一句体会。很多人第一次看到波形被压平时会觉得“参数对了就完事”但真正能迁移到工程上的能力其实是判断“这个扰动到底是不是周期的、周期是多少、应该在哪一层闭环里去治理它”。我在实际项目里踩过的坑远比仿真多比如把负载转矩脉动误当成阶跃扰动调PI调了几天没效果也见过有人把重复控制输出限幅忘掉结果一启动就饱和顶到限幅值。这些都说明仿真模型不只是一种工具更是一种训练判断力的方式。希望这篇经验分享能帮你少走点弯路。