在工业自动化领域,温度控制一直是个经典课题。最近我在一个烘箱温度控制项目中尝试用西门子S7-200 PLC实现了完全自主编写的PID算法,不使用PLC自带的标准PID指令。这个方案最大的特点是用数字量输出来控制加热器通断,通过调节占空比实现温度精确控制。
传统做法是直接调用PLC的PID功能块,但这次我选择自己编写比例、积分、微分三环节的算法。这样做虽然增加了编程复杂度,但带来了三个显著优势:第一,可以完全掌控算法细节,针对特定被控对象优化参数;第二,避免了标准PID功能块的一些限制,比如采样周期固定等问题;第三,数字量输出省去了模拟量模块的成本,特别适合中小型温控场合。
自主编写PID算法首先要吃透三个环节的数学本质。比例环节(P)即时响应偏差,积分环节(I)消除静差,微分环节(D)预测变化趋势。在离散系统中,PID算法可以表示为:
code复制输出 = Kp×e(k) + Ki×Σe(j) + Kd×[e(k)-e(k-1)]
其中e(k)是当前采样时刻的偏差(设定值-实际值),Σe(j)是历史偏差累加,[e(k)-e(k-1)]是偏差变化率。在PLC中实现时,需要特别注意以下几点:
用数字量输出做温度控制,本质上是脉宽调制(PWM)技术。PLC通过快速开关控制加热器通断,通过调节通断时间比例来等效连续控制。具体实现时:
例如,如果PID输出为70%,则在10秒周期内加热器导通7秒,断开3秒。这种方法的控制精度取决于基础周期的选择,周期太短会导致继电器频繁动作,太长则控制粗糙。
在S7-200中需要先定义以下关键变量:
code复制// 输入变量
PV_R : REAL; // 过程变量(温度测量值)
SP_R : REAL; // 设定值
// PID参数
Kp : REAL := 2.0; // 比例系数
Ti : REAL := 120.0; // 积分时间(秒)
Td : REAL := 30.0; // 微分时间(秒)
// 中间变量
Err : REAL; // 当前偏差
Err_Last : REAL; // 上次偏差
Integral : REAL; // 积分累加值
Derivative : REAL; // 微分值
// 输出
Output : REAL; // 0.0-100.0%
Q0.0 : BOOL; // 实际输出触点
初始化时要特别注意清零历史数据和设置合理的输出限幅:
code复制Integral := 0.0;
Err_Last := 0.0;
Output := 0.0;
在定时中断组织块(如OB35)中编写核心算法:
code复制// 计算偏差
Err := SP_R - PV_R;
// 比例项
P_Term := Kp * Err;
// 积分项(带抗饱和)
IF ABS(Output) < 100.0 THEN
Integral := Integral + (Kp/Ti)*Err*T_sample;
END_IF;
// 微分项(采用测量值微分)
Derivative := (Kp*Td)*(PV_Last - PV_R)/T_sample;
PV_Last := PV_R;
// 合成输出
Output := P_Term + Integral + Derivative;
// 输出限幅
IF Output > 100.0 THEN Output := 100.0; END_IF;
IF Output < 0.0 THEN Output := 0.0; END_IF;
// 转换为PWM输出
IF (TON_Q0_0.PT/100)*Output >= TON_Q0_0.ET THEN
Q0.0 := 0;
ELSE
Q0.0 := 1;
END_IF;
对于这种自主PID算法,我推荐采用经典的试凑法:
注意:对于温度这种大滞后系统,实际使用的Kp通常比计算值小20-30%,Ti要适当延长
由于采用数字量输出,还需要特别注意:
可能原因及对策:
实测案例:某烘箱温度波动±3℃,发现是热电偶信号干扰导致。在程序中加入一阶滞后滤波后(α=0.2),波动减小到±0.8℃。
优化方法:
解决方法:
在基本PID稳定后,可以加入简单的自整定逻辑:
code复制IF ABS(SP_R - PV_R) > 20.0 THEN
// 大偏差区间
Kp_temp := Kp * 1.5;
Ti_temp := Ti * 0.8;
ELSE
// 小偏差区间
Kp_temp := Kp;
Ti_temp := Ti;
END_IF;
更完善的抗积分饱和逻辑:
code复制IF (Output >= 100.0 AND Err > 0) OR (Output <= 0.0 AND Err < 0) THEN
// 不积分
ELSE
// 正常积分
Integral := Integral + (Kp/Ti)*Err*T_sample;
END_IF;
对于需要按特定温度曲线运行的场景,可以设计一个配方表:
code复制// 配方数据结构
TYPE Recipe :
STRUCT
Setpoint : REAL;
HoldTime : TIME;
END_STRUCT;
END_TYPE
VAR
Recipes : ARRAY[1..10] OF Recipe;
CurrentStep : INT;
END_VAR
在烘箱项目中实测,这套自主PID算法最终将控制精度稳定在±0.5℃以内,完全满足工艺要求。相比标准PID指令,自主编写的算法响应更快,超调更小,特别是在设定值变化较大时表现更优。