资讯动态

电机转速闭环控制中PI控制器的工程实践:为什么PI比PID更合适?

发布时间:2026/9/8 22:32:58 来源:尧图企业网站定制
别人调参数调的是PID我这次在P2阶段硬是把微分项给砍了只留了P和I。一开始组里还有人质疑说转速闭环不上D项动态响应能看吗结果实测数据出来超调量、调节时间、稳态误差三项指标全在要求范围内而且全程没被高频噪声折腾。这篇就把我这次做PI闭环控制的完整思路、实现过程和踩坑记录写下来特别是为什么在噪声敏感的场合PI反而比PID更合适。1. 为什么这个阶段我只用PI不加微分项1.1 从开环到闭环第一个拦路虎是静差说句实话如果只是让电机转起来开环给个占空比就够了根本用不上闭环。但P2这个项目的要求不是“转起来”而是“给定转速和目标转速的误差维持在允许范围内”。这就必须要引入反馈而反馈控制里最先遇到、也最容易理解的问题就是静差。纯比例控制也就是只有Kp的那一项它的作用是“误差越大输出修正越猛”。但你稍微推一下就会发现纯P控制天生就留了一个尾巴系统稳定后控制器必须持续输出一个不为零的控制量来对抗负载、摩擦力这些扰动可只要输出不为零比例项就要求误差不为零这个误差就是静差。静差大不大取决于你Kp给的有多高但Kp又不能无限加加高了系统就开始振荡电机转速会在目标值附近来回摆。所以PI控制器里的积分项本质上就是干一件事把过去所有误差累积起来用“历史欠账”来补足纯比例控制怎么都消不掉的那一点稳态偏差。只要误差长期存在积分项的输出就会一直增大直到控制量恰好抵消扰动误差收敛到零。用大白话说P负责“当下反应多快”I负责“最终偏差能不能归零”。1.2 微分项在数字控制里容易被噪声放大很多教材在讲PID的时候都会强调微分项可以预测误差趋势、抑制超调、加快响应。理论上没问题但到了实际电路里D项往往是第一个给你惹麻烦的。P2这个项目的电流采样用的是一块分辨率有限、采样噪声偏大的板子转速信号本身也有量化抖动。微分项算的是误差的变化率也就是相邻两次误差的差值除以时间。本来微小的随机噪声求一次差分之后幅度会被放大再乘以Kd最终叠加到输出上的就是一个剧烈波动的控制量。你会发现电机转速曲线看着挺平稳但PWM占空比在疯狂跳动驱动器发热也明显增加。我测试的时候试过一次带D项的参数组合比例不动只加一点点微分示波器上看输出波形原本干净的控制量曲线直接变成毛刺状。这种毛刺不会让系统立刻崩溃但它会显著加速功率器件的老化还会在机械结构上引入高频振动噪音。既然P2的重点是先跑通转速闭环、摸清系统特性我决定这一版干脆不上微分项用PI先把稳态性能和基本动态性能做扎实。1.3 PI的适用范围和边界条件PI不是万能的尤其对于纯滞后比较大的对象比如长传输管道、大惯量负载、或者存在明显纯延时的数字通信链路PI的积分项可能会因为“误差一直在输出一直加”而导致严重的振荡甚至发散。P2这个项目控制的是电机转速属于典型的二阶惯性对象时间常数适中滞后不明显PI是非常成熟的经典方案。如果是温度控制那种大滞后对象光靠PI整定会非常痛苦那时候就得考虑Smith预估器或者更高级的算法了。所以我理解PI闭环控制的定位是适用于被控对象有一定惯性、但纯滞后不严重的场合它用最小的计算开销解决稳态精度和基本动态响应问题。工程上不追求算法炫技能稳定、可靠、可维护地满足指标这才是关键。2. 从传递函数到MCU中断把PI算法真正写成能跑的代码2.1 连续域里的PI长什么样我们在纸面上讨论PI控制器常用的形式是u(t) Kp * e(t) (Kp / Ti) * ∫ e(t) dt这里的两个核心参数一个是Kp叫比例增益另一个是Ti叫积分时间常数。还有一个写法是u(t) Kp * e(t) Ki * ∫ e(t) dt其中 Ki Kp / Ti。这两种写法其实是等价的但工程习惯上我更推荐用Kp和Ti来记录参数因为Ti的量纲是时间物理意义更直观——积分项“追上”纯比例项的修正效果需要多长时间。Ti越小积分作用越强Ti越大积分作用越弱。我这次在项目记录里用的是Kp Ki的形式因为代码里直接就是两个系数相乘累加少一步除法运算MCU主频不高的场景下能省一点算力。但调试笔记里我同时标注了对应的Ti值方便后续跟理论模型对照。2.2 离散化位置式还是增量式控制器最终要跑在数字芯片里必须把连续的积分换成离散的累加。假设采样周期为T第k个采样时刻的误差为e[k]那么离散化后积分项 ≈ Σ e[i] * T对所有历史采样点求和位置式PI的输出u[k] Kp * e[k] Ki * Σ(e[i]) * T这种算法实现非常简单但有一个工程隐患它输出的直接是完整控制量一旦积分项把总和累得过大输出就可能超过执行机构的物理限幅。而且位置式算法必须把历史误差全部累加在同一个变量里如果前期误差一直很大后来误差变小了积分项要花很长时间才能“消化”掉那些堆积的旧账。增量式PI的思路则完全不同它不输出绝对控制量而是输出“本次控制量相比上次增加的量”Δu[k] Kp * (e[k] - e[k-1]) Ki * T * e[k]执行机构每次拿到的是增量再在自己的变量里做累加。这样做有几个天然好处第一即使某次计算或者通讯出错单次增量误差远小于绝对量误差系统不容易直接被带飞第二从位置式切换到增量式时不需要重新初始化历史误差过渡非常平滑第三执行机构自带积分作用控制器的积分项和机构的累加天然解耦。我在P2里选择的是增量式PI。电机驱动系统有个特性PWM占空比的绝对值不是最关键的关键是相对上一周期的变化量。增量式天然适合这种“步进调节”的执行方式就算采样周期偶尔抖动一下输出也不会出现跳变。2.3 采样周期T的选择原则和我的实测取值采样周期T是PI控制器落地的第一个关键参数。T选得太大控制器来不及响应快速变化系统容易出现极限环振荡T选得太小CPU开销增大而且误差差分会被量化噪声淹没Kp稍高一点就抖。工程上有两条经验路径。如果是纯软件实现的控制器T通常取系统机械时间常数的1/10到1/20如果是基于硬件中断的采样T要跟编码器或电流采样的更新周期对齐。P2用的电机额定转速2000rpm机械时间常数在50ms量级我最后把速度环采样周期定在5ms也就是200Hz的更新频率。这个值既避开了采样噪声的频段又足够覆盖机械响应的带宽实测下来毛刺很少响应速度也够。代码里我用一个定时器中断来触发采样和控制计算中断周期就是5ms。这里提醒一个细节中断服务函数里应该只做轻量级的计算和变量更新不要把串口打印、浮点运算、显示刷新这类耗时操作放进去否则中断执行时间超过采样周期整个控制时序就乱了。下面是P2里速度环增量式PI的核心代码片段我用的是定点数把浮点运算转成Q格式整数运算让主频72MHz的MCU跑起来毫无压力typedef struct { int32_t kp_q12; // Kp, Q12格式定点数 int32_t ki_q12; // Ki, Q12格式定点数 int32_t err_last; // 上一次误差 int32_t out_inc; // 输出增量 int32_t out; // 实际输出控制量 } PI_Inc_T; void PI_Inc_Step(PI_Inc_T *pi, int32_t target, int32_t feedback) { int32_t err target - feedback; // 增量式: du Kp * (err - err_last) Ki * T * err pi-out_inc (pi-kp_q12 * (err - pi-err_last) 12) (pi-ki_q12 * err 12); pi-err_last err; pi-out pi-out_inc; // 输出限幅 if (pi-out PWM_PERIOD_MAX) pi-out PWM_PERIOD_MAX; if (pi-out 0) pi-out 0; }这个结构体以后要扩展抗积分饱和逻辑直接在PI_Inc_Step内部加判断就行不用改动外部调用。实际跑起来一次步进计算的执行时间不超过10微秒对中断压力极小。3. 参数整定不用背公式我围着Kp和Ti转了两天的实战路线3.1 我不想一上来就背整定公式很多教材喜欢直接扔出齐格勒-尼古尔斯整定公式告诉你先让系统振荡、测临界增益和临界周期、再套公式算出Kp和Ti。这个方法理论上没毛病但放在P2的硬件上有个现实问题让系统进入等幅振荡需要把Kp调到临界值这个过程中电流冲击很大有几次我甚至闻到了一点糊味。对于有硬件成本、不希望反复折腾控制对象本身的场景我更推荐直接从响应波形出发的“手动逼近”路线边看响应边调先建立对参数的直觉。3.2 我的调试步骤先P后I再联合微调第一步只用比例项。把Ki设为0Kp从一个很小的值开始比如0.5然后给一个200rpm的阶跃目标看转速响应曲线。这时候你会看到两种典型情况超调大且振荡不断说明Kp太大响应慢、到达目标值的爬升过程很长说明Kp太小。我的做法是每次Kp增加20%左右每次调整后给系统1到2秒的稳定时间再记录曲线。盯着波形迭代了大约十轮之后我找到了一个Kp值让系统正好处于“轻度欠阻尼”的状态也就是转速第一次冲到目标值上方3%-5%然后很快回到目标值附近。有些教程要求把系统调到临界阻尼但工程上轻度欠阻尼反而更常见因为机械系统本身有一点阻尼轻超调可以显著缩短上升时间。第二步加入积分项。固定刚才找到的Kp把Ti从大往小调。这里有一个很多人反着来的误区不是一开始就调成很小让积分作用很强而是从大到小慢慢加强。我初始设Ti1000ms这时候转速曲线底部的稳态误差几乎没有改善因为积分作用太弱了。然后每次把Ti减半500ms、250ms、125ms观察稳态误差的收敛速度。有一个很明显的信号能说明积分作用合适了转速进入稳态后误差曲线不再有那个顽固的“平台期”而是缓慢而稳定地趋于零。继续把Ti往下压比如压到30ms你会发现转速开始出现低频周期波动这就是积分作用过强系统进入极限环振荡的前兆。遇到这种情况把Ti往回退一档多留30%的安全余量。第三步联合微调。加好积分项之后系统的阻尼特性会变原来Kp合适的点会变得偏过阻尼还是欠阻尼需要在Kp和Ti之间做两三次交叉微调。我的做法是固定一个感受基准就是阶跃响应曲线的“第一波峰值”和“回归目标值的用时”。如果第一波峰值超过8%我就降低Kp如果回归目标值的用时占整个过渡过程的比例太大我就稍微加大一点Ti也就是减弱积分作用。最终P2的速度环参数落定在Kp18.5Ti120ms等效Ki≈154。阶跃响应数据为超调量约4.5%调节时间约220ms稳态误差±2rpm以内在200rpm的参考下大约是1%精度满足项目要求。3.3 参数整定的速查对照表我把这次调试过程中出现过的典型现象和对应的调整方向整理成了下面这张表格以后接手类似项目的同事可以直接拿来对照响应现象原因分析调整方向转速到达目标值极慢像“爬不动”比例增益不足增大Kp轻微超调后快速稳定稳态无静差理想欠阻尼状态保持超调明显、来回振荡几次才稳定比例增益偏大或积分偏强先减Kp再增大Ti持续等幅振荡、不衰减增益过大或采样周期不合理大幅减Kp检查T是否过小稳态存在固定偏差、长时间消不掉积分作用太弱减小Ti转速出现低频周期漂浮积分作用过强增大Ti波形毛刺多、高频抖动测量噪声污染或Kp过高先查采样滤波再减Kp这张表的价值不在于替代理论而是帮助你快速定位问题区间减少盲目的参数试错。3.4 用“扰动法”验证鲁棒性而不是只看阶跃响应阶跃响应只能说明系统能跟上指令变化但实际运行时更多时候需要对抗的是外部扰动比如负载突然增加、供电电压波动。这里我推荐一个很实用的测试方法让系统稳定运行在某个转速上然后手动给电机的输出轴施加一个短暂的阻力比如用手轻捏一下联轴器注意安全转速别太高同时记录转速恢复过程。PI控制器对扰动的恢复速度最能体现参数到底合不合适。P2的实测效果是在500rpm稳定运行状态用手轻碰一下转轴转速瞬时掉到420rpm左右随后在150ms内回到目标值附近恢复过程的超调控制在4%以内。这个数据说明比例项对瞬时扰动的抵抗能力足够积分项又能以合理速度“补偿”残余偏差。如果恢复过程又慢又拖泥带水那就是积分作用太懒了。4. 实测中踩过的三个大坑积分饱和、启动冲击和噪声抖动的完整排查链路4.1 积分饱和超调的隐形推手尤其在大给定阶跃时第一个坑发生在从200rpm直接切到1500rpm的时候。起初我用的还是从低速阶跃调试收敛的同一套参数但转速曲线直接来了一个25%的大超调然后花了很长时间才跌回目标值。问题不在Kp上而是积分项“堆账”了。积分饱和出现的机制是这样的1500rpm阶跃导致的初始误差高达1300rpmPI控制器一上来就疯狂增大积分几毫秒内输出就冲到了PWM限幅值。实际上系统加速需要时间误差不会瞬间消失误差大→积分继续增大→输出长期饱和这个状态持续了整整一截加速过程。等到转速终于接近目标值误差开始变小时积分项里已经积攒了一个巨大的“正数欠账”哪怕误差已经变成了零这个欠账仍然让输出维持在高位结果就是转速冲过头。之后积分项才开始慢慢“还债”转速才回落。排查链路是这样的先看输出曲线发现PWM占空比很早就顶到了100%并且维持了很长时间再看误差曲线转速达到目标值附近时误差已经开始收窄了但输出仍然不被松开最后定位到积分累加器里积攒的数值远大于稳态需要的数值。这不是某个参数固定的问题而是算法结构缺少了对积分饱和的约束。解决这个问题我用了两个手段。第一是限幅积分累加值把积分项的输出限制在一个比执行机构物理限幅更小的范围内这样即使积分饱和发生输出也不会卡死在最高位太久。第二是条件积分也叫条件抑制积分判断只有当前输出没达到执行机构限幅时才允许积分继续累加输出在限幅饱和状态时积分就暂停。这两个手段叠在一起1500rpm阶跃的超调量直接降到了7%以内。代码里加上抗积分饱和逻辑之后的样子void PI_Inc_Step_AntiWindup(PI_Inc_T *pi, int32_t target, int32_t feedback) { int32_t err target - feedback; int32_t saturated (pi-out PWM_PERIOD_MAX)? 1 : (pi-out 0)? -1 : 0; if (saturated 0) { // 未达到限幅正常积分 pi-out_inc (pi-kp_q12 * (err - pi-err_last) 12) (pi-ki_q12 * err 12); } else { // 已进入限幅仅保留比例项计算积分项冻结 pi-out_inc (pi-kp_q12 * (err - pi-err_last) 12); } pi-err_last err; pi-out pi-out_inc; if (pi-out PWM_PERIOD_MAX) pi-out PWM_PERIOD_MAX; if (pi-out 0) pi-out 0; }注意增量式实现里虽然输出变量本身就带有一定“积分”属性抗饱和处理同样不可省因为限幅让输出变量和真实执行值脱节后误差消失时输出还需要额外一步补偿才能回落。4.2 启动瞬间的冲击电流PI控制器的第一个敌人第二个坑在冷启动时就暴露了。目标转速从0直接给到1000rpmPI控制器在最初几个采样周期内把输出拉到最大电机瞬间获得接近满占空比的电压电流冲击很大导致供电电压都出现了明显跌落。这对电池供电的便携设备来说完全不能接受。这个问题的根源不是PI本身而是阶跃指令对系统来说太“陡”了。解决方案我用了两点一是把阶跃目标改成斜坡目标也就是让目标转速以预设的斜率爬升给电机一个渐进的加速过程而不是瞬间拉满。二是在启动时限制输出增量每次步进允许的最大变化量单独设一个上限防止输出突变。斜坡时间我根据机械结构的承受能力设为300ms也就是0到1000rpm在300ms内线性爬升。实测电流冲击从原来的4.2A降到2.1A降幅超过一半机械连接的冲击感也明显变轻。这个斜坡参数可以做成可配置项不同的负载状态可以动态调整。提示斜坡时间不是越长越好。太长的斜坡会增加工时和加速时间对需要快速响应的设备来说是负面优化。一般取正常阶跃响应调节时间的1.0~1.5倍实测比较合适。4.3 噪声抖动和数据记录中的“假象”第三个坑是排查难度最高的一个。有一段时间我盯着转速波形总觉得输出曲线的规律性很强没有毛刺但用手摸电机外壳能感觉到细微的高频振动。用上位机记录下来的转速数据看不出异常可振动就是存在。排查链路是先怀疑机械装配问题检查联轴器、轴承座确认没有明显的不同心。再怀疑PWM频率换了几组频率问题依旧。最后把电流波形拉出来看发现PWM占空比其实每几个周期就有一个小幅度的跳变虽然幅度很小但频率落在机械共振频段附近电机壳体就开始振。这个抖动不是传感器噪声直接引起的而是编码器的量化误差在低转速下占比太高导致误差值在相邻采样点之间反复横跳。转速越高编码器一个脉冲对应的时间越短量化误差的相对影响越小转速低到一定程度这种量化抖动就开始主导误差PI控制器误以为转速在波动于是输出跟着来回调整。定位到原因后我加了两个措施。一是对编码器测速做滑动平均滤波窗口取3个采样点也就是15ms增加测速稳定性二是在PI算法里对误差做死区处理当误差绝对值小于3rpm时不再更新积分项只保留比例项跟随时输出这个死区大小需要根据控制精度要求调整太小没效果太大会让人感知到稳态偏差。两个措施加完后高频振动消失电流波形也干净了很多。从这几个坑可以发现很多PI调试过程中的异常根源往往不在PI参数本身而在采样链路、执行机构特性和外部干扰上。排查问题时一定要先怀疑数据来源再怀疑算法最后才怀疑参数。5. 交付前如何证明PI真的“闭环成功”量化指标和边界测试5.1 阶跃响应的四个核心指标怎么统计做完了整定和避坑还不能直接说项目完成。工程交付必须有无可争议的量化数据否则后续交接或者评审时拿不出说服力的证据。我在P2阶段用上位机自动记录了阶跃响应数据并且写了一段简单的分析脚本自动识别四个核心指标超调量转速越过目标值的最大偏移除以目标值百分比表示。调节时间从阶跃发出到转速进入并停留在目标值±5%两个设定阈值带内不再出去的时间。稳态误差进入稳态后100个连续采样点的平均误差以及最大波动范围。上升时间从目标值的10%到达90%所需的时间。实测数据记录如下目标转速1000rpm指标实测值项目要求结论超调量6.3%≤10%通过调节时间280ms≤500ms通过稳态误差±2rpm±5rpm通过上升时间145ms≤300ms通过这组数据说明PI参数在需求域内是达标的而且留了一定的余量。这里要提醒一个细节调节时间的统计基准是“进入误差带后不再次超出”有些人在统计时只看第一次进入误差带的时间点这样会把实际超调后回落的情况也算成已完成数据会虚低评审时容易被挑战。5.2 打破常规工况的边界测试除了指标我还做了几组边界测试重点看系统在最恶劣情况下的行为先从最低目标转速起步100rpm给阶跃观察PI是否还有能力稳定在低速区间。低速的问题是编码器脉冲间隔变大量化误差突出实测在这个转速下稳态误差变为±6rpm波动相对偏大但系统没有失去稳定。再给最高目标转速接近电机标称极限的1900rpm此时PWM占空比已经接近饱和。PI的抗积分饱和机制在这里起了关键作用转速最终稳定在1896rpm左右没有出现超调后长时间回落不了的迹象。然后是负载扰动测试在稳定运行的状态下给转轴施加一个持续负载记录转速跌落和重新恢复的过程。实测转速从800rpm跌到760rpm恢复时间约180ms稳态误差回到±2rpm以内说明PI对这种持续扰动有很好的补偿能力。5.3 长期运行的稳定性确认短时间测试通过不意味着长时间稳定尤其是积分项相关的漂移问题需要让系统持续运行来暴露。我让电机连续以800rpm运行了10小时每小时记录一次稳态误差、控制器输出均值和芯片温度。10小时跑下来稳态误差始终在±3rpm以内没有出现积分项随温度漂移而越积越大的现象。控制器输出均值也非常稳定只在±1%的占空比范围内缓慢变化。这说明温度变化对PI参数的影响在可接受范围内不需要在线调整参数。如果系统表现出明显的长时间漂移比如稳态误差随时间逐渐增大或者控制器输出均值单调上升就需要考虑加入参数自适应或者定时重置积分项的机制。P2这个项目目前还没到这个复杂度但留了接口后续如果需要扩展不需要推翻现有框架。最后的调试体会项目收尾之后我复盘了一下PI闭环控制本身并不复杂真正让人花时间的地方全在细节采样周期和噪声的关系、积分饱和的隐蔽性、抗饱和逻辑和斜坡启动相互配合的时序、以及边界条件下的稳定性验证。P2阶段我把微分项去掉的这个决定从结果看是完全正确的项目指标的达成率高而且省去了大量和噪声做斗争的调试时间。如果之后遇到需要使用D项的场合我会先确认采样链路已经足够干净或者说滤波带来的滞后可以接受再来评估是否值得引入微分项。对于电机类负载的控制需求先用好PI把P和I的行为吃透很多时候就已经够了。

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

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

免费获取报价