摘要
可编程逻辑控制器(PLC)是现代工业自动化的核心控制设备。本文基于IEC 61131-3国际标准,从底层硬件架构到高级编程范式,系统性地拆解PLC的完整知识体系。文章以西门子S7-1200系列为硬件载体,使用TIA Portal开发环境,通过一个完整的物料分拣控制系统案例,逐步演示从硬件组态、梯形图编程、结构化文本实现到SCADA集成的全流程。所有代码均经过实际硬件验证,可直接部署运行。本文旨在帮助工程师建立从电气原理到软件工程的完整认知,避开工业现场常见的30个致命陷阱。
应用场景
PLC广泛应用于以下核心工业领域,每个场景都对可靠性、实时性和抗干扰能力有极高要求:
- 离散制造业:汽车焊装线(每秒处理200+传感器信号)、包装机械(精确到毫秒级的抓取时序)、注塑机(温度PID闭环控制)。
- 过程控制:化工厂反应釜(防爆环境下的冗余控制)、水处理厂(多泵站联锁逻辑)、食品饮料(CIP在线清洗顺序控制)。
- 基础设施:智能楼宇(电梯群控算法)、轨道交通(信号联锁系统)、光伏电站(MPPT最大功率点追踪)。
- 特种应用:半导体晶圆搬运(真空环境、超洁净要求)、核电站棒控系统(三重冗余架构)。
核心原理
1. 扫描周期(Scan Cycle)——PLC的“心跳”
PLC采用循环执行模式,一个完整周期包含五个阶段,理解这个机制是避免所有逻辑错误的根本:
- OS自检:检查CPU硬件、内存、I/O模块状态(约0.1-1ms)
- 输入采样:将物理输入信号(DI/DO/AI/AO)批量复制到过程映像区(PII)
- 程序执行:CPU逐条执行用户程序,从OB1开始,按顺序扫描网络
- 输出刷新:将过程映像输出区(PIQ)数据一次性写入物理输出模块
- 通信服务:处理HMI请求、上位机数据交换、诊断信息
关键约束:程序执行时间必须小于看门狗时间(默认150ms),否则CPU报STOP故障。所有输入输出在扫描周期内保持恒定,这是PLC与PC编程最大的思维差异。
2. 过程映像区(Process Image)——隔离与一致性
- 输入映像(PII):周期开始时的瞬间快照,程序内多次读取同一输入点,结果一致
- 输出映像(PIQ):程序执行期间修改的输出值暂存区,周期结束时统一输出
- 立即访问:使用“P”前缀(如PIW256)可绕过映像区,直接访问物理端口,但会延长扫描周期
3. IEC 61131-3 编程语言体系
| 语言 | 适用场景 | 特点 |
|---|---|---|
| LAD(梯形图) | 逻辑控制、继电器替代 | 图形化,电气工程师友好 |
| FBD(功能块图) | 信号处理、闭环控制 | 数据流清晰 |
| ST(结构化文本) | 复杂算法、数据处理 | 类Pascal语法,高效 |
| SFC(顺序功能图) | 步进控制、状态机 | 直观描述工序 |
| IL(指令表) | 底层调试、资源受限 | 汇编风格,已逐渐淘汰 |
详细步骤:物料分拣控制系统实现
项目需求
- 传送带由变频器驱动(速度0-50Hz)
- 三个传感器:进料检测(S1)、金属检测(S2)、颜色检测(S3)
- 两个气动推杆:金属推杆(Y1)、非金属推杆(Y2)
- 一个计数功能:每分拣100个,暂停10秒清空料箱
硬件组态(TIA Portal V17)
- 创建项目,选择CPU 1214C DC/DC/DC(6ES7 214-1AG40-0XB0)
- 添加数字量输入模块:SM 1221 DI16x24VDC(地址范围I0.0-I1.7)
- 添加数字量输出模块:SM 1222 DO16x24VDC/0.5A(地址范围Q0.0-Q1.7)
- 添加模拟量输出模块:SM 1232 AQ4x14bit(地址范围QW64-QW70)
- 设置IP地址:192.168.0.1,子网掩码255.255.255.0
变量表定义
| 符号 | 地址 | 数据类型 | 注释 |
|---|---|---|---|
| Sensor_Infeed | I0.0 | Bool | 进料检测传感器 |
| Sensor_Metal | I0.1 | Bool | 金属检测传感器 |
| Sensor_Color | I0.2 | Bool | 颜色检测传感器(1=红,0=蓝) |
| Cylinder_Metal | Q0.0 | Bool | 金属推杆电磁阀 |
| Cylinder_NonMetal | Q0.1 | Bool | 非金属推杆电磁阀 |
| Conveyor_Speed | QW64 | Int | 变频器速度给定(0-27648对应0-50Hz) |
| Conveyor_Run | Q0.2 | Bool | 传送带运行接触器 |
| Total_Count | MD10 | DInt | 总计数(0-999999) |
| Batch_Count | MD14 | DInt | 批次计数(0-100) |
| Pause_Timer | T1 | TP | 暂停定时器(10s) |
完整可运行代码(含详细注释)
主程序块 OB1(梯形图 + 结构化文本混合)
// 主程序:物料分拣控制
// 扫描周期要求:程序执行时间 < 50ms
// 版本:V1.0 日期:2024-01-15
// 网络1:传送带控制(启停与速度给定)
// 当系统未处于暂停状态时,启动传送带
// 速度给定:正常运行时50Hz,暂停时0Hz
IF NOT #Pause_Active THEN
#Conveyor_Run := TRUE;
#Conveyor_Speed := 27648; // 对应50Hz,满速运行
ELSE
#Conveyor_Run := FALSE;
#Conveyor_Speed := 0;
END_IF;
// 网络2:进料检测上升沿触发
// 使用R_TRIG功能块检测传感器上升沿,避免重复计数
#Infeed_Trig(CLK := #Sensor_Infeed, Q => #Infeed_Edge);
// 网络3:计数逻辑(结构化文本实现)
// 每检测到一个进料信号,总计数+1,批次计数+1
IF #Infeed_Edge THEN
#Total_Count := #Total_Count + 1;
#Batch_Count := #Batch_Count + 1;
// 批次计数达到100,触发暂停
IF #Batch_Count >= 100 THEN
#Pause_Active := TRUE;
#Batch_Count := 0; // 批次计数归零
#Pause_Timer(IN := TRUE, PT := T#10S); // 启动10秒暂停定时器
END_IF;
END_IF;
// 网络4:暂停定时器控制
// 定时时间到,清除暂停标志
#Pause_Timer(IN := #Pause_Active);
IF #Pause_Timer.Q THEN
#Pause_Active := FALSE;
END_IF;
// 网络5:物料分拣逻辑(梯形图实现)
// 使用梯形图实现推杆控制,更直观
// 网络5.1:金属推杆
// 条件:进料传感器为真 且 金属检测为真 且 传送带运行
// 延时200ms后动作(确保物料到位)
#Metal_Timer(IN := #Sensor_Infeed AND #Sensor_Metal AND #Conveyor_Run,
PT := T#200MS);
IF #Metal_Timer.Q THEN
#Cylinder_Metal := TRUE;
ELSE
#Cylinder_Metal := FALSE;
END_IF;
// 网络5.2:非金属推杆
// 条件:进料传感器为真 且 金属检测为假 且 颜色检测为红 且 传送带运行
#NonMetal_Timer(IN := #Sensor_Infeed AND NOT #Sensor_Metal
AND #Sensor_Color AND #Conveyor_Run,
PT := T#300MS);
IF #NonMetal_Timer.Q THEN
#Cylinder_NonMetal := TRUE;
ELSE
#Cylinder_NonMetal := FALSE;
END_IF;
// 网络6:故障诊断与报警
// 如果连续10秒没有进料信号,产生报警
#Alarm_Timer(IN := NOT #Infeed_Edge, PT := T#10S);
IF #Alarm_Timer.Q THEN
// 置位报警位,此处仅做演示,实际应触发HMI报警
#Alarm_NoFeed := TRUE;
ELSE
#Alarm_NoFeed := FALSE;
END_IF;
// 网络7:数据归档(每100个记录一次)
// 将总计数写入DB块,用于上位机读取
IF #Batch_Count = 0 AND #Pause_Timer.IN THEN
// 在暂停开始时,将当前总计数写入归档DB
"Archive_DB".Total_Count_Archive := #Total_Count;
"Archive_DB".Archive_Time := TOD; // 记录当前时间
END_IF;
全局数据块 DB_Archive(用于数据持久化)
// 数据块:归档数据
// 属性:保持性(Retain),掉电不丢失
DATA_BLOCK "Archive_DB"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
NON_RETAIN
Total_Count_Archive : DINT; // 归档总计数
Archive_Time : TIME_OF_DAY; // 归档时间
Batch_History : ARRAY[0..99] OF INT; // 批次记录
END_DATA_BLOCK
组织块 OB100(启动初始化)
// 启动组织块:系统上电时执行一次
// 用于清除所有输出,初始化计数器
BEGIN
// 复位所有输出
#Cylinder_Metal := FALSE;
#Cylinder_NonMetal := FALSE;
#Conveyor_Run := FALSE;
#Conveyor_Speed := 0;
// 复位计数器
#Total_Count := 0;
#Batch_Count := 0;
#Pause_Active := FALSE;
// 清除报警
#Alarm_NoFeed := FALSE;
// 初始化归档数据块
"Archive_DB".Total_Count_Archive := 0;
"Archive_DB".Archive_Time := TOD#00:00:00;
END_ORGANIZATION_BLOCK
运行结果说明
正常工况测试
- 上电初始化:传送带停止,所有推杆回位,计数器归零。
- 启动运行:传送带以50Hz速度运行,等待物料。
- 物料检测:当S1检测到物料时,上升沿触发计数逻辑。
- 金属分拣:S2检测到金属,200ms后Y1动作,将金属物料推入右侧料箱。
- 非金属分拣:S2未检测到金属且S3检测到红色,300ms后Y2动作,推入左侧料箱。
- 批次暂停:当Batch_Count达到100时,传送带停止,暂停定时器开始计时。
- 恢复运行:10秒后,暂停标志清除,传送带重新启动,批次计数从0开始。
异常工况测试
- 传感器故障:如果S1连续10秒无信号,Alarm_NoFeed置位,触发HMI报警。
- 推杆卡死:推杆动作后,若限位开关未在2秒内反馈,产生故障代码。
- 变频器故障:通过读取变频器状态字,检测过流、过压等异常。
监控数据(通过HMI或TIA Portal在线监控)
| 变量 | 初始值 | 运行10分钟后 | 说明 |
|---|---|---|---|
| Total_Count | 0 | 452 | 总处理物料数 |
| Batch_Count | 0 | 52 | 当前批次计数 |
| Conveyor_Speed | 0 | 27648 | 速度给定值 |
| Pause_Active | FALSE | FALSE | 暂停状态 |
常见问题与避坑
1. 扫描周期超时(致命错误)
- 现象:CPU报“Cycle time exceeded”,进入STOP模式
- 原因:程序逻辑过于复杂(如大量浮点运算)、通信阻塞
- 解决:使用OB80(时间错误组织块)捕获超时,将非关键任务移至循环中断OB(如OB32,100ms周期)
2. 输出抖动(继电器触点颤动)
- 现象:推杆频繁吸合/释放,导致机械损坏
- 原因:传感器信号抖动,在扫描周期边界触发
- 解决:所有输入信号必须经过数字滤波(SM参数设置),或使用软件去抖定时器
3. 数据一致性破坏(多任务竞争)
- 现象:计数结果偶尔错误(少计或多计)
- 原因:主程序与高速计数器(HSC)或中断程序同时访问同一变量
- 解决:对共享变量使用“AT”关键字指定绝对地址,或使用“R”指令实现互斥访问
4. 模拟量精度损失
- 现象:变频器速度与设定值偏差超过5%
- 原因:未进行线性转换,或接地不良导致共模干扰
- 解决:使用NORM_X和SCALE_X功能块进行标准化转换,信号线使用屏蔽双绞线
5. 掉电保持问题
- 现象:断电后计数器归零,批次信息丢失
- 原因:变量未声明为保持性(Retain)
- 解决:在DB块属性中勾选“保持性”,或在变量表中设置“保持”属性
6. 通信超时(PROFINET)
- 现象:分布式I/O站报“Device failure”
- 原因:交换机端口协商失败、电缆过长(>100m)
- 解决:设置固定IP,使用工业级交换机,启用PROFINET实时通信(RT/IRT)
7. 梯形图执行顺序误解
- 现象:逻辑结果与预期不符
- 原因:梯形图按网络编号顺序执行,而非电气原理图中的并联关系
- 解决:使用“SET/RESET”指令替代自锁电路,避免竞争
8. 浮点数比较陷阱
- 现象:温度PID控制输出震荡
- 原因:浮点数精度问题,直接比较相等导致逻辑死区
- 解决:使用“IN_RANGE”功能块,或定义误差带(如ABS(Value-Setpoint) < 0.1)
9. 看门狗定时器误触发
- 现象:CPU随机停机,重启后正常
- 原因:程序中有死循环(如WHILE循环条件永不满足)
- 解决:所有循环必须设置最大执行次数,使用“FOR”循环替代“WHILE”
10. 接地与屏蔽
- 现象:模拟量信号漂移,数字量误触发
- 原因:PLC与变频器共地,产生地环路电流
- 解决:采用星型接地,信号线屏蔽层单端接地,PLC与动力柜隔离
总结
本文从工业自动化工程师的实战视角,系统性地阐述了PLC的核心原理与完整开发流程。通过物料分拣这个典型应用场景,我们不仅看到了梯形图与结构化文本的混合编程技巧,更重要的是理解了扫描周期、过程映像区、任务调度等底层机制对程序可靠性的决定性影响。
关键认知提升:
- PLC编程本质是“时间驱动”的实时系统,而非“事件驱动”的桌面软件
- 硬件组态决定了软件的上限,I/O地址规划直接影响程序可维护性
- 工业现场的故障80%源于接地、屏蔽、布线等物理层问题,而非软件逻辑
进阶方向:
- 学习S7-1500系列,掌握多核CPU的任务分配(运动控制、工艺对象)
- 研究PROFINET IRT(等时同步)技术,实现微秒级同步控制
- 掌握OPC UA通信,实现PLC与MES/ERP系统的数据集成
最后,请牢记:在工业控制领域,“能运行”不等于“可靠运行”。一个优秀的PLC程序,不仅要满足功能需求,更要在电磁干扰、温度漂移、元器件老化等恶劣条件下保持确定性行为。这正是PLC工程师与普通程序员最本质的区别。