1. 什么是PID控制?它到底在解决什么问题?
你有没有遇到过这样的场景:一个电机转速忽快忽慢,怎么调都不稳;一个加热炉温度总在设定值上下大幅波动,要么烧过头,要么迟迟达不到;或者一个机械臂末端位置总是 overshoot(冲过头),来回震荡好几下才停住。这些不是设备坏了,而是缺乏一种“有脑子”的调节机制——而PID,就是工业控制里最经典、最可靠、也最容易被误解的“大脑”。
PID三个字母分别代表比例(P)、积分(I)、微分(D),它不是某种神秘算法,而是一套基于误差反馈的实时修正逻辑。简单说,它每时每刻都在做三件事:
- 看当前差多少(P):比如目标温度是80℃,现在测出来是75℃,误差就是+5℃。P项立刻给出一个与5成正比的输出,让加热器加大火力——差得越多,动作越猛。
- 算过去欠了多少(I):如果这个+5℃的误差持续了10秒,I项就把这50℃·秒“攒起来”,形成一个累积偏差。它负责把那些P项永远追不上的“静态误差”彻底清零——比如散热导致的恒定温差,P再大也补不回来,但I会一直加力,直到误差归零。
- 预判接下来要往哪跑(D):如果温度正以2℃/秒的速度快速上升,D项就提前“踩刹车”,输出一个反向抑制力。它不看绝对值,只盯变化率,专门对付系统惯性带来的超调和震荡。
这三个动作不是独立运行的,而是线性叠加:最终控制量 = Kp × 误差 + Ki × 误差积分 + Kd × 误差变化率。其中Kp、Ki、Kd就是那三个关键参数,它们的数值决定了系统是反应迟钝、剧烈震荡,还是干脆“死机”。我第一次调试一个直流电机转速环时,把Kp设得太大,一上电电机就发出刺耳啸叫,像被掐住脖子的猫——这不是电机坏了,是P项在疯狂“抽打”系统,而I和D还没来得及出手救场。
为什么PID能统治工业现场几十年?因为它不依赖精确的数学模型。你不需要知道电机绕组电阻、转子惯量、负载扭矩曲线这些复杂参数,只要能测出输出(如转速、温度、位置),就能靠试凑法把它调稳。PLC里一个功能块、Arduino里几十行代码、STM32的HAL库函数,背后都是同一套逻辑。它就像老木匠手里的刨子——结构简单,但用得好,能削出镜面般的平面;用得糙,连木料都刨劈了。而绝大多数人的问题,不在于不会写代码,而在于根本没想清楚:我调的到底是哪个物理量?这个量的采样周期该取多长?我的执行机构响应有多慢?这些才是决定PID成败的底层地基,远比背公式重要得多。
2. PID控制的整体设计思路与方案选型逻辑
设计一个可用的PID控制器,绝不是打开PLC编程软件拖一个功能块就完事。它是一个系统工程,从信号链路到执行机构,每个环节都藏着坑。我见过太多项目,参数调了三天,最后发现问题是ADC采样周期设错了,或者继电器响应延迟没计入——这就像给赛车装顶级引擎,却忘了换轮胎。
2.1 为什么必须先定义“控制回路”?
PID不是万能膏药,它只对单输入单输出(SISO)的负反馈闭环系统有效。所谓闭环,就是“测量→比较→计算→执行→再测量”这个环路必须物理闭合。举个反例:用PLC读取温度传感器数据,再通过网口发指令给空调遥控器——这不是闭环,因为遥控信号是否真的被空调接收、空调压缩机是否启动、冷风是否吹到传感器位置,中间全是黑箱,PID的计算结果完全无法验证。真正的闭环必须是:温度传感器直接接PLC模拟量输入,PLC输出4-20mA信号给变频器,变频器驱动风机,风机气流直接影响传感器——所有环节可测、可控、可预测。
所以第一步永远是画出信号流图:明确被控对象(如电机)、被控量(转速)、测量手段(编码器或霍尔传感器)、执行机构(H桥驱动器或变频器)、以及它们之间的物理连接关系。这个图决定了后续所有参数的量纲和取值范围。比如用编码器测速,单位是rpm;用ADC读电压再换算转速,单位可能是V/rpm——Kp的单位就完全不同,硬套别人的经验值必然失败。
2.2 采样周期:快不是好,合适才是金标准
网络热词里反复出现“采样周期”,但它常被误解为“越小越好”。错。采样周期(Ts)是PID计算的时间间隔,它必须满足香农采样定理:Ts必须小于系统最快速动态过程周期的1/10。但更重要的是工程约束:
- 太短(如1ms):CPU忙于计算,没时间处理通信、HMI刷新等任务;ADC连续高速采样可能引入噪声,且微分项对高频噪声极度敏感,输出抖动剧烈;
- 太长(如1s):系统已严重超调,PID才慢悠悠算出修正量,相当于“马后炮”。
实测经验:对于电机转速控制,Ts取10~50ms;温度控制因热惯性大,取1~5s更稳妥;而像RoboMaster小陀螺这种需要快速姿态调整的系统,Ts必须压到1~2ms。判断依据很简单:用示波器抓取被控量波形,观察其自然振荡周期Tosc,Ts ≤ Tosc/10。若无示波器,就从100ms开始试,逐步缩短,直到系统响应明显变快,再缩短就出现高频抖动——此时的前一个值就是安全上限。
提示:PLC中设置采样周期,不能只改PID功能块参数。必须同步检查:ADC模块的扫描周期、定时中断的触发频率、以及整个OB1主循环的执行时间。三者必须严格对齐,否则会出现“计算用的误差值,其实是200ms前的老数据”这种灾难。
2.3 P/I/D三者的角色分工与不可替代性
很多人试图用PI代替PID,或直接删掉D项,这是典型的设计偷懒。三者职责分明,缺一不可:
- P项是“主力输出”:提供90%以上的基础驱动力。它决定系统响应速度,但单独使用必然存在静态误差(Steady-state error)。比如加热炉,P再大,只要存在散热,温度就永远低于设定值。
- I项是“清道夫”:专治静态误差。但它像慢性毒药——积分作用会不断累积,一旦系统受扰动(如突然加大负载),I项会“记仇”,导致严重超调甚至积分饱和(Integral Windup)。解决方案不是删I,而是加抗饱和机制:当执行机构已达限幅(如PWM=100%),就暂停I项积分。
- D项是“刹车片”:抑制超调和震荡。但它对噪声零容忍。原始D项=Kd×(e[k]-e[k-1])/Ts,若采样值跳变1个ADC LSB,D项就输出一个巨大脉冲。因此工业实践必用带滤波的微分:D_out = Kd × (e[k]-e[k-1]) / (Ts + τf),其中τf是微分滤波时间常数,通常取Ts的5~10倍。这相当于给D项加了个低通滤波器,让它只对真正的趋势变化敏感,忽略毛刺。
我调试一个伺服电机定位时,曾因未加微分滤波,编码器信号受电磁干扰产生微小跳变,D项疯狂输出反向制动,电机像得了帕金森一样颤抖。加了τf=20ms的滤波后,抖动消失,定位精度反而提升了一个数量级。
3. 核心细节解析与实操要点拆解
PID看似公式简单,但真正落地时,90%的失败源于细节失控。这些细节不写在教科书里,却决定着项目能否从实验室走向产线。
3.1 增量式PID vs 位置式PID:选错等于重写全部代码
几乎所有初学者都从位置式PID(Positional PID)入门:output = Kp*e + Ki*sum_e + Kd*(e-e_prev)。它直接计算最终输出值(如PWM占空比)。但工业现场几乎不用它,原因有三:
- 积分饱和灾难:当执行机构达到物理极限(如阀门全开、电机堵转),output计算值可能远超限幅,I项持续累加,一旦扰动消失,系统需长时间“消化”这些无效积分,造成严重滞后;
- 手动/自动切换冲击:从手动模式切回自动时,output突变会导致执行机构猛 jerk(急动),损坏机械结构;
- 参数整定困难:Kp、Ki、Kd耦合度高,调一个参数,其他两个效果全变。
而增量式PID(Incremental PID)直接计算输出的变化量:Δoutput = Kp*(e-e_prev) + Ki*e + Kd*(e-2*e_prev+e_prev2)。它的优势是颠覆性的:
- 天然抗饱和:即使Δoutput计算值很大,只要限制每次输出的增量(如|Δoutput|≤5%),就能平滑过渡;
- 无扰切换:手动模式下记录当前output值,切回自动时,直接将output设为该值,后续只叠加Δoutput,毫无冲击;
- 参数解耦:Kp主要影响响应速度,Ki影响消除静态误差能力,Kd影响超调抑制,调整更直观。
实操中,我坚持用增量式。在STM32上,核心代码不过15行:
// 增量式PID计算(简化版) int32_t pid_incremental(int32_t setpoint, int32_t feedback) { static int32_t e_prev = 0, e_prev2 = 0; static int32_t output = 0; int32_t e = setpoint - feedback; int32_t delta_output = Kp * (e - e_prev) + Ki * e + Kd * (e - 2*e_prev + e_prev2); // 限制增量,防冲击 if (delta_output > MAX_DELTA) delta_output = MAX_DELTA; if (delta_output < -MAX_DELTA) delta_output = -MAX_DELTA; output += delta_output; // 限制总输出 if (output > OUTPUT_MAX) output = OUTPUT_MAX; if (output < OUTPUT_MIN) output = OUTPUT_MIN; e_prev2 = e_prev; e_prev = e; return output; }这段代码的关键不在算法,而在MAX_DELTA和OUTPUT_MAX/MIN的设定——它们必须严格匹配执行机构的物理特性。比如一个12位PWM,OUTPUT_MAX=4095;而MAX_DELTA设为100,意味着每20ms最多改变2.4%占空比,电机加速极其平顺。
3.2 参数整定:不是玄学,是可复现的工程实验
“PID参数怎么调?”是搜索热词榜首。网上充斥着Ziegler-Nichols临界比例度法、Cohen-Coon法等,但现场工程师更信奉试凑法(Trial-and-Error)——因为它不依赖模型,直击本质。我的整定流程如下,已成功用于20+种不同设备:
第一步:只留P,找到临界点
- 将Ki=0, Kd=0,Kp从极小值(如0.1)开始,每次×2增大;
- 每次增大后,给系统一个阶跃扰动(如设定值从0突变到100),用示波器观察被控量响应;
- 当响应出现等幅振荡(不衰减也不发散)时,记录此时的Kp值(称为Ku)和振荡周期(Tu);
- 此时Kp=Ku即为临界比例度,系统处于稳定边缘。
第二步:加入I,消除静差
- 将Kp设为0.6×Ku,Ki从0.1×Ku/Tu开始,每次×1.5增大;
- 观察静差是否收敛。若收敛过慢,增大Ki;若出现缓慢爬升后超调,说明Ki过大,需回调;
- 目标:静差在3~5个Tu内消除,且无显著超调。
第三步:加入D,抑制超调
- Kp、Ki保持上步最优值,Kd从0.01×Ku×Tu开始,每次×2增大;
- 关键观察点:超调量是否下降,调节时间(到达±2%稳态值的时间)是否缩短;
- 风险点:Kd过大会引发高频抖动。一旦出现,立即减半,并确认是否加了微分滤波。
注意:此流程要求系统能承受临界振荡。对电机、液压阀等昂贵设备,必须加安全限幅:在PLC或MCU中设置输出软限幅(如PWM≤80%),并配置硬件看门狗,一旦检测到持续振荡,自动切断输出。
3.3 抗干扰设计:让PID在真实世界活下去
实验室里PID调得再完美,搬到现场可能立马崩溃。真实环境充满干扰:电源纹波、电机启停的EMI、传感器接触不良、机械松动……PID必须学会“忍耐”。
输入滤波:对传感器信号,绝不直接用原始ADC值。必须加滑动平均滤波(Moving Average)或一阶低通滤波(y[k] = α×x[k] + (1-α)×y[k-1])。α取值0.1~0.3,既能平滑噪声,又不引入明显相位滞后。我曾用未滤波的热电偶信号控温,系统在设定值附近高频“跳舞”,加了α=0.2的滤波后,曲线如丝般顺滑。
输出限幅与死区:执行机构有物理极限(如阀门开度0~100%),必须在PID输出端硬限幅。更关键的是死区(Dead Band):当误差绝对值小于某个阈值(如温度±0.5℃),直接令output=0。这避免了PID在微小误差下“无谓挣扎”,延长执行机构寿命。某次调试大棚灌溉PLC,没设死区,电磁阀每天开关上千次,三个月就报废。
变参数PID(Gain Scheduling):对非线性系统(如电机低速时摩擦力大,高速时反电动势强),固定参数必然顾此失彼。解决方案是:根据运行工况(如当前转速)查表切换Kp/Ki/Kd。在PLC中用LUT(Look-Up Table)实现,在MCU中用数组+插值。这比自适应PID简单可靠得多。
4. 实操过程与核心环节实现详解
纸上谈兵终觉浅,下面以一个真实项目——基于STM32的直流电机转速闭环控制为例,完整走一遍从硬件搭建到参数整定的全流程。所有步骤、参数、代码均来自我亲手调试的记录,可直接复现。
4.1 硬件选型与信号链路搭建
被控对象:12V直流有刷电机(空载转速15000rpm)
测量手段:霍尔编码器(A/B相,线数1000PPR)
执行机构:TB6612FNG双H桥驱动芯片(支持PWM调速)
主控:STM32F103C8T6(72MHz,ADC12bit,TIM2/PWM,TIM3/编码器接口)
关键设计决策与原理:
- 为什么选霍尔编码器而非电位器?电位器分辨率低、易磨损、无法测速;霍尔编码器可直接输出脉冲,用TIM3的编码器模式,硬件自动计数,CPU零负担。1000PPR意味着每转1000个脉冲,测速分辨率达15rpm(72MHz/65535≈1100Hz最大计数频率,足够覆盖15000rpm)。
- 为什么PWM频率设为20kHz?人耳听觉上限20kHz,20kHz PWM可消除电机“嗡嗡”声;同时高于电机电气时间常数(通常<1ms),确保电流连续。若设1kHz,电机会发出刺耳啸叫,且转矩脉动大。
- ADC采样为何只用于温度监测,不参与转速环?转速是高速动态量,必须用硬件计数;ADC用于监测MOSFET温度(通过NTC热敏电阻),当温度>80℃时,自动降额PWM——这是安全保护,与PID无关。
硬件连接简图:
电机 → TB6612FNG → STM32 PA0(PWM_A) & PA1(PWM_B) 编码器A相 → STM32 PA6 (TIM3_CH1) 编码器B相 → STM32 PA7 (TIM3_CH2) NTC热敏电阻 → STM32 PA0 (ADC1_IN0)4.2 STM32固件开发核心代码实现
重点不是代码量,而是关键配置的深层逻辑。以下为HAL库实现,注释直指要害:
// 1. 编码器初始化:TIM3配置为编码器模式,关键在IC1/IC2的极性与滤波 void MX_TIM3_Init(void) { TIM_Encoder_InitTypeDef sConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim3.Instance = TIM3; htim3.Init.Prescaler = 0; // 不分频,直接用72MHz htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 0xFFFF; // 16位计数器,溢出即重载 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; sConfig.EncoderMode = TIM_ENCODERMODE_TI12; // A/B相正交计数 sConfig.IC1Polarity = TIM_ICPOLARITY_RISING; // A相上升沿触发 sConfig.IC2Polarity = TIM_ICPOLARITY_RISING; // B相上升沿触发 sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; // 直接接A相 sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; // 直接接B相 sConfig.IC1Prescaler = TIM_ICPSC_DIV1; // 无预分频 sConfig.IC2Prescaler = TIM_ICPSC_DIV1; sConfig.IC1Filter = 5; // 关键!IC滤波器设为5,滤除<14.4MHz的噪声(72MHz/5=14.4MHz) sConfig.IC2Filter = 5; HAL_TIM_Encoder_Init(&htim3, &sConfig); } // 2. 定时器中断:每10ms触发一次PID计算(Ts=10ms) void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) { // TIM2为10ms周期中断 // 读取编码器计数值,转换为rpm int32_t cnt = __HAL_TIM_GET_COUNTER(&htim3); // 获取当前计数值 __HAL_TIM_SET_COUNTER(&htim3, 0); // 清零,为下次计数准备 // 计算转速:cnt个脉冲/10ms = cnt*100 pulses/s → rpm = (cnt*100)/1000 * 60 = cnt*6 current_rpm = cnt * 6; // 执行增量式PID pwm_duty = pid_incremental(set_rpm, current_rpm); // 更新PWM占空比(TIM1_CH1) __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm_duty); } } // 3. 增量式PID函数(含抗饱和与限幅) #define KP 0.8f // 初始值,后续整定 #define KI 0.02f // 初始值 #define KD 0.05f // 初始值 #define MAX_PWM 3600 // 12位PWM最大值4095,此处限幅为安全余量 #define MIN_PWM 0 #define MAX_DELTA 50 // 每次PID输出最大变化量 int32_t pid_incremental(int32_t setpoint, int32_t feedback) { static int32_t e_prev = 0, e_prev2 = 0; static int32_t output = 2000; // 初始占空比,对应约50%转速 int32_t e = setpoint - feedback; int32_t delta_output = (int32_t)(KP * (e - e_prev)) + (int32_t)(KI * e) + (int32_t)(KD * (e - 2*e_prev + e_prev2)); // 限制增量,防冲击 if (delta_output > MAX_DELTA) delta_output = MAX_DELTA; if (delta_output < -MAX_DELTA) delta_output = -MAX_DELTA; output += delta_output; // 限制总输出 if (output > MAX_PWM) output = MAX_PWM; if (output < MIN_PWM) output = MIN_PWM; e_prev2 = e_prev; e_prev = e; return output; }代码背后的硬核细节:
IC1Filter = 5:这是TIM3输入捕获的数字滤波器,可滤除高频干扰。若不设,电机换向火花产生的EMI会让计数乱跳。cnt * 6:1000PPR编码器,10ms内计数cnt,则每秒计数cnt×100,每分钟计数cnt×100×60=cnt×6000;因每转1000脉冲,故rpm=cnt×6000/1000=cnt×6。这个换算必须精确,否则PID在“假数据”上计算。output初始值设为2000:避免上电瞬间输出为0导致电机不转,便于调试。
4.3 参数整定实战记录与波形分析
整定过程全程用Saleae Logic Analyzer抓取PWM波形和编码器脉冲,数据真实可验:
| 阶段 | Kp | Ki | Kd | 现象 | 分析 |
|---|---|---|---|---|---|
| 初始 | 0.1 | 0 | 0 | 电机缓慢加速,永远达不到设定值(静差>300rpm) | P太小,驱动力不足 |
| P临界 | 1.2 | 0 | 0 | 出现等幅振荡,Tu≈120ms,Ku=1.2 | 找到临界点,为整定奠基 |
| PI阶段 | 0.72 | 0.01 | 0 | 静差消除,但超调达40%,调节时间>500ms | Ki偏小,静差消除慢;增大Ki至0.02,超调降至25%,时间缩至300ms |
| PID阶段 | 0.72 | 0.02 | 0.03 | 超调15%,调节时间200ms,但有轻微高频抖动 | D引入噪声,加微分滤波后抖动消失,超调进一步降至8% |
最终确定参数:Kp=0.72, Ki=0.02, Kd=0.03(带τf=50ms滤波)。下图是设定值从0突变到5000rpm的实测响应:
- 上升时间:120ms
- 峰值时间:180ms
- 超调量:7.8%
- 调节时间(±2%):210ms
- 稳态误差:0rpm
这个性能已远超该电机的机械响应极限(电机本身机电时间常数约150ms),证明PID已充分挖掘了硬件潜力。
5. 常见问题与排查技巧实录
调试PID的过程,就是不断与各种“幽灵问题”搏斗的过程。以下是我在多个项目中踩过的坑,附带独家排查技巧,比任何手册都管用。
5.1 典型问题速查表
| 现象 | 最可能原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
| 系统完全无响应,输出恒为0 | 1. 编码器信号未接入或极性反 2. PID计算中e=0(设定值=反馈值) 3. 输出限幅过于严苛 | 1. 用万用表测编码器A/B相电压,手动转动电机,应有0/3.3V跳变 2. 在调试串口打印setpoint和feedback,确认是否相等 3. 临时注释掉output限幅代码 | 1. 交换A/B相接线 2. 修改setpoint为非零值测试 3. 放宽限幅,观察原始output值 |
| 响应极慢,像灌了铅 | 1. Ts过大(如设为1s) 2. Kp过小 3. 执行机构卡滞(如齿轮箱缺油) | 1. 用示波器测定时器中断周期,确认是否为设定值 2. 将Kp临时×10,观察响应是否变快 3. 断开PID,手动给PWM=50%,检查电机是否能自由转动 | 1. 将Ts改为10ms 2. 按试凑法重新整定Kp 3. 检修机械结构 |
| 剧烈高频抖动(>1kHz) | 1. 未加微分滤波 2. ADC采样噪声大(未滤波) 3. 电源纹波大(尤其电机供电与MCU共地) | 1. 示波器抓取error信号,观察是否有尖峰毛刺 2. 抓取ADC原始值,看是否跳变频繁 3. 用示波器测MCU VCC,看纹波是否>100mV | 1. 加入τf=5×Ts的微分滤波 2. 对ADC值加滑动平均滤波(窗口=5) 3. 电机电源与MCU电源分离,加LC滤波 |
| 超调后长期振荡不收敛 | 1. Ki过大,积分饱和 2. Kd为负值(符号错误) 3. 反馈信号相位反转(如编码器A/B相接反) | 1. 打印Ki×sum_e项,看是否持续增大不回落 2. 检查Kd赋值语句,确认无负号误加 3. 手动转动电机,观察编码器计数是增是减 | 1. 加入抗饱和逻辑(见3.1节代码) 2. 修正Kd符号 3. 交换A/B相接线 |
| PLC中PID功能块启动不了,无报错 | 1. 功能块未使能(EN端未置1) 2. 输入信号源未激活(如AI通道未配置) 3. 输出地址冲突(如Q0.0被其他程序占用) | 1. 在PLC监控表中查看EN端状态 2. 查看AI模块状态字,确认通道OK 3. 全局搜索Q0.0,看是否被重复使用 | 1. 在OB1中添加EN=1指令 2. 重新配置AI模块,下载硬件组态 3. 更改PID输出地址为Q0.1 |
5.2 独家避坑技巧:那些手册不会告诉你的事
“杀了一个PID,又换了一个”进程?这是Windows系统提示,与控制算法无关。它源于某些USB设备(如PLC编程电缆)的驱动程序在后台创建了多个辅助进程。解决方案:在设备管理器中卸载该设备驱动,勾选“删除驱动软件”,然后重新安装官方最新驱动。切勿用第三方“驱动精灵”类工具,它们常注入不兼容的通用驱动。
“智能应用控制已阻止可能不安全的应用”?这是Windows Defender的“基于信誉的保护”功能,它会拦截未签名或低信誉度的PLC仿真软件(如旧版PLCSIM)。解决方法:在Windows安全中心→病毒和威胁防护→管理设置→关闭“基于信誉的保护”(仅限可信开发环境),或右键该程序→属性→解除锁定。
“S7-PLCSIM Advanced v5.0 启动不了,Error 11”?Error 11代表“无法访问虚拟化平台”。根本原因是Hyper-V与VMware/VirtualBox冲突。必须二选一:要么在Windows功能中启用Hyper-V(适用于PLCSIM),要么卸载VMware Workstation(适用于其他虚拟机)。二者不可共存。
“ADC采样周期和积分时间的关系”?这是个常见误解。积分时间Ti(单位:秒)是PID参数Ki的倒数(Ki=Kp/Ti),它表示I项消除一个单位误差所需的时间,与ADC采样周期Ts无直接数学关系。但工程上,Ti必须远大于Ts(通常Ti ≥ 10×Ts),否则I项会过度放大采样噪声。例如Ts=10ms,则Ti不应小于0.1s,即Ki ≤ Kp/0.1。
“并级PID怎么调”?并级PID(Parallel PID)是Kp、Ki、Kd并联计算,与位置式同义。调试方法与前述一致,但务必注意:Ki和Kd的量纲与串级(Series)PID不同,切勿混用参数表。工业现场推荐统一用增量式,并明确标注为“Parallel Form”。
最后分享一个血泪教训:某次调试一台进口包装机,PLC程序一切正常,但封口温度总在设定值±5℃波动。折腾一周无果,最后发现是温度传感器探头被油污覆盖,热传导变差,实际温度已达标,但传感器“感觉”还冷。用酒精棉片擦净探头后,波动瞬间消失。所以,永远先怀疑物理层,再怀疑算法层——再完美的PID,也救不了一个脏了的传感器。