交互式模拟器入门

面向机器人控制系统的 PID 控制器模拟器

在这个 PID 控制器模拟器里,一边整定比例、积分和微分三个增益,一边把系统的响应、误差、饱和与扰动都画出来观察。

类别
控制系统
时长
60–120 分钟
平台
浏览器 · Arduino
面向机器人控制系统的 PID 控制器模拟器 技术示意图RESPONSETIMESETPOINT

01 / 从这里开始

简介

PID 控制贯穿整个机器人领域:轮速、航向、关节位置、温度和平衡系统都依赖反馈。这个项目把控制器变成一个看得见的实验。改变一个增益,扰动一下被控对象,再把由此得到的曲线与能在 Arduino 或嵌入式控制器上运行的代码联系起来。

Live lab / Deterministic sampled control loop

PID controller simulator

Drive a second-order plant toward a setpoint. Tune each gain, inject a load, and watch response, error, and control effort in real time.

Browser native
This simulator plots a PID controller's response, error, and control effort over time. Use the controls below to run it, or read the full theory and algorithm after this lab.

Three stacked plots share a scrolling time axis: measured output against the setpoint line, tracking error around zero, and control effort inside the shaded actuator-limit band.

Simulation

Paused. Press Start or Step to begin.

Setpoint & timing
PID gains
Disturbance
Setpoint
1.00
Measured
0.000
Error
1.000
Control
0.000
Overshoot
0%
Steady-state error
1.000

Keyboard: focus the plots, then use Space to run/pause, N to step, R to reset, G to toggle the load, and F for full screen.

控件

模拟器开放设定点、比例增益、积分增益、微分增益、采样间隔、执行器限幅和扰动幅值这几项参数。对齐的图表会显示设定点、测量输出、误差和控制输出。重置会清空控制器的记忆,让各次实验之间保持可比。

原理

反馈控制器用设定点减去测量值来算误差。比例作用立即响应,积分作用累积持续存在的误差,微分作用响应的则是变化率。三者之和就是执行器指令。

控制器的性能受被控对象所限。采样太慢会把运动藏起来;驱动超过执行器限幅就会饱和;而带噪声的测量会让未经滤波的微分项变得不稳定。因此调参是一场同时涉及控制器和被控对象的实验。

二阶系统三种整定的阶跃响应对比图。高增益曲线会越过设定点并振荡一段时间才稳定。整定良好的曲线上升很快、只有轻微超调、并且很快稳定。低增益曲线上升缓慢,而且从不超调。
阻尼决定阶跃响应的形状:增益过大就超调并振铃,过小则迟钝,而平衡的整定能快速稳定。 下载 SVG

算法

  1. 按固定间隔读取测量值并计算误差。
  2. 用实际的时间步长累积一个有界的积分项。
  3. 由测量值或误差估计微分项,并施加相应的滤波。
  4. 把三项加权结果相加,并限制到执行器范围内。
  5. 施加指令、保存上一个样本,并记录各项指标。
  6. 当控制模式或被控对象发生明显变化时,重置积分项和历史记录。

源代码

这个实现包含一个简单的抗积分饱和条件:

float updatePid(float setpoint, float measured, float dt) {
  const float error = setpoint - measured;
  const float derivative = (error - previousError) / dt;
  const float candidateIntegral = integral + error * dt;
  const float raw = kp * error + ki * candidateIntegral + kd * derivative;

  const float output = constrain(raw, outputMin, outputMax);
  if (raw == output) integral = candidateIntegral;
  previousError = error;
  return output;
}

产品级的控制器还会为无效测量、定时器溢出、模式切换和执行器故障定义相应的行为。

假设与硬件差异

这里的被控对象是一个干净的二阶模型,质量、阻尼和延迟都由滑块设定——而不是一台带摩擦、带死区、扭矩随转速衰减、驱动器还会发热的真实电机。采样在构造上就是固定的,因此微分项始终表现良好;可是在 Arduino 上,delay() 或其他阻塞式工作会让间隔产生抖动,即使增益一点没改,D 项也会出问题。执行器饱和被建模为硬限幅并提供了抗饱和,但真实系统还有电流限制、电源压降和温升,它们会在运行中改变这个上限。先在这里把形状调好,再到硬件上去验证——在那里被控对象只是近似已知。

电路图

反馈传感器报告的是实际输出;它不能替代限流或硬件安全停机。控制器把设定点与调理后的传感器读值作比较,然后通过一个按负载额定选型的 PWM 级去驱动执行器。

闭环 PID 反馈回路的框图。设定点进入求和节点,得到的误差送入 PID 控制器,其输出驱动执行器和 PWM 级,再由它驱动被控对象,传感器测量被控对象的输出并以负号反馈回求和节点。
闭环 PID 回路:传感器把从被控对象输出回到求和节点的路径闭合,在那里反馈从设定点中被减去。 下载 SVG

引导实验

读到超调,跟刻意把超调造出来不是一回事。下面每个实验 都只需要几分钟,而且各自只隔离一个效应。

1. 找出临界增益

把 Ki 和 Kd 设为零。提高 Kp,直到输出以恒定幅度振荡—— 既不增大也不衰减。记下增益(Ku)和振荡周期(Tu)。

首次整定只需要这两个数字:

控制器 Kp Ki Kd
PID(经典) 0.6 Ku 1.2 Ku / Tu 0.075 Ku Tu
PID(无超调) 0.2 Ku 0.4 Ku / Tu 0.066 Ku Tu

把这些值填进去对比。经典那一行很激进,会超调 20–40%;第二行落得稳而且不带超调,只是花的时间更长。两者都不算“正确”——它们是对不同要求给出的不同答案,而这正是重点。

2. 亲眼看积分饱和发生

把执行器限幅设得很低——大约在量程的 20%——然后给一个很大的设定点阶跃。 观察控制输出曲线:它立刻饱和并停在那里,而积分项还在不断累积它根本无力施加的误差。当输出终于到达设定点时,那些储存下来的作用力一次性释放出来,系统会冲过很远。

现在提高执行器限幅,用同样的增益再跑一遍。超调基本上消失了。 控制器本身一点没变——这就是要点。饱和是控制器与饱和执行器之间相互作用的属性,而不是增益的属性。

3. 证明杀死回路的是滞后而不是噪声

保持增益不变,把采样间隔从最低值开始逐级提高。响应在图表看起来还 不算噪声的时候就先变差了:超调变大,然后出现振荡,接着变得不稳定。

采样间隔 用原本不错的整定会看到
5 ms 干净,跟整定一致
20 ms 超调略多
50 ms 出现明显振铃
100 ms 持续振荡
200 ms 不稳定

这就是为什么把机器人回路里的一个 delay() 去掉,往往比任何程度的调参都更能改善跟踪性能。过期的信息无法靠增益找回来。

4. 往微分项里灌噪声

先在 Kd 为零时提高扰动幅值,再提高 Kd。控制输出曲线在输出曲线 之前很久就变得参差不齐——你看到的就是微分运算在放大高频成分,它本来就该如此。

正是这种行为让人得出“D 项没用”的结论并把它设成零。真正的修法在上游: 对测量值做滤波,或者对微分项本身做滤波。

你应该观察到什么

设置 预期形状 如果你看到的不是这样
只用 Kp,取值低 缓慢上升,稳定在设定点之下 —
只用 Kp,取值高 超调、振铃、衰减 振荡不断增大说明你已经越过 Ku
Kp + Kd 快速上升,超调很小,稳态偏差很小 输出参差说明 D 项在放大噪声
Kp + Ki 精确到达设定点,较慢 冲过头说明存在饱和或 Ki 太大
完整 PID 快,超调极小,无偏差 —

只有 P、D 而没有 I 时的稳态偏差值得刻意造出来看一次。它最清楚地 演示了积分项到底是为了什么:比例作用必须有一个非零误差才能产生任何输出, 所以它必然会停在稍微差一点的位置。

硬件落地

在这里找到的增益是一个起点,而不是可以直接搬运的东西。能够完美搬运的是 整套流程;搬不过去的是那些数字,因为它们描述的是这里的被控对象。

这个实验台 真实机器人
采样间隔是精确的 除非你测量 dt 并把它传进去,否则会有抖动
被控对象是干净的二阶模型 摩擦、死区、随转速衰减的扭矩
执行器限幅是硬限幅 还有电流限制、电源压降和温升
不加就有传感器噪声 永远有噪声,而且很少是高斯的
被控对象永远不变 电池电压、负载和温度都会改变它

最后一行在实际中造成的困惑最多。一组在全新电池上完美的整定,到了快没电的 电池上就会变得迟钝,因为同一条指令现在产生的扭矩更少了。这并不是方法失效—— 增益是被控对象的属性,而被控对象变了。专业的做法是在下面加一层速度环, 或者做增益调度。把如何整定 PID 控制器的完整流程 走一遍,然后把它带到循迹实验台去,在那里被控对象会反击。

硬件清单

元器件

  • 带稳定定时器的单片机
  • 可测量的被控对象,例如直流电机或舵机
  • 编码器、电位器或其他反馈传感器
  • 按执行器额定值选型的输出驱动器
  • 稳压电源和急停开关

探索关联图谱

哪里用到这个模拟器

以这个实验台为基础的项目、学习路线和教程。

继续搭建

下载资源

完成项目时可以参考本页上的这些资料。可下载的项目包只会在其源文件和版本发布之后才会添加。

常见问题

常见问题解答

应该先整定哪一项?

先把积分增益和微分增益设为零。提高比例增益,直到响应够用但带有振荡,然后加入微分阻尼。最后才加积分增益,而且只在仍然存在可重复的稳态误差时才加。一条常用的经验法则是:P 带来速度,D 减少超调,I 消除偏差——按这个顺序,一次加一项。

如何防止 PID 控制器超调?

超调通常来自过强的比例或积分作用。先降低比例增益,再提高微分增益,让趋近过程得到阻尼。如果超调只在执行器达到极限之后才出现,那么原因是积分饱和而不是增益,你应该对积分项做限幅。

为什么我的 PID 控制器会振荡?

持续的振荡几乎总是意味着比例增益对这个回路来说太高,或者微分项太弱,不足以提供阻尼。把比例增益降低大约一半,再加入微分增益。振荡也可能来自运行太慢或间隔不稳定的控制回路,这会让微分项变得不可靠。

什么是积分饱和,如何防止?

积分饱和发生在执行器已经饱和——电机全速运转、阀门全开——而累积的积分误差却还在不断增大的时候,于是当误差最终反向时,控制器会严重超调。防止的方法有限幅法(在输出饱和期间停止累加积分)和反算法(利用请求输出与实际输出之差,把积分值逐步泄放下来)。

PID 回路需要跑多快?

回路的采样速度应该比它所控制的系统快好几倍,而且间隔要稳定。在单片机上,要避免长时间的阻塞延迟:即使增益不变,间隔多变或过慢的回路也会改变实际起作用的积分项和微分项,这是整定效果差的一个常见隐藏原因。

PID 可以只用 P 和 D 两项吗?

可以。当可以接受很小的稳态误差、又想避免积分饱和时,PD 控制(不含积分)很常见;而 PI 控制(不含微分)适合信号噪声大的场合,因为微分项会放大噪声。只使用问题真正需要的那几项,而不是一律运行完整的 PID。

手动整定和 Ziegler–Nichols 法有什么区别?

手动整定是一边观察响应、一边一次调整一个增益,直观又安全,适合学习。Ziegler–Nichols 是一种基于公式的方法,它根据持续振荡的临界点推导出增益;它更快,但往往偏激进,所以它给出的结果通常只是一个起点,还要再手动微调。

延伸阅读

参考资料

权威资料,帮助你越过本模拟器有限的教学模型,进一步深入学习。