文章目录

博途程序的错误处理与异常捕获

发布于 2026-03-23 16:22:19 · 浏览 3 次 · 评论 0 条

博途(TIA Portal)是西门子推出的全集成自动化软件,涵盖PLC编程、HMI设计、驱动配置等功能。在实际工程项目中,程序运行难免遇到通信中断、数据越界、硬件故障等异常情况。若缺乏系统的错误处理机制,轻则导致设备停机,重则引发生产事故。本文从实际工程需求出发,系统讲解博途程序的错误处理与异常捕获方法。


一、错误类型与风险等级划分

博途项目中的错误可分为三类,需采取不同的处理策略。

错误类别 典型场景 处理原则
致命错误 CPU进入STOP模式、循环时间超时、存储器故障 立即停机,人工排查
功能错误 通信中断、伺服报警、传感器信号异常 自动复位或切换至安全模式
警告信息 参数越限、非关键设备离线 记录日志,继续运行

评估项目风险等级时,需结合设备价值、生产节拍和安全规范。对于涉及人身安全的场景(如机器人工作站),任何异常都应触发急停回路。


二、组织块(OB)的异常捕获机制

S7-1200/1500 PLC通过组织块实现系统级错误处理。合理配置OB是构建容错程序的基础。

2.1 必配的组织块

创建以下OB文件,确保CPU在异常时保持RUN状态:

OB编号 功能说明 触发条件
OB82 诊断中断 模块诊断状态变化
OB83 插拔中断 模块插入/移除
OB85 程序循环错误 访问缺失的OB/FC/FB
OB86 机架故障 分布式IO站故障
OB100 启动组织块 CPU从STOP→RUN

操作路径:项目树 → 双击"程序块" → 点击"添加新块" → 选择"组织块" → 指定OB编号。

2.2 诊断OB的编程模板

OB82为例,标准处理流程如下:

// OB82: 诊断中断处理
VAR_TEMP
    slotInfo : Word;      // 槽位信息
    moduleState : Byte;   // 模块状态
END_VAR

BEGIN
    // 提取启动信息
    slotInfo := OB82_MDL_ADDR;      // 故障模块的起始地址
    moduleState := OB82_MDL_TYPE;   // 模块类型信息

    // 写入诊断缓冲区
    #diagnosticBuffer.write(
        timestamp := RD_SYS_T(),
        eventID := 16#55_82,        // 自定义事件代码
        info1 := slotInfo,
        info2 := WORD_TO_BYTE(OB82_RACK_SLOT)
    );

    // 触发HMI报警
    #hmiInterface.setAlarm(
        alarmID := 2000 + BYTE_TO_INT(OB82_RACK_SLOT),
        severity := 2               // 中等优先级
    );
END

关键细节OB82的启动信息仅在执行期间有效,必须立即读取并转存至全局变量或数据块。


三、程序代码层的防御性编程

系统OB只能捕获硬件和运行时错误,逻辑错误需在代码层面预防。

3.1 输入数据合法性检查

功能块入口添加过滤器,防止无效数据进入运算环节:

// FB: 电机速度控制
VAR_INPUT
    setSpeed : Real;        // 设定转速 (rpm)
    maxSpeed : Real := 3000.0;  // 最大允许转速
    enable : Bool;
END_VAR

VAR_OUTPUT
    valid : Bool;           // 输入数据有效标志
    cmdSpeed : Real;        // 输出至驱动的指令值
END_VAR

VAR
    filteredSpeed : Real;
END_VAR

BEGIN
    // 步骤1: 使能检查
    IF NOT #enable THEN
        #valid := FALSE;
        #cmdSpeed := 0.0;
        RETURN;
    END_IF;

    // 步骤2: 数值范围检查
    IF #setSpeed < 0.0 OR #setSpeed > #maxSpeed THEN
        #valid := FALSE;
        #cmdSpeed := 0.0;
        // 记录错误日志
        #logError(errorCode := 16#8001, 
                  detail := "速度设定越限");
        RETURN;
    END_IF;

    // 步骤3: 变化率限制(防冲击)
    #filteredSpeed := #rateLimiter(
        input := #setSpeed,
        maxDelta := 500.0   // 每秒最大变化500rpm
    );

    #valid := TRUE;
    #cmdSpeed := #filteredSpeed;
END

3.2 除零与溢出防护

实数运算前执行零值检测,整数运算使用饱和处理:

// 安全除法函数
FUNCTION safeDivide : Real
VAR_INPUT
    numerator : Real;       // 分子
    denominator : Real;     // 分母
    defaultVal : Real := 0.0;  // 除零时的返回值
END_VAR

BEGIN
    IF ABS(#denominator) < 1.0E-6 THEN
        safeDivide := #defaultVal;
        // 可选:设置错误标志位
    ELSE
        safeDivide := #numerator / #denominator;
    END_IF;
END_FUNCTION

// 整数饱和加法(防止溢出)
FUNCTION satAddInt : Int
VAR_INPUT
    a, b : Int;
END_VAR

VAR_TEMP
    sum : DInt;
END_VAR

BEGIN
    #sum := INT_TO_DINT(#a) + INT_TO_DINT(#b);

    IF #sum > 32767 THEN
        satAddInt := 32767;     // 正饱和
    ELSIF #sum < -32768 THEN
        satAddInt := -32768;    // 负饱和
    ELSE
        satAddInt := DINT_TO_INT(#sum);
    END_IF;
END_FUNCTION

四、通信错误的自动恢复

工业现场中,PROFINET、Modbus TCP等通信链路易受电磁干扰。设计"自愈"机制可显著提升系统可用性。

4.1 通信状态机设计

采用状态机管理通信生命周期,实现故障自动重连:

graph LR A["空闲\nIdle"] -->|"启动请求"| B["连接中\nConnecting"] B -->|"超时/失败"| C["错误等待\nErrorWait"] B -->|"连接成功"| D["运行中\nRunning"] D -->|"通信中断"| C C -->|"延时到期"| B D -->|"正常关闭"| A C -->|"放弃命令"| A style C fill:#ffcccc style D fill:#ccffcc

4.2 SCL实现代码

// FB: TCP客户端通信管理
TYPE
    CommState : (IDLE, CONNECTING, RUNNING, ERROR_WAIT, STOPPING);
END_TYPE

VAR
    state : CommState := IDLE;
    retryTimer : TON;
    retryCount : Int;
    maxRetries : Int := 3;
    retryDelay : Time := T#5S;
END_VAR

BEGIN
    CASE #state OF

        IDLE:
            IF #startReq THEN
                #state := CONNECTING;
                #tsapConnect.remoteIP := #targetIP;
                #tsapConnect.remotePort := #targetPort;
                #tsapConnect.execute := TRUE;
            END_IF;

        CONNECTING:
            #tsapConnect.execute := TRUE;

            IF #tsapConnect.done THEN
                #state := RUNNING;
                #retryCount := 0;
                #tsapSend.execute := TRUE;  // 启动数据交换

            ELSIF #tsapConnect.error THEN
                #state := ERROR_WAIT;
                #retryTimer(IN := TRUE, PT := #retryDelay);

                IF #retryCount >= #maxRetries THEN
                    #fatalError := TRUE;
                    #state := IDLE;
                END_IF;
            END_IF;

        RUNNING:
            #tsapSend.execute := TRUE;
            #tsapReceive.execute := TRUE;

            // 检测通信中断
            IF #tsapSend.error OR #tsapReceive.error 
               OR NOT #tsapConnect.connected THEN
                #state := ERROR_WAIT;
                #retryTimer(IN := TRUE, PT := #retryDelay);
            END_IF;

        ERROR_WAIT:
            #retryTimer(IN := TRUE);

            IF #retryTimer.Q THEN
                #retryTimer(IN := FALSE);
                #retryCount := #retryCount + 1;
                #state := CONNECTING;
                #tsapConnect.execute := FALSE;  // 复位连接块
            END_IF;

            IF #stopReq THEN
                #state := IDLE;
                #retryTimer(IN := FALSE);
            END_IF;

    END_CASE;

    // 背景调用通信功能块
    #tsapConnect();
    #tsapSend();
    #tsapReceive();
END

关键参数retryDelay建议设为通信超时时间的2-3倍,避免过快重试导致网络拥塞。


五、诊断缓冲区的深度应用

诊断缓冲区是排查间歇性故障的核心工具。合理设计自定义诊断信息,可将平均故障修复时间(MTTR)降低60%以上。

5.1 标准诊断数据结构

// 全局数据块: DiagnosticBuffer
TYPE
    DiagEntry : STRUCT
        timestamp : Date_And_Time;  // 事件发生时刻
        eventCode : Word;           // 分类编码
        sourceBlock : String[16];   // 来源FB/FC名称
        lineNumber : UInt;          // 代码行号(SCL)
        param1 : DWord;             // 上下文参数1
        param2 : DWord;             // 上下文参数2
    END_STRUCT;
END_TYPE

VAR
    entries : Array[0..99] of DiagEntry;  // 循环缓冲区
    writeIndex : Int := 0;
    overflowCount : UDInt := 0;
END_VAR

5.2 日志写入函数

FUNCTION writeDiag : Void
VAR_INPUT
    eventCode : Word;
    param1 : DWord := 0;
    param2 : DWord := 0;
END_VAR

VAR_TEMP
    callerInfo : Block_FC_C;
END_VAR

BEGIN
    // 获取调用者信息(S7-1500支持)
    GET_INSTRUCTIONS(CODE := callerInfo);

    // 写入当前槽位
    "DiagnosticBuffer".entries["DiagnosticBuffer".writeIndex] := 
        (timestamp := RD_SYS_T(),
         eventCode := #eventCode,
         sourceBlock := #callerInfo.BLOCK_NAME,
         lineNumber := #callerInfo.LINE_NUMBER,
         param1 := #param1,
         param2 := #param2);

    // 更新索引
    "DiagnosticBuffer".writeIndex := 
        ("DiagnosticBuffer".writeIndex + 1) MOD 100;

    // 检测溢出
    IF "DiagnosticBuffer".writeIndex = 0 THEN
        "DiagnosticBuffer".overflowCount := 
            "DiagnosticBuffer".overflowCount + 1;
    END_IF;
END_FUNCTION

5.3 与HMI的集成

在WinCC或精智面板中,配置诊断视图控件,绑定数据块数组。启用时间筛选功能,允许操作员按时间段检索历史报警。


六、安全相关的故障处理

涉及安全功能(急停、安全门、光幕)的程序,必须遵循EN ISO 13849或IEC 62061标准。

6.1 安全程序与普通程序的隔离

项目 安全程序(F-CPU) 标准程序
编程语言 F-LAD/F-FBD(有限制) 全部语言
数据类型 F-BOOL/F-INT等 全部类型
故障反应 强制进入安全状态 可配置
认证要求 需TÜV等第三方认证 自行测试

关键原则:安全功能不得依赖标准程序的计算结果。标准程序可读取安全状态,但不能覆盖安全输出。

6.2 F-CPU的集体安全签名

每次修改安全程序后,必须执行"一致性检查"并记录安全签名(Collective F-Signature)。该签名是安全审计的法定依据。


七、调试与验证方法

完善的错误处理机制需经过系统性验证。

7.1 故障注入测试清单

测试项 注入方法 预期行为
通信中断 断开网线/关闭交换机端口 状态机转入ERROR_WAIT,HMI显示特定报警
模块故障 拔出分布式IO模块 OB82触发,程序切换至降级模式
数据越界 强制写入超范围设定值 输入过滤器阻断,记录诊断日志
循环时间超时 插入大量空循环 OB80触发,CPU保持RUN(若已配置)
电源波动 使用可调电源模拟欠压 电源模块诊断位变化,触发预警

7.2 在线诊断工具的使用

打开"在线与诊断"视图,掌握以下功能:

  1. 模块状态:查看所有硬件的LED状态模拟图
  2. 诊断缓冲区:按时间顺序浏览系统事件
  3. 分配列表:检查IO地址冲突
  4. 交叉引用:追踪变量在程序中的使用情况
  5. 比较功能:离线与在线程序的差异分析

八、性能优化注意事项

过度复杂的错误处理可能拖累扫描周期。遵循以下准则:

限制每个OB82/OB83的执行时间,超过5ms的诊断操作移至循环中断OB(如OB35)异步执行。

避免在故障处理程序中调用通信功能块,防止错误级联。

评估诊断缓冲区的写入频率,高频场景(如每秒超过10次)改用采样记录而非全量记录。

监控PLC的循环时间负荷率,保持在60%以下以预留故障处理的计算余量。


博途的错误处理体系涵盖硬件配置、程序架构和运维工具三个层面。建议从项目初期即规划诊断策略,而非事后补丁式添加。建立统一的错误编码规范、设计可复用的诊断功能块、训练运维人员解读诊断信息,三者结合方能构建真正可靠的自动化系统。

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文