零 BUG 工业实战!IEC61131-3 标准物料分拣系统 + 10 大避坑汇总

3 阅读11分钟

摘要

可编程逻辑控制器(PLC)是工业自动化领域的核心控制设备。本文从工程师视角出发,以IEC 61131-3标准的结构化文本(ST)语言为主线,系统阐述PLC的硬件架构、扫描周期原理、数据类型与指令系统。通过一个完整的物料分拣控制案例,展示从需求分析、I/O分配、程序编写到调试验证的全流程。文章包含可直接运行的ST代码、详细的运行结果分析以及10个高频踩坑点,帮助读者建立扎实的PLC工程实践能力。

应用场景

PLC广泛应用于以下工业控制场景:

  1. 离散制造:汽车焊装线、电子装配线、包装机械的顺序控制
  2. 过程控制:化工反应釜的温度PID调节、水处理厂的压力联锁
  3. 运动控制:伺服电机的点位控制、多轴同步(电子凸轮)
  4. 能源管理:智能电网的断路器控制、光伏逆变器的并网逻辑
  5. 基础设施:地铁屏蔽门系统、隧道通风控制、楼宇自动化

本文聚焦于离散制造中最典型的“传感器-控制器-执行器”闭环场景。

核心原理

1. 硬件架构

PLC由CPU模块、电源模块、数字量输入模块(DI)、数字量输出模块(DO)、模拟量输入模块(AI)、模拟量输出模块(AO)及通信模块组成。CPU内部包含:

  • 处理器:执行用户程序,通常为ARM Cortex-A系列或专用ASIC
  • 存储器:RAM(数据存储)、Flash(程序存储)、EEPROM(掉电保持)
  • 看门狗定时器:防止程序死循环

2. 扫描周期

PLC采用循环扫描工作方式,每个扫描周期包含五个阶段:

  1. 读输入:将物理输入信号状态读入输入映像区
  2. 执行程序:按顺序执行用户逻辑,结果写入输出映像区
  3. 通信处理:处理网络请求、诊断信息
  4. 自诊断:检查CPU、内存、I/O模块状态
  5. 写输出:将输出映像区状态刷新到物理输出点

扫描周期时间 = 输入采样时间 + 程序执行时间 + 通信时间 + 诊断时间 + 输出刷新时间。典型值为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. 根据颜色激活对应推杆(推杆动作时间1秒)
  3. 推杆动作期间忽略新物料
  4. 传送带故障时立即停止所有输出
  5. 手动复位按钮清除故障状态

步骤2:I/O分配

信号名称类型地址说明
Sensor_ArrivalDI%IX0.0物料到位传感器
Sensor_RedDI%IX0.1红色识别
Sensor_GreenDI%IX0.2绿色识别
Sensor_BlueDI%IX0.3蓝色识别
Fault_ConveyorDI%IX0.4传送带故障
Reset_ButtonDI%IX0.5手动复位
Actuator_RedDO%QX0.0红色推杆
Actuator_GreenDO%QX0.1绿色推杆
Actuator_BlueDO%QX0.2蓝色推杆
Motor_RunDO%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. 物料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. 物料2(绿色)到达:重复上述流程,Actuator_Green动作1000ms

  3. 物料3(蓝色)到达:重复上述流程,Actuator_Blue动作1000ms

异常流程测试

测试条件:正在处理红色物料时,传送带故障信号Fault_Conveyor变为TRUE。

预期行为:

  • 立即停止所有输出:Actuator_Red、Motor_Run全部为FALSE
  • bSystemFault置为TRUE
  • 状态机锁定,不再响应新物料
  • 按下Reset_Button后,故障清除,系统恢复ST_IDLE状态

边界条件测试

  1. 连续物料:若物料间距小于处理时间(1秒+离开检测时间),第二个物料将被忽略(bProcessing=TRUE时忽略新物料)
  2. 颜色未识别:若Sensor_Red/Green/Blue均为FALSE,则stCurrentColor=0,跳过执行直接进入等待
  3. 复位时正在处理:按下复位仅清除故障标志,不中断当前处理(可在实际项目中增加急停逻辑)

常见问题与避坑

问题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)语言的工程化应用。核心要点如下:

  1. 理解扫描周期是PLC编程的基础,所有逻辑必须考虑“输入采样-程序执行-输出刷新”的时序特性
  2. 状态机设计是复杂控制逻辑的标准解法,建议采用CASE语句实现,确保每个状态都有明确的进入和退出条件
  3. 定时器、计数器、边沿检测是PLC编程的三大基础功能块,必须掌握其正确使用方法
  4. 故障处理逻辑应独立于主控逻辑,优先级最高,确保安全联锁的可靠性
  5. 变量声明时明确作用域和保持属性,避免运行时错误

建议读者在掌握本文内容后,进一步学习:

  • 模拟量处理:4-20mA信号采集、工程量转换、滤波算法
  • PID控制:位置式与增量式算法、参数整定方法
  • 通信协议:Modbus RTU/TCP、Profinet、EtherCAT
  • 运动控制:电子齿轮、电子凸轮、CNC插补

工业控制没有捷径,唯有严谨的工程思维和大量的实践积累。希望本文能成为你PLC技术进阶的坚实阶梯。