摘要
可编程逻辑控制器(PLC)是工业自动化领域的核心控制设备。本文从工程师视角出发,以IEC 61131-3标准的结构化文本(ST)语言为主线,系统阐述PLC的硬件架构、扫描周期原理、数据类型与指令系统。通过一个完整的物料分拣控制案例,展示从需求分析、I/O分配、程序编写到调试验证的全流程。文章包含可直接运行的ST代码、详细的运行结果分析以及10个高频踩坑点,帮助读者建立扎实的PLC工程实践能力。
应用场景
PLC广泛应用于以下工业控制场景:
- 离散制造:汽车焊装线、电子装配线、包装机械的顺序控制
- 过程控制:化工反应釜的温度PID调节、水处理厂的压力联锁
- 运动控制:伺服电机的点位控制、多轴同步(电子凸轮)
- 能源管理:智能电网的断路器控制、光伏逆变器的并网逻辑
- 基础设施:地铁屏蔽门系统、隧道通风控制、楼宇自动化
本文聚焦于离散制造中最典型的“传感器-控制器-执行器”闭环场景。
核心原理
1. 硬件架构
PLC由CPU模块、电源模块、数字量输入模块(DI)、数字量输出模块(DO)、模拟量输入模块(AI)、模拟量输出模块(AO)及通信模块组成。CPU内部包含:
- 处理器:执行用户程序,通常为ARM Cortex-A系列或专用ASIC
- 存储器:RAM(数据存储)、Flash(程序存储)、EEPROM(掉电保持)
- 看门狗定时器:防止程序死循环
2. 扫描周期
PLC采用循环扫描工作方式,每个扫描周期包含五个阶段:
- 读输入:将物理输入信号状态读入输入映像区
- 执行程序:按顺序执行用户逻辑,结果写入输出映像区
- 通信处理:处理网络请求、诊断信息
- 自诊断:检查CPU、内存、I/O模块状态
- 写输出:将输出映像区状态刷新到物理输出点
扫描周期时间 = 输入采样时间 + 程序执行时间 + 通信时间 + 诊断时间 + 输出刷新时间。典型值为1-100ms,取决于程序复杂度和CPU性能。
3. 数据类型与变量
IEC 61131-3标准定义的数据类型:
- 基本类型:BOOL(位)、BYTE(8位)、WORD(16位)、DWORD(32位)、SINT/INT/DINT(有符号整数)、USINT/UINT/UDINT(无符号整数)、REAL/LREAL(浮点数)
- 派生类型:ARRAY(数组)、STRUCT(结构体)、ENUM(枚举)
- 系统类型:TIME(时间)、DATE(日期)、STRING(字符串)
变量作用域:
- VAR:局部变量,仅在本POU(程序组织单元)内有效
- VAR_INPUT:输入参数,由调用者传入
- VAR_OUTPUT:输出参数,返回给调用者
- VAR_IN_OUT:输入输出参数,可读写
- VAR_GLOBAL:全局变量,所有POU共享
4. 结构化文本(ST)核心语法
ST语言类似于Pascal,支持:
- 赋值语句:A := B + C;
- 条件语句:IF...THEN...ELSIF...ELSE...END_IF;
- 选择语句:CASE...OF...ELSE...END_CASE;
- 循环语句:FOR...DO...END_FOR;WHILE...DO...END_WHILE;REPEAT...UNTIL...END_REPEAT;
- 函数调用:Result := Function_Name(Param1, Param2);
- 功能块实例化:FB_Instance(In1:=Val1, Out1=>Var1);
详细步骤:物料分拣控制系统实现
步骤1:需求分析
设计一个三色物料分拣系统:
- 传感器1(光电):检测物料到位
- 传感器2(颜色):识别红/绿/蓝
- 执行器1(推杆1):推出红色物料
- 执行器2(推杆2):推出绿色物料
- 执行器3(推杆3):推出蓝色物料
- 传送带电机:连续运行,故障时停止
控制要求:
- 物料到位后,颜色传感器识别颜色
- 根据颜色激活对应推杆(推杆动作时间1秒)
- 推杆动作期间忽略新物料
- 传送带故障时立即停止所有输出
- 手动复位按钮清除故障状态
步骤2:I/O分配
| 信号名称 | 类型 | 地址 | 说明 |
|---|---|---|---|
| Sensor_Arrival | DI | %IX0.0 | 物料到位传感器 |
| Sensor_Red | DI | %IX0.1 | 红色识别 |
| Sensor_Green | DI | %IX0.2 | 绿色识别 |
| Sensor_Blue | DI | %IX0.3 | 蓝色识别 |
| Fault_Conveyor | DI | %IX0.4 | 传送带故障 |
| Reset_Button | DI | %IX0.5 | 手动复位 |
| Actuator_Red | DO | %QX0.0 | 红色推杆 |
| Actuator_Green | DO | %QX0.1 | 绿色推杆 |
| Actuator_Blue | DO | %QX0.2 | 蓝色推杆 |
| Motor_Run | DO | %QX0.3 | 传送带电机 |
步骤3:变量声明
在PLC编程软件(如CODESYS、TIA Portal)中创建全局变量列表:
VAR_GLOBAL
// 输入映像
Sensor_Arrival AT %IX0.0 : BOOL;
Sensor_Red AT %IX0.1 : BOOL;
Sensor_Green AT %IX0.2 : BOOL;
Sensor_Blue AT %IX0.3 : BOOL;
Fault_Conveyor AT %IX0.4 : BOOL;
Reset_Button AT %IX0.5 : BOOL;
// 输出映像
Actuator_Red AT %QX0.0 : BOOL;
Actuator_Green AT %QX0.1 : BOOL;
Actuator_Blue AT %QX0.2 : BOOL;
Motor_Run AT %QX0.3 : BOOL;
// 内部变量
bSystemFault : BOOL := FALSE;
bProcessing : BOOL := FALSE;
ton_Red : TON; // 定时器功能块实例
ton_Green : TON;
ton_Blue : TON;
stCurrentColor : BYTE := 0; // 0=无, 1=红, 2=绿, 3=蓝
END_VAR
步骤4:主程序编写
创建主程序POU(PRG_Main),使用ST语言编写控制逻辑。
完整可运行代码(带注释)
// ============================================================
// 程序名称:PRG_Main
// 功能描述:三色物料分拣控制系统
// 作者:工业控制专家
// 日期:2025-01-15
// 版本:V1.0
// ============================================================
PROGRAM PRG_Main
VAR
// 上升沿检测变量
rTrig_Arrival : R_TRIG;
rTrig_Reset : R_TRIG;
fTrig_Arrival : F_TRIG;
// 定时器预置时间常量(单位:毫秒)
cstActuatorTime : TIME := T#1000ms;
// 状态机状态枚举
eState : (ST_IDLE, ST_DETECT, ST_ACTUATE, ST_WAIT) := ST_IDLE;
END_VAR
// ------------------------------------------------------------
// 主逻辑执行区
// ------------------------------------------------------------
// 1. 上升沿检测实例化(必须在每个周期调用)
rTrig_Arrival(CLK := Sensor_Arrival);
rTrig_Reset(CLK := Reset_Button);
fTrig_Arrival(CLK := Sensor_Arrival);
// 2. 故障处理逻辑
IF Fault_Conveyor THEN
bSystemFault := TRUE;
// 故障时立即停止所有输出
Actuator_Red := FALSE;
Actuator_Green := FALSE;
Actuator_Blue := FALSE;
Motor_Run := FALSE;
END_IF
// 3. 复位逻辑(仅在故障状态且按下复位按钮时清除故障)
IF rTrig_Reset.Q AND bSystemFault THEN
bSystemFault := FALSE;
bProcessing := FALSE;
eState := ST_IDLE;
END_IF
// 4. 主控逻辑(仅在无故障时执行)
IF NOT bSystemFault THEN
// 传送带正常运行
Motor_Run := TRUE;
// 状态机实现
CASE eState OF
// 状态0:空闲等待
ST_IDLE:
// 检测到物料到位且系统空闲
IF rTrig_Arrival.Q AND NOT bProcessing THEN
bProcessing := TRUE;
eState := ST_DETECT;
END_IF
// 状态1:颜色识别
ST_DETECT:
// 读取颜色传感器(优先级:红 > 绿 > 蓝)
IF Sensor_Red THEN
stCurrentColor := 1;
ELSIF Sensor_Green THEN
stCurrentColor := 2;
ELSIF Sensor_Blue THEN
stCurrentColor := 3;
ELSE
stCurrentColor := 0; // 未识别,默认无动作
END_IF
// 进入执行状态
eState := ST_ACTUATE;
// 状态2:执行推杆动作
ST_ACTUATE:
CASE stCurrentColor OF
1: // 红色
Actuator_Red := TRUE;
ton_Red(IN := TRUE, PT := cstActuatorTime);
IF ton_Red.Q THEN
Actuator_Red := FALSE;
ton_Red(IN := FALSE);
eState := ST_WAIT;
END_IF
2: // 绿色
Actuator_Green := TRUE;
ton_Green(IN := TRUE, PT := cstActuatorTime);
IF ton_Green.Q THEN
Actuator_Green := FALSE;
ton_Green(IN := FALSE);
eState := ST_WAIT;
END_IF
3: // 蓝色
Actuator_Blue := TRUE;
ton_Blue(IN := TRUE, PT := cstActuatorTime);
IF ton_Blue.Q THEN
Actuator_Blue := FALSE;
ton_Blue(IN := FALSE);
eState := ST_WAIT;
END_IF
ELSE // 未识别颜色,直接进入等待
eState := ST_WAIT;
END_CASE
// 状态3:等待物料离开
ST_WAIT:
// 物料离开检测(下降沿)
IF fTrig_Arrival.Q THEN
bProcessing := FALSE;
stCurrentColor := 0;
eState := ST_IDLE;
END_IF
END_CASE
ELSE
// 故障状态下复位所有内部状态
bProcessing := FALSE;
stCurrentColor := 0;
eState := ST_IDLE;
// 定时器复位
ton_Red(IN := FALSE);
ton_Green(IN := FALSE);
ton_Blue(IN := FALSE);
END_IF
// ------------------------------------------------------------
// 程序结束
// ------------------------------------------------------------
END_PROGRAM
运行结果说明
正常流程测试
测试条件:传送带无故障,依次送入红、绿、蓝三种物料。
预期输出时序:
-
物料1(红色)到达:Sensor_Arrival上升沿触发
- 状态机从ST_IDLE -> ST_DETECT
- 检测到Sensor_Red=TRUE,stCurrentColor=1
- 进入ST_ACTUATE,Actuator_Red输出TRUE
- 1000ms后定时器到,Actuator_Red复位为FALSE
- 进入ST_WAIT,等待物料离开(Sensor_Arrival下降沿)
- 物料离开后,状态回到ST_IDLE
-
物料2(绿色)到达:重复上述流程,Actuator_Green动作1000ms
-
物料3(蓝色)到达:重复上述流程,Actuator_Blue动作1000ms
异常流程测试
测试条件:正在处理红色物料时,传送带故障信号Fault_Conveyor变为TRUE。
预期行为:
- 立即停止所有输出:Actuator_Red、Motor_Run全部为FALSE
- bSystemFault置为TRUE
- 状态机锁定,不再响应新物料
- 按下Reset_Button后,故障清除,系统恢复ST_IDLE状态
边界条件测试
- 连续物料:若物料间距小于处理时间(1秒+离开检测时间),第二个物料将被忽略(bProcessing=TRUE时忽略新物料)
- 颜色未识别:若Sensor_Red/Green/Blue均为FALSE,则stCurrentColor=0,跳过执行直接进入等待
- 复位时正在处理:按下复位仅清除故障标志,不中断当前处理(可在实际项目中增加急停逻辑)
常见问题与避坑
问题1:输出抖动
现象:推杆快速通断,执行器损坏。 原因:未使用上升沿检测,在扫描周期内反复触发。 解决:所有触发信号必须使用R_TRIG或F_TRIG功能块。
问题2:定时器未复位
现象:定时器到达后不再计时,但输出保持。 原因:定时器IN端未在完成时置为FALSE。 解决:在定时器Q为TRUE后,立即将IN置为FALSE(如代码中ton_Red(IN:=FALSE))。
问题3:全局变量冲突
现象:多个POU同时修改同一变量,逻辑混乱。 原因:未使用互斥机制。 解决:采用主程序集中控制,或使用SEMAPHORE功能块。
问题4:扫描周期过长
现象:响应延迟、看门狗超时。 原因:循环体内有长延时指令或死循环。 解决:避免使用WHILE TRUE等无限循环;使用定时器替代软件延时。
问题5:I/O地址映射错误
现象:程序逻辑正确但输出无反应。 原因:物理I/O地址与变量地址不匹配。 解决:在硬件配置中核对模块插槽位置和起始地址,使用AT关键字强制映射。
问题6:数据类型溢出
现象:计数器异常、运算结果错误。 原因:INT类型范围-32768~32767,超出后回绕。 解决:根据计数范围选择DINT或UDINT类型,必要时做限幅处理。
问题7:状态机未覆盖所有状态
现象:程序卡死在某状态,无法恢复。 原因:CASE语句缺少ELSE分支。 解决:始终添加ELSE分支,将状态重置为初始状态。
问题8:通信数据未同步
现象:上位机显示值与实际值不符。 原因:多周期数据不一致。 解决:使用MOVE_BLK或MEMCPY一次性传输,或增加数据有效标志位。
问题9:掉电保持数据丢失
现象:重启后工艺参数归零。 原因:变量未声明为RETAIN属性。 解决:在VAR_GLOBAL RETAIN中声明需要保持的变量。
问题10:在线修改程序导致停机
现象:修改程序后PLC自动停止。 原因:未启用“在线修改”功能。 解决:在编程软件中启用“允许在线修改”,或使用“热复位”功能。
总结
本文从PLC的硬件架构和扫描原理出发,通过一个完整的物料分拣案例,深入讲解了结构化文本(ST)语言的工程化应用。核心要点如下:
- 理解扫描周期是PLC编程的基础,所有逻辑必须考虑“输入采样-程序执行-输出刷新”的时序特性
- 状态机设计是复杂控制逻辑的标准解法,建议采用CASE语句实现,确保每个状态都有明确的进入和退出条件
- 定时器、计数器、边沿检测是PLC编程的三大基础功能块,必须掌握其正确使用方法
- 故障处理逻辑应独立于主控逻辑,优先级最高,确保安全联锁的可靠性
- 变量声明时明确作用域和保持属性,避免运行时错误
建议读者在掌握本文内容后,进一步学习:
- 模拟量处理:4-20mA信号采集、工程量转换、滤波算法
- PID控制:位置式与增量式算法、参数整定方法
- 通信协议:Modbus RTU/TCP、Profinet、EtherCAT
- 运动控制:电子齿轮、电子凸轮、CNC插补
工业控制没有捷径,唯有严谨的工程思维和大量的实践积累。希望本文能成为你PLC技术进阶的坚实阶梯。