在PLC编程中,顺序控制是最常见的逻辑场景。传统的梯形图(LAD)往往需要编写大量的自锁、互锁逻辑,导致程序结构松散、可读性差。利用博途(TIA Portal)平台下的SCL语言,结合枚举类型与状态机模式,可以将复杂的顺序逻辑转化为清晰、严谨的代码结构。
一、 枚举类型的定义与配置
枚举类型是构建高可读性状态机的基石。它允许开发者使用具有实际意义的名称代替枯燥的数字,显著降低代码的维护成本。
1. 创建用户数据类型
在博途项目树中,找到 “PLC数据类型” 文件夹,右键点击 并选择 “添加新数据类型”。将 新创建的数据类型重命名为 ST_StateMachine。
2. 声明枚举值
在数据类型编辑界面,定义 状态机的各个步骤名称。系统默认从 0 开始分配数值,但为了逻辑严密,建议显式指定数值。
| 变量名 | 数值 | 说明 |
|---|---|---|
IDLE |
0 | 系统待机状态 |
STEP_FILL |
10 | 注液工步 |
STEP_HEAT |
20 | 加热工步 |
STEP_DRAIN |
30 | 排液工步 |
ERROR |
99 | 故障报警状态 |
注意:各个状态数值之间保留一定间隔(如10、20、30),便于后续插入新状态而无需大规模修改代码。
二、 功能块接口变量的规划
状态机必须封装在功能块(FB)中,以保证状态的持久化和逻辑的封装性。
创建 一个功能块 FB_ProcessControl,并 切换 至 SCL 语言。在接口区 声明 以下变量:
-
输入变量:
bStart(Bool):启动信号。bStop(Bool):停止信号。bReset(Bool):故障复位信号。rTempActual(Real):实际温度检测值。
-
输出变量:
bValve_Fill(Bool):注液阀控制。bValve_Drain(Bool):排液阀控制。bHeater(Bool):加热器控制。nCurrentState(Int):当前状态编号(用于HMI监控)。
-
静态变量:
eState(ST_StateMachine):当前状态枚举变量。tTimer(Timer):定时器实例。tElapsed(Time):累计时间。
三、 状态机逻辑的SCL实现
状态机的核心逻辑由“动作执行”与“跳转条件”两部分组成。使用 CASE...OF 语句实现状态流转。
1. 状态流转逻辑架构
以下流程图展示了从待机到故障处理的核心逻辑路径:
2. 编写代码逻辑
在程序代码区,输入 以下逻辑:
// 故障复位逻辑(最高优先级)
IF #bReset THEN
#eState := ST_StateMachine#IDLE;
#bValve_Fill := FALSE;
#bHeater := FALSE;
#bValve_Drain := FALSE;
END_IF;
// 主状态机逻辑
CASE #eState OF
// 待机状态
ST_StateMachine#IDLE:
// 动作:关闭所有输出
#bValve_Fill := FALSE;
#bHeater := FALSE;
#bValve_Drain := FALSE;
// 跳转:按下启动且无停止信号
IF #bStart AND NOT #bStop THEN
#eState := ST_StateMachine#STEP_FILL;
END_IF;
// 注液状态
ST_StateMachine#STEP_FILL:
// 动作:开启注液阀
#bValve_Fill := TRUE;
// 跳转:假设液位传感器接入(此处用模拟条件替代)
IF "Sensor_Level_High" THEN
#eState := ST_StateMachine#STEP_HEAT;
END_IF;
// 加热状态
ST_StateMachine#STEP_HEAT:
// 动作:开启加热器
#bHeater := TRUE;
// 跳转:温度达到设定值 (例如 80.0度)
IF #rTempActual >= 80.0 THEN
#eState := ST_StateMachine#STEP_DRAIN;
END_IF;
// 排液状态
ST_StateMachine#STEP_DRAIN:
// 动作:关闭加热,开启排液阀
#bHeater := FALSE;
#bValve_Drain := TRUE;
// 跳转:定时器超时 (排空时间假设为5秒)
#tTimer(IN := TRUE, PT := T#5S);
IF #tTimer.Q THEN
#tTimer(IN := FALSE); // 复位定时器
#eState := ST_StateMachine#IDLE;
END_IF;
// 故障状态
ST_StateMachine#ERROR:
// 动作:急停所有动作
#bValve_Fill := FALSE;
#bHeater := FALSE;
#bValve_Drain := FALSE;
// 仅允许复位信号跳出
IF #bReset THEN
#eState := ST_StateMachine#IDLE;
END_IF;
ELSE
// 异常处理:状态字非法时回归待机
#eState := ST_StateMachine#IDLE;
END_CASE;
// 将枚举状态映射为整数供HMI读取
#nCurrentState := INT_TO_DINT(#eState); // 注意:枚举在SCL中通常按整数处理
四、 进阶技巧:状态机的健壮性增强
基础的逻辑仅能满足功能需求,工业级代码还需处理边界情况。
1. 状态监控与超时保护
每个状态应设置超时保护,防止传感器失灵导致死循环。定义 一个静态变量 tStateTimer 用于记录当前状态持续时间。
// 在每个状态的动作区加入计时逻辑
ST_StateMachine#STEP_FILL:
#tStateTimer(IN := TRUE, PT := T#30S); // 设定30秒超时
IF #tStateTimer.Q THEN
// 超时未达到液位,判定故障
#eState := ST_StateMachine#ERROR;
#nErrorCode := 1; // 错误码:注液超时
END_IF;
2. 步进标志位的使用
为了避免在一个周期内多次触发跳转,建议引入上升沿检测。声明 临时变量 bStepForward 作为跳转标志。
| 场景 | 处理方式 |
|---|---|
| 启动跳转 | 使用 R_TRIG 实例检测 bStart 上升沿 |
| 状态内计时 | 确保定时器仅在特定状态下运行,进入新状态时需复位 |
3. 数值映射表
为了让操作员能在HMI上直观看到当前步骤,可将枚举值转换为描述性文本或整数。
| 枚举值 | 映射整数 | HMI显示文本 |
|---|---|---|
IDLE |
0 | 待机中 |
STEP_FILL |
10 | 正在注液 |
STEP_HEAT |
20 | 正在加热 |
STEP_DRAIN |
30 | 正在排液 |
ERROR |
99 | 设备故障 |
五、 调试与常见问题排查
编写完成后,需通过仿真或在线调试验证逻辑。
- 监控状态字:下载 程序后,在监控表中 添加
#eState变量。观察其数值是否随逻辑变化,例如从0跳变至10。 - 强制输入测试:在博途软件中 勾选
bStart,观察状态是否进入STEP_FILL。随后 强制 液位传感器信号,验证是否跳转至STEP_HEAT。 - 排查卡死现象:
- 若状态停留在
IDLE无法启动,检查 启动信号是否被互锁条件拦截。 - 若状态在非预期状态间反复横跳,通常是缺少了自锁逻辑或跳转条件未复位。
- 若状态停留在
通过枚举类型与 CASE 语句的结合,SCL编写的状态机不仅结构整洁,且极大地降低了后续维护人员阅读代码的门槛。

暂无评论,快来抢沙发吧!