在厂务自控系统中,西门子S7-1200/1500系列PLC是绝对的主力。SCL(Structured Control Language,结构化控制语言)作为博途平台的高级语言,语法接近Pascal,非常适合编写复杂的算法和逻辑。本文通过厂务实际案例,带你掌握SCL的核心用法。
💡 学习建议: SCL适合处理数学计算、循环、条件分支等复杂逻辑;简单启停互锁仍推荐LAD(梯形图)。两者可在同一项目中混合使用。
1. SCL语言概述
SCL符合IEC 61131-3标准,核心特点:
- 结构化编程:支持IF...THEN...ELSE、CASE...OF、FOR...TO...DO等高级语法
- 强数据类型:INT、REAL、BOOL、TIME、ARRAY、STRUCT等
- 可创建FB/FC:功能块(FB)带背景数据块,函数(FC)无记忆
2. 电机星三角切换控制
厂务系统中大量使用星三角启动的大功率电机(如空压机、水泵、风机)。下面用SCL实现一个标准的星三角切换FB。
// ============================================
// 功能块:FB_StarDelta
// 功能:电机星三角启动控制
// ============================================
FUNCTION_BLOCK FB_StarDelta
// --- 输入参数 ---
VAR_INPUT
Start : BOOL; // 启动命令
Stop : BOOL; // 停止命令
Overload : BOOL; // 热过载信号
StarTime : TIME := T#5S; // 星形运行时间
TransitionTime : TIME := T#50MS; // 切换延时
END_VAR
// --- 输出参数 ---
VAR_OUTPUT
MainContactor : BOOL; // 主接触器
StarContactor : BOOL; // 星形接触器
DeltaContactor : BOOL; // 三角形接触器
Running : BOOL; // 运行状态
Fault : BOOL; // 故障状态
CurrentState : INT; // 当前状态(0:停止 1:星形 2:切换 3:三角形)
END_VAR
// --- 静态变量 ---
VAR
StarTimer : TON; // 星形运行定时器
TransTimer : TON; // 切换延时定时器
State : INT := 0;
StartEdge : BOOL; // 启动上升沿
StartMem : BOOL;
END_VAR
// --- 代码主体 ---
// 启动上升沿检测
StartEdge := Start AND NOT StartMem;
StartMem := Start;
// 故障处理:过载或停止命令复位
IF Overload THEN
Fault := TRUE;
State := 0;
ELSIF Stop THEN
Fault := FALSE;
State := 0;
END_IF;
// 状态机
CASE State OF
0: // 停止状态
MainContactor := FALSE;
StarContactor := FALSE;
DeltaContactor := FALSE;
Running := FALSE;
IF StartEdge AND NOT Fault THEN
State := 1;
END_IF;
1: // 星形运行
MainContactor := TRUE;
StarContactor := TRUE;
DeltaContactor := FALSE;
Running := TRUE;
StarTimer(IN := TRUE, PT := StarTime);
IF StarTimer.Q THEN
State := 2;
StarTimer(IN := FALSE);
END_IF;
2: // 切换延时(断开星形,等待电弧熄灭)
MainContactor := TRUE;
StarContactor := FALSE;
DeltaContactor := FALSE;
Running := FALSE; // 切换瞬间电机短时失电
TransTimer(IN := TRUE, PT := TransitionTime);
IF TransTimer.Q THEN
State := 3;
TransTimer(IN := FALSE);
END_IF;
3: // 三角形运行
MainContactor := TRUE;
StarContactor := FALSE;
DeltaContactor := TRUE;
Running := TRUE;
IF Stop OR Overload THEN
State := 0;
END_IF;
END_CASE;
CurrentState := State;
// 定时器调用
StarTimer();
TransTimer();
END_FUNCTION_BLOCK
🔑 关键点:
- 状态2的切换延时至关重要,用于灭弧,防止星形和三角形接触器同时导通造成短路
- 切换时间通常设为30-100ms
- 星形运行时间根据电机功率设定,一般为3-10秒
3. 模拟量处理与标定
厂务系统中大量使用4-20mA传感器(温度、压力、湿度、流量等)。PLC通过模拟量输入模块读取0-27648的整数值,需要标定为实际工程值。
// ============================================
// 函数:FC_ScaleAnalog
// 功能:4-20mA模拟量标定
// ============================================
FUNCTION FC_ScaleAnalog : REAL
VAR_INPUT
RawValue : INT; // 原始值 (0-27648)
EngMin : REAL; // 工程量下限
EngMax : REAL; // 工程量上限
RawMin : INT := 0; // 原始值下限(0-20mA用0, 4-20mA用5530)
RawMax : INT := 27648; // 原始值上限
END_VAR
VAR_TEMP
RawReal : REAL;
RawMinReal : REAL;
RawMaxReal : REAL;
SpanRaw : REAL;
SpanEng : REAL;
END_VAR
// 线性标定公式: Eng = ((Raw - RawMin) / (RawMax - RawMin)) * (EngMax - EngMin) + EngMin
RawReal := INT_TO_REAL(RawValue);
RawMinReal := INT_TO_REAL(RawMin);
RawMaxReal := INT_TO_REAL(RawMax);
SpanRaw := RawMaxReal - RawMinReal;
SpanEng := EngMax - EngMin;
IF SpanRaw = 0.0 THEN
FC_ScaleAnalog := EngMin;
ELSE
FC_ScaleAnalog := ((RawReal - RawMinReal) / SpanRaw) * SpanEng + EngMin;
END_IF;
// 限幅
IF FC_ScaleAnalog > EngMax THEN
FC_ScaleAnalog := EngMax;
ELSIF FC_ScaleAnalog < EngMin THEN
FC_ScaleAnalog := EngMin;
END_IF;
END_FUNCTION
// ========== 使用示例 ==========
// 温度传感器:PT100,量程0-100℃
"DB_HVAC".Temp_Actual := FC_ScaleAnalog(
RawValue := %IW64,
EngMin := 0.0,
EngMax := 100.0,
RawMin := 5530 // 4mA对应5530
);
// 压力变送器:0-10bar,对应4-20mA
"DB_CDA".Pressure_Actual := FC_ScaleAnalog(
RawValue := %IW66,
EngMin := 0.0,
EngMax := 10.0,
RawMin := 5530
);
⚠️ 注意: S7-1200/1500的4-20mA对应原始值为0-27648(而非5530-27648)。标定时请根据实际模块型号确认。部分模块支持直接配置为4-20mA量程。
4. PID控制功能块
厂务系统中PID控制无处不在:MAU送风温度、DCC冷冻水阀、冷却塔风机频率等。博途提供现成的PID_Compact指令,但理解其原理并封装自己的PID FB有助于灵活调试。
// ============================================
// 功能块:FB_PID_Basic
// 功能:基本PID控制器(位置式)
// ============================================
FUNCTION_BLOCK FB_PID_Basic
VAR_INPUT
Setpoint : REAL; // 设定值 SP
Actual : REAL; // 实际值 PV
ManualValue : REAL; // 手动输出值
ManualMode : BOOL; // 手动模式
Kp : REAL := 1.0; // 比例增益
Ti : TIME := T#20S; // 积分时间
Td : TIME := T#0S; // 微分时间
CycleTime : TIME := T#100MS; // 采样周期
OutMax : REAL := 100.0;
OutMin : REAL := 0.0;
END_VAR
VAR_OUTPUT
Output : REAL; // 控制输出
END_VAR
VAR
Error : REAL; // 当前误差
P_Term : REAL; // 比例项
I_Term : REAL; // 积分项
D_Term : REAL; // 微分项
LastError : REAL; // 上一次误差
CycleTimer : TON; // 采样定时器
Ti_Real : REAL; // 积分时间(秒)
Td_Real : REAL; // 微分时间(秒)
Cycle_Real : REAL; // 采样周期(秒)
END_VAR
// 时间转换
Ti_Real := TIME_TO_REAL(Ti) / 1000.0;
Td_Real := TIME_TO_REAL(Td) / 1000.0;
Cycle_Real := TIME_TO_REAL(CycleTime) / 1000.0;
// 采样定时器
CycleTimer(IN := TRUE, PT := CycleTime);
IF CycleTimer.Q THEN
CycleTimer(IN := FALSE);
// 计算误差
Error := Setpoint - Actual;
// 比例项
P_Term := Kp * Error;
// 积分项(抗积分饱和)
IF Ti_Real > 0.0 THEN
I_Term := I_Term + Kp * Cycle_Real / Ti_Real * Error;
// 积分限幅
IF I_Term > OutMax THEN
I_Term := OutMax;
ELSIF I_Term < OutMin THEN
I_Term := OutMin;
END_IF;
ELSE
I_Term := 0.0;
END_IF;
// 微分项
IF Td_Real > 0.0 AND Cycle_Real > 0.0 THEN
D_Term := Kp * Td_Real * (Error - LastError) / Cycle_Real;
ELSE
D_Term := 0.0;
END_IF;
LastError := Error;
// 手动/自动切换
IF ManualMode THEN
Output := ManualValue;
I_Term := ManualValue - P_Term - D_Term; // 无扰切换
ELSE
Output := P_Term + I_Term + D_Term;
END_IF;
// 输出限幅
IF Output > OutMax THEN
Output := OutMax;
ELSIF Output < OutMin THEN
Output := OutMin;
END_IF;
END_IF;
END_FUNCTION_BLOCK
5. 报警与事件处理
厂务系统需要完善的报警管理。以下是一个通用报警FB,支持延时触发、自动复位、确认功能。
// ============================================
// 功能块:FB_Alarm
// 功能:通用报警处理(带延时和确认)
// ============================================
FUNCTION_BLOCK FB_Alarm
VAR_INPUT
Condition : BOOL; // 报警条件
Ack : BOOL; // 确认信号
DelayTime : TIME := T#2S; // 触发延时
AutoReset : BOOL := TRUE; // 条件消失后自动复位
END_VAR
VAR_OUTPUT
Alarm : BOOL; // 报警输出
Unacked : BOOL; // 未确认状态
FirstOut : BOOL; // 首出报警(需配合全局变量)
END_VAR
VAR
DelayTimer : TON;
ConditionMem : BOOL;
RisingEdge : BOOL;
AckMem : BOOL;
END_VAR
// 上升沿检测
RisingEdge := Condition AND NOT ConditionMem;
ConditionMem := Condition;
// 延时触发
DelayTimer(IN := Condition, PT := DelayTime);
// 报警触发
IF DelayTimer.Q THEN
Alarm := TRUE;
IF RisingEdge THEN
Unacked := TRUE;
END_IF;
END_IF;
// 确认处理
IF Ack AND NOT AckMem THEN
Unacked := FALSE;
END_IF;
AckMem := Ack;
// 自动复位
IF AutoReset AND NOT Condition THEN
Alarm := FALSE;
Unacked := FALSE;
END_IF;
DelayTimer();
END_FUNCTION_BLOCK
6. 实用技巧与调试方法
SCL调试常用技巧
6.1 在线监控与断点
- 使用监视(Monitor)功能实时查看变量值
- 使用断点(Breakpoint)暂停程序执行,分析中间状态
- 注意:断点会延长扫描周期,生产环境慎用
6.2 数据记录(Trace)
博途的Trace功能可以高速记录变量曲线,是PID整定、故障分析的利器。建议将关键变量(设定值、实际值、输出值)加入Trace。
6.3 常用快捷操作
| 快捷键 | 功能 |
|---|---|
| Ctrl + Space | 代码补全 |
| Ctrl + Shift + F | 格式化代码 |
| Ctrl + / | 注释/取消注释 |
| F1 | 打开帮助文档 |
📦 资源下载: 本文涉及的FB/FC源码已打包,可在资源下载页面获取TIA Portal库文件。