参考资料
几个控制参数
我们要分清“PID 控制器本身”和“整个闭环系统”
- 对于 PID 控制器(你的代码逻辑),它其实只有一个核心输入:误差 $e(t)$
- $e(t) = \text{Set Point} (目标值) - \text{Process Variable} (实际测量值)$。
- 输出:控制量 $u(t)$(比如 PWM 的占空比)。
- 对于整个仿真系统(闭环回路):为了模拟真实世界,仿真器通常有 3 个输入 和 1 个输出:
- 输入 1:设定值 (Set Point, SP) —— 你希望温度达到的度数(如 $120^\circ\text{C}$)。
- 输入 2:测量噪声 (Measurement Noise) —— 模拟传感器的抖动。
- 输入 3:过程扰动 (Process Disturbance) —— 模拟外部环境的变化。
- 输出:实际温度 (Process Variable, PV) —— 传感器最终读到的数值
为什么仿真器里会有“噪声”这个选项
噪声是 PID 算法(尤其是 D 项)的“天敌”。
- 传感器的真实情况:你的 PT100 即使在恒温下,ADC 读数也会有 $\pm0.1^\circ\text{C}$ 的跳动。
- D 项的放大效应:
- $D$ 项是求导(变化率)。
- 如果噪声让温度在 1 毫秒内跳动了 $0.1$ 度,导数就是 $0.1 / 0.001 = 100$!
- 这会导致你的控制输出(PWM)像抽风一样剧烈抖动,即便温度其实很稳定。
所以在真实 CEMS 开发中,我们在把数据传给 PID 之前,必须先经过你思维导图里的“双重滤波算法”(算术平均或一阶滞后),这就是为了干掉噪声。
你在仿真器里尝试开启一点 Noise,然后观察:
- 当你 $D$ 值很小时,曲线还算平滑。
- 当你把 $D$ 调大,你会发现输出信号(通常是底下的那个条)变得非常杂乱。
- 这就是为什么在工业现场,很多工程师宁愿只用 PI 控制,也不轻易开 D 的原因
“扰动 (Disturbance)”又是什么
噪声是“眼睛(传感器)”看花了,而扰动是“身体”被踢了一脚。
- 场景:你的发热片正在稳稳地保持 $120^\circ\text{C}$。
- 扰动:这时候采样泵突然开启,冷烟气快速流过,带走了热量;或者你打开了机箱风扇。
- PID 的任务:它必须立刻感知到这个由于外部干扰导致的温度下降,并迅速加大功率补偿回来。
PID 网页仿真器
|
|
这个仿真器模拟了发热片控温过程:它有热惯性(升温慢)、有散热(自然冷却)、有噪声。
如何使用这个仿真器学习?
当你打开这个网页后,请尝试以下“实验步骤”:
实验 1:感受“静差”
- 将 $K_i$ 和 $K_d$ 设为 0。
- 慢慢调大 $K_p$。你会发现蓝线(实际温度)永远追不上红虚线(目标温度)。
- 原理:因为散热的存在,当误差变小时,$K_p$ 产生的热量正好抵消了散热,温度就不再上升了。
实验 2:感受“积分的力量”
- 在实验 1 的基础上,慢慢调大 $K_i$。
- 你会看到蓝线开始“缓慢但坚定”地向红线靠拢,最终完美重合。
- 副作用:调大 $K_i$ 后,你会发现蓝线冲过了头(超调)。
实验 3:感受“噪声的恐惧”
- 保持一个稳定的 PID 参数。
- 调大 “环境噪声” 滑块。
- 此时再调大 $K_d$。你会发现蓝线变得非常抖动。
- 结论:在有噪声的环境下,$K_d$ 不能开太大,或者需要先对温度进行滤波。
从“网页仿真”到 C 语言的跨越
在 STM32 中,为了让代码整洁、可复用(比如你以后可能同时控制 3 路加热,每路都要一个 PID),我们通常会定义一个 结构体 (Struct)。
|
|
为什么这段 C 代码比网页版更“高级”
- 面向对象思想:通过
PID_Controller结构体,你可以轻松创建Heater_PID、Pump_PID等多个实例。 - 抗饱和机制:专门加入了
IntegralMax,防止系统在长时间达不到目标时产生的“失控”现象。 - 指针传递:使用
*pid指针传递,运行效率极高,符合 STM32 这种嵌入式环境的要求。
PID 控制注意事项
积分饱和—— 最隐蔽的“定时炸弹”
- 现象:你的目标是 $120^\circ\text{C}$,但此时发热片断电了。PID 发现温度没升,积分项($I$)就会疯狂累积。当电源恢复时,累积的巨大积分值会让加热器保持 $100%$ 功率输出,直到温度冲到 $200^\circ\text{C}$ 都降不下来。
- 解决方案:积分限幅。给
Integral设一个上限和下限(比如最大只允许占输出的 $20%$)。
微分突变—— “瞬间心梗”
- 现象:当你突然把目标温度从 $100^\circ\text{C}$ 改为 $150^\circ\text{C}$ 时,误差 $e(t)$ 瞬间产生了一个巨大的台阶。因为微分项 $D$ 计算的是误差的变化率,这会导致输出 $u(t)$ 瞬间产生一个巨大的尖峰脉冲。
- 后果:这个瞬间电流脉冲可能击穿你的 MOSFET 或导致电源保护性重启。
- 解决方案:微分先行 。在计算 $D$ 项时,不计算误差的变化,而是计算测量值(PV)的变化。因为温度本身不会瞬间跳变,这样输出就会平滑得多。
采样周期不固定 —— “算法的基石动摇”
- 现象:PID 的公式是基于时间的 $dt$。如果你在
while(1)循环里随意调用 PID 函数,循环里其他代码执行时间的变化(比如 Modbus 响应久了点)会导致 $dt$ 不稳定。 - 后果:$I$ 和 $D$ 的计算逻辑会完全乱套,系统产生不可预测的震荡。
- 解决方案:定时中断。必须把 PID 计算放在 STM32 的硬件定时器中断里(比如固定每 $100\text{ ms}$ 执行一次)。
传感器断线或短路 —— “逻辑致盲”
- 现象:CEMS 现场震动大,PT100 探头可能脱落。
- 后果:如果探头断了,ADC 读数可能变为 0 或最大值。PID 以为温度极低,会疯狂加热,导致发热片烧毁甚至起火。
- 解决方案:安全保护逻辑。在 PID 运行前加一行:
if (temp < -10 || temp > 300) { Stop_All_Heaters(); }。
进阶版 PID 代码框架(带坑位修复)
|
|
安全监控逻辑
例如,如果功率输出 $100%$ 持续了 5 分钟,温度还没上升 $5^\circ\text{C}$,这说明什么?(可能是发热片坏了或探头掉了)。在这种情况下,程序应该怎么做?(报警并切断电源)。
在工业现场,一套成熟的控制系统,安全监控逻辑的代码量往往比 PID 核心算法还要多。对于 CEMS 这种需要 24 小时无人值守的设备,必须假设“硬件总会坏”,并用软件筑起最后一道防线。
工业级安全监控逻辑
|
|
为什么这才是工业级?
- 容错时间窗口:它不是一发现异常就报错,而是观察一段时间(如 60 秒),避开了传感器抖动或冷风吹过导致的干扰。
- 全链路覆盖:它不仅管传感器,还通过“能量守恒”逻辑监控 MOSFET 和发热片的健康。
- 状态机思维:它将错误分类,方便你在串口屏(HMI)上精准弹出错误代码(如:
E01: 传感器断线,E03: 固态继电器击穿)。
首次调试
真实硬件有热惯性(升温后停不下来)和非线性(电压波动),不像仿真器那么听话。建议采用“渐进式经验法”(也叫试凑法)。不要去算复杂的数学公式,按照下面的步骤操作,既安全又能快速见效:
第一步:安全第一(调试前的硬限制)
在写下第一行 PID_Compute 之前,先在代码里做两个限制,防止把发热片烧红:
- 输出限幅:将
OutputMax先设为 50%(比如 PWM 是 1000,先限制在 500)。等调稳了再放开。 - 采样时间固定:确保你的 PID 函数是在定时器中断(如 100ms 一次)里跑的,这比什么都重要。
第二步:确定比例系数 $K_p$(找“劲头”)
目标:让温度动起来,允许有差距,但不能震荡。
- 将 $K_i$ 和 $K_d$ 设为 0。
- 从一个很小的 $K_p$ 开始(比如 0.1 或 1.0,取决于你的量程)。
- 观察温度曲线:
- 现象 A:温度升得很慢,离目标值还差十万八千里就不动了。—— 调大 $K_p$。
- 现象 B:温度猛冲,过了目标值还在狂跳(震荡)。—— 调小 $K_p$。
- 最终状态:让温度能快速上升到目标值的 80%~90% 左右,曲线平滑,不产生剧烈来回摆动。
第三步:确定积分系数 $K_i$(消“静差”)
目标:把最后那点“够不着”的温差磨平。
- 保持刚才调好的 $K_p$,开始加入微小的 $K_i$(比如从 0.01 开始)。
- 观察曲线:
- 现象 A:温度在 $K_p$ 停下的位置慢悠悠地往目标值蹭,蹭得很久才到。—— 稍微调大 $K_i$。
- 现象 B:温度很快到了目标值,但直接“冲过了头”(超调),然后反复好几次才稳住。—— 调小 $K_i$。
- 最终状态:温度能稳稳地停在目标线上,误差为 0。
第四步:确定微分系数 $K_d$(加“刹车”)
注意:对于发热片这种大惯性系统,$K_d$ 往往可以设为 0。
- 如果你的系统在加入 $K_i$ 后,超调(冲过头)还是无法接受。
- 试着加入一点点 $K_d$(比 $K_i$ 还要小)。
- 作用:它会预测温度上升的趋势,在快到目标时提前减小电流。
核心辅助工具:串口示波器
一定要用图形化软件看曲线! 光看串口打印的数字,你根本分不清是“震荡”还是“正常的漂移”。
- 推荐工具:VOFA+。
- 做法:在程序里
printf("%f,%f\n", Target, CurrentTemp);。 - 看图说话:
- 锯齿太多?—— 滤波没做好或 D 太大。
- 波浪太大?—— P 太大或 I 太大。