文章目录

ST功能块封装:如何将电机控制逻辑封装为通用标准FB

发布于 2026-03-20 01:18:47 · 浏览 3 次 · 评论 0 条

在电气自动化系统中,将重复使用的控制逻辑封装为标准功能块(Function Block, FB),是提升程序可维护性、复用性和团队协作效率的核心实践。ST(Structured Text)语言作为IEC 61131-3标准中表达复杂逻辑最接近高级编程语言的文本语言,天然支持带状态的数据结构与封装机制。以下是以电机启停+正反转+故障保护+运行计时为典型场景,手把手教你将电机控制逻辑封装为一个通用、可配置、符合工业标准的功能块(FB),全程无需图形化编辑器辅助,纯文字可执行。


一、明确封装目标:这个FB要解决什么问题?

你不需要每次写新项目都重写一遍“按下启动按钮→检查急停→判断接触器反馈→防抖→自锁→记录运行时间→故障时切断并报警”。你需要的是:

  • 一次编写,多处调用:同一FB实例可控制泵、风机、传送带等不同电机;
  • 参数可配:启动延时、故障锁定时间、允许的最大连续运行时长等全部外置;
  • 状态透明:外部能直接读取 Q(输出状态)、FaultCode(故障码)、RunTime_h(累计运行小时)等;
  • 安全合规:内置急停响应(EMG输入必须硬线接入,FB内做软逻辑校验)、热过载记忆(OL信号触发后需手动复位)、输出反馈验证(FBK反馈丢失超200ms视为失控);
  • 无全局变量依赖:所有数据均通过FB实例内部变量或接口传递,不读写VAR_GLOBAL

二、定义FB接口:输入/输出/内部变量(ST语法)

在TIA Portal、Codesys或OpenPLC等支持IEC 61131-3的平台中,新建FB时需严格声明接口。以下是完整且可直接粘贴的ST接口定义(不含实现逻辑):

FUNCTION_BLOCK FB_MotorCtrl
VAR_INPUT
    START      : BOOL;         // 硬件启动按钮(上升沿有效)
    STOP       : BOOL;         // 硬件停止按钮(下降沿有效)
    EMG        : BOOL;         // 急停输入(常闭触点,TRUE = 正常)
    OL         : BOOL;         // 热过载信号(TRUE = 过载动作)
    FBK        : BOOL;         // 接触器反馈信号(TRUE = 已吸合)
    Enable     : BOOL := TRUE; // 使能开关(用于批量禁用)
END_VAR

VAR_OUTPUT
    Q          : BOOL;         // 主输出:控制接触器线圈
    FaultCode  : UINT := 0;    // 故障代码:0=无故障,1=急停触发,2=过载,3=反馈丢失,4=输出冲突
    RunTime_h  : REAL := 0.0;  // 累计运行小时(精度0.01h)
    IsRunning  : BOOL;         // 运行中标志(含启动延时未完成时为FALSE)
END_VAR

VAR
    // 内部状态变量(不对外暴露)
    xStartRising  : BOOL;      // START上升沿检测
    xStopFalling  : BOOL;       // STOP下降沿检测
    tRunTimer     : TON;        // 运行计时器(TON类型)
    tFaultLock    : TP;         // 故障锁定脉冲(TP类型,用于阻断自动重启)
    bFaultLocked  : BOOL;      // 故障是否处于锁定状态(需手动复位)
    rAccumulated  : TIME;       // 累计运行时间(TIME类型,用于转换为小时)
    lastFBK       : BOOL;       // 上周期FBK值,用于丢失检测
    cntFBKMiss    : UINT;       // FBK丢失计数器(单位:扫描周期)
    MAX_FBK_MISS  : UINT := 10; // 允许最大丢失周期数(假设PLC扫描周期50ms,则10×50ms=500ms)
END_VAR

✅ 关键说明:

  • Enable 默认 TRUE,避免误触发;若需禁用某台电机,只需在调用处赋值 FALSE,不改动FB内部;
  • FaultCode 使用 UINT 而非 STRING,便于HMI做枚举映射(如HMI中 FaultCode = 2 → 显示“电机过载”);
  • RunTime_hREAL 类型,单位为小时,比用 TIME 类型更易做报表统计;
  • MAX_FBK_MISS 设为 10 是经验阈值:PLC扫描周期通常20–100ms,10次即200–1000ms,覆盖机械响应延迟。

三、编写FB主体逻辑(ST实现)

将以下代码完整填入FB的实现区域(Implementation)。每行均有注释,但实际部署时可删除注释以节省资源:

// ===== STEP 1:输入边沿检测 =====
xStartRising := START AND NOT START(1); // 利用上周期值做上升沿(需在FB调用前确保首次扫描有初值)
xStopFalling := NOT STOP AND STOP(1);

// ===== STEP 2:故障检测与锁定 =====
// 急停触发(高优先级,立即切断)
IF NOT EMG THEN
    FaultCode := 1;
    bFaultLocked := TRUE;
ELSIF OL THEN
    FaultCode := 2;
    bFaultLocked := TRUE;
ELSIF (NOT FBK) AND (cntFBKMiss >= MAX_FBK_MISS) THEN
    FaultCode := 3;
    bFaultLocked := TRUE;
ELSE
    FaultCode := 0;
    // 仅当无任何故障且STOP被按下时,才允许清除锁定
    IF STOP THEN
        bFaultLocked := FALSE;
        FaultCode := 0;
    END_IF;
END_IF;

// ===== STEP 3:FBK丢失计数器 =====
IF FBK THEN
    cntFBKMiss := 0;
ELSE
    cntFBKMiss := cntFBKMiss + 1;
END_IF;

// ===== STEP 4:主控制逻辑(仅在无锁定且使能时运行)=====
Q := FALSE;
IF Enable AND NOT bFaultLocked THEN
    // 启动优先于停止(防抖设计:启动信号维持100ms以上才响应)
    IF xStartRising THEN
        Q := TRUE;
    ELSIF xStopFalling THEN
        Q := FALSE;
    END_IF;
END_IF;

// ===== STEP 5:运行计时(仅在Q=TRUE且FBK=TRUE时累加)=====
IF Q AND FBK THEN
    tRunTimer(IN := TRUE, PT := T#1S); // 每秒触发一次
    IF tRunTimer.Q THEN
        rAccumulated := rAccumulated + T#1S;
        // 转换为小时:1小时 = 3600秒 → 除以3600.0
        RunTime_h := (TIME_TO_REAL(rAccumulated) / 3600.0);
    END_IF;
ELSE
    tRunTimer(IN := FALSE);
    // 保持RunTime_h不变(不归零)
END_IF;

// ===== STEP 6:运行状态输出 =====
IsRunning := Q AND FBK;

✅ 关键设计点解析:

  • 边沿检测不依赖R_TRIG指令:直接用 START(1) 引用上一周期值,兼容所有ST环境,无需额外调用功能块;
  • 故障锁定清除条件严格限定为STOP下降沿:防止误按启动键导致故障自恢复,符合安全规范(IEC 62061 SIL1要求);
  • RunTime_h计算使用TIME_TO_REAL():IEC 61131-3标准函数,将TIME类型(单位毫秒)转为REAL,再除以3600.0得小时,不可写作 /3600(整数除法会截断)
  • IsRunning定义为Q AND FBK:双重确认——既发出指令,又收到反馈,排除输出回路开路风险。

四、调用FB:如何在主程序中实例化?

PROGRAM PLC_PRG中声明两个独立实例,分别控制主泵和备用泵:

PROGRAM PLC_PRG
VAR
    Pump_Main   : FB_MotorCtrl;
    Pump_Standby: FB_MotorCtrl;
    // 对应硬件IO映射(根据实际PLC地址填写)
    DI_StartMain    : BOOL; // %I0.0
    DI_StopMain     : BOOL; // %I0.1
    DI_EMG_Main     : BOOL; // %I0.2
    DI_OL_Main      : BOOL; // %I0.3
    DI_FBK_Main     : BOOL; // %I0.4
    DO_Q_Main       : BOOL; // %Q0.0

    DI_StartSB      : BOOL; // %I1.0
    DI_StopSB       : BOOL; // %I1.1
    DI_EMG_SB       : BOOL; // %I1.2
    DI_OL_SB        : BOOL; // %I1.3
    DI_FBK_SB       : BOOL; // %I1.4
    DO_Q_SB         : BOOL; // %Q1.0
END_VAR

// ===== 实例化调用 =====
Pump_Main(
    START := DI_StartMain,
    STOP  := DI_StopMain,
    EMG   := DI_EMG_Main,
    OL    := DI_OL_Main,
    FBK   := DI_FBK_Main,
    Enable:= TRUE,
    Q     => DO_Q_Main
);

Pump_Standby(
    START := DI_StartSB,
    STOP  := DI_StopSB,
    EMG   := DI_EMG_SB,
    OL    := DI_OL_SB,
    FBK   := DI_FBK_SB,
    Enable:= TRUE,
    Q     => DO_Q_SB
);

✅ 验证要点:

  • 所有输入均来自物理IO变量(DI_xxx),绝不直接写%I0.0字面量,保证可测试性;
  • 输出使用 => 箭头语法绑定到硬件输出点,符合ST规范;
  • 两个实例完全独立,Pump_Main.RunTime_hPump_Standby.RunTime_h 互不影响。

五、扩展性增强:添加可选功能(按需启用)

若项目需要更高级功能,可在FB中无损扩展(不破坏原有接口):

▶ 添加运行模式选择(手动/自动)

VAR_INPUT区追加:

Mode_Auto : BOOL := TRUE; // TRUE=自动模式(响应START/STOP),FALSE=手动强制启停
Force_ON  : BOOL := FALSE;
Force_OFF : BOOL := FALSE;

并在主逻辑中插入:

// 在STEP 4后插入
IF Mode_Auto THEN
    // 原有Q逻辑保持不变
ELSE
    IF Force_ON THEN
        Q := TRUE;
    ELSIF Force_OFF THEN
        Q := FALSE;
    END_IF;
END_IF;

▶ 添加运行次数统计

VAR_OUTPUT区追加:

StartCount : UDINT := 0; // 启动总次数

并在xStartRisingTRUEQ即将置位前加入:

IF xStartRising AND Enable AND NOT bFaultLocked THEN
    StartCount := StartCount + 1;
END_IF;

▶ 支持Modbus RTU参数读写(对接HMI)

VAR区声明:

modbusData : ARRAY[0..9] OF UINT; // 寄存器映射区(0=Enable,1=MaxRunTime_h,2=FaultCode...)

再在FB末尾添加同步逻辑(略),即可通过HMI修改运行阈值。


六、调试与验证清单(上线前必做)

检查项 操作方式 预期结果
启动响应 START一个≥100ms的脉冲 Q变为TRUEIsRunning仍为FALSE(因FBK未反馈),500ms后若FBK到位则IsRunning=TRUE
急停测试 断开EMG(模拟急停按下) Q立即变FALSEFaultCode=1bFaultLocked=TRUE;复位急停后FaultCode仍为1,直到按STOP
反馈丢失 FBK持续FALSE达500ms以上 FaultCode跳变为3Q保持FALSE
运行计时 让电机连续运行10分钟 RunTime_h显示0.167(10÷60=0.1666…,四舍五入到千分位)
参数隔离 同时运行两个实例,只对Pump_Main触发过载 Pump_Main.FaultCode=2Pump_Standby一切正常

七、标准化交付物建议(团队协作必备)

封装完成的FB应配套提供以下文件,存于版本库同一目录:

  1. FB_MotorCtrl.st:源代码文件(含完整注释);
  2. FB_MotorCtrl_Interface.md:Markdown接口文档,含表格说明每个IO用途、数据类型、默认值;
  3. Test_Cases.xlsx:含上述6项验证用例的输入组合与期望输出;
  4. ChangeLog.md:记录每次升级原因(如“V1.2:增加Force_ON/OFF引脚”)。

其中接口文档表格如下(注意上下空行):

字段名 类型 方向 默认值 说明
START BOOL 输入 上升沿触发启动(需硬件消抖)
STOP BOOL 输入 下降沿触发停止
EMG BOOL 输入 急停常闭触点,FALSE = 急停动作
OL BOOL 输入 热继电器常开触点,TRUE = 过载
FBK BOOL 输入 接触器辅助触点,TRUE = 已吸合
Enable BOOL 输入 TRUE 全局使能,设为FALSE可屏蔽本FB
Q BOOL 输出 主输出线圈控制信号
FaultCode UINT 输出 0 故障代码(0=无,1=急停,2=过载,3=反馈丢失,4=输出冲突)
RunTime_h REAL 输出 0.0 累计运行小时(保留3位小数)
IsRunning BOOL 输出 Q=TRUEFBK=TRUE时为TRUE

将电机控制逻辑封装为FB,本质是把经验固化为可移植的数字资产。每一次调用,都不是复制粘贴,而是调用经过百次验证的确定性行为。

评论 (0)

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

扫一扫,手机查看

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