博文

20通道设备保养计时器:一段ST代码读懂设备运维的核心逻辑

笔记

在工业自动化项目中,设备保养提醒是几乎每台设备都会用到的功能。今天通过一段结构化文本(ST)程序,拆解多通道保养计时器的实现思路。


一、功能概述

这段程序实现了一个 20通道设备保养计时器,核心功能包括:

  • 🕐 实时运行时间累计:以”小时.分钟”格式存储(如 5.37 = 5小时37分钟)
  • 保养提示:运行时间达到预设提示阈值时,触发提醒
  • 🚨 超时报警:运行时间达到预设超时阈值时,触发故障报警
  • 🔄 一键复位:保养完成后复位计时,重新开始累计

二、数据结构说明

程序中用到的核心变量如下:

//保养参数结构体
Maintenance_typ : 	STRUCT  (*//*)
  rTips     : ARRAY[0..19]OF REAL;
  rOverTime : ARRAY[0..19]OF REAL;
  rInterger : ARRAY[0..19]OF REAL;
  rActTime  : ARRAY[0..19]OF REAL;
  bReset    : ARRAY[0..19]OF BOOL;
  bTips     : ARRAY[0..19]OF BOOL;
  bAlarm    : ARRAY[0..19]OF BOOL;
END_STRUCT;
// —— 时间计数变量 ——
iSeconds    : INT;      // 秒计数器(0~59)
iMinutes    : INT;      // 分计数器(0~59)
rMinutes    : REAL;     // 当前小时内的小数分钟值(0.00~0.59)
bExecute    : BOOL;     // 整点触发标志(每小时触发一次)

// —— 保养通道循环变量 ——
iMaintenance : INT;     // 循环索引(0~19,共20个通道)

// —— 保养数据结构(每通道独立)——
gMaintenance.rActTime[20]   : REAL;   // 实际运行时间(HH.MM格式)
gMaintenance.rInterger[20]  : REAL;   // 整数小时备份(断点续算用)
gMaintenance.rTips[20]      : REAL;   // 提示阈值(如 100.00 = 100小时提示)
gMaintenance.rOverTime[20]  : REAL;   // 超时阈值(如 120.00 = 120小时报警)
gMaintenance.bTips[20]      : BOOL;   // 保养提示标志
gMaintenance.bAlarm[20]     : BOOL;   // 超时报警标志
gMaintenance.bReset[20]     : BOOL;   // 复位请求(外部触发)

三、完整代码(逐行注释版)

// ==========================================================**
// 第一部分:秒→分→时 时间累计逻辑
// 前提:本段程序由外部定时器每 1 秒调用一次
// **==========================================================

IF iMinutes < 60 THEN
    // —— 未满1小时,继续累加 ——
    IF iSeconds < 60 THEN
        // 秒未满60,正常+1
        iSeconds := iSeconds + 1;
    ELSE
        // 秒满60,进位到分钟,秒清零
        iMinutes := iMinutes + 1;
        iSeconds := 0;
    END_IF;
    // 将分钟转换为小数部分:1分钟 = 0.01
    // 例如:37分钟 → 0.37,与整数小时拼接后得到 5.37(即5小时37分)
    rMinutes := INT_TO_REAL(iMinutes MOD 60) * 0.01;
ELSE
    // —— 满1小时,整点触发 ——
    iMinutes := 0;        // 分钟归零,开始新一轮计数
    bExecute := TRUE;     // 置位整点触发标志
END_IF;

// ==========================================================**
// 第二部分:保养时间累计(整点刷新 + 分钟细更新)
// **==========================================================

IF bExecute THEN
    // —— 整点触发:整数小时 +1,并备份到 rInterger ——
    FOR iMaintenance := 0 TO 19 DO
        gMaintenance.rActTime[iMaintenance]  := gMaintenance.rActTime[iMaintenance] + 1.0;
        gMaintenance.rInterger[iMaintenance] := gMaintenance.rActTime[iMaintenance];
        bExecute                             := FALSE;  // 触发完成后清除标志
    END_FOR;
    
ELSE
    // —— 非整点:实时更新分钟小数部分 ——
    // rActTime = 整数小时(上次整点备份)+ 当前分钟小数
    // 效果:rActTime 实时反映 HH.MM 格式的运行时长
    FOR iMaintenance := 0 TO 19 DO
        gMaintenance.rActTime[iMaintenance] := gMaintenance.rInterger[iMaintenance] + rMinutes;
    END_FOR;
END_IF;

// ==========================================================**
// 第三部分:保养判定逻辑(提示 / 报警 / 复位)
// **==========================================================

FOR iMaintenance := 0 TO 19 DO
    
    // —— 3.1 复位逻辑 ——
    // 当外部触发复位(如操作员完成保养后按下复位按钮)
    IF gMaintenance.bReset[iMaintenance] THEN
    	gMaintenance.rInterger[iMaintenance] := 0.0;    // 整数时间清零
        gMaintenance.rActTime[iMaintenance]  := 0.0;     // 运行时间清零
        gMaintenance.bTips[iMaintenance]     := FALSE;   // 清除提示标志
        gMaintenance.bAlarm[iMaintenance]    := FALSE;   // 清除报警标志
        gMaintenance.bReset[iMaintenance]    := FALSE;   // 清除复位请求(自锁解除)
    END_IF;
    
    // —— 3.2 保养提示 ——
    // 运行时间 ≥ 提示阈值时,触发保养提醒
    // 例如:rTips = 100.00,则运行满100小时后提示"请保养"
    IF gMaintenance.rActTime[iMaintenance] >= gMaintenance.rTips[iMaintenance] THEN
        gMaintenance.bTips[iMaintenance] := TRUE;
    END_IF;
    
    // —— 3.3 超时报警 ——
    // 运行时间 ≥ 超时阈值时,触发故障报警
    // 例如:rOverTime = 120.00,则运行满120小时后报警"已超时"
    IF gMaintenance.rActTime[iMaintenance] >= gMaintenance.rOverTime[iMaintenance] THEN
        gMaintenance.bAlarm[iMaintenance] := TRUE;
    END_IF;
    
END_FOR;

四、运行逻辑图解

每1秒调用一次


┌─────────────┐     否     ┌──────────────────┐
│ iMinutes<60? │──────────→│ 秒+1,分钟转小数   │
└──────┬──────┘            │ rActTime实时更新  │
       │ 是(满60分)          └──────────────────┘

┌─────────────┐
│ 分钟归零     │
│ bExecute=TRUE│
└──────┬──────┘

┌─────────────────────┐
│ 20通道: rActTime+1.0│
│ rInterger备份        │
│ bExecute=FALSE       │
└─────────────────────┘


┌─────────────────────────┐
│ 20通道循环判定:           │
│ · bReset? → 清零复位     │
│ · rActTime≥rTips? → 提示 │
│ · rActTime≥rOverTime? → 报警│
└─────────────────────────┘

五、时间存储格式说明

程序采用 HH.MM 格式 存储运行时间,用一个 REAL 变量同时表示小时和分钟:

实际运行时间rActTime 值含义
0小时15分钟0.15刚运行15分钟
5小时30分钟5.30运行了5个半小时
100小时00分钟100.00运行满100小时
100小时45分钟100.45100小时又45分钟

设计巧妙之处

  • rInterger 保存整点时刻的整数小时数(如 100.00
  • rMinutes 保存当前小时内的分钟小数(如 0.45
  • 两者相加得到实时精确时间 100.45
  • 比较阈值时直接用 即可,无需额外换算

六、应用场景示例

假设有3个保养通道,配置如下:

通道保养项目rTips(提示)rOverTime(报警)
0主轴轴承润滑100.00(100h)120.00(120h)
1导轨油更换500.00(500h)600.00(600h)
2皮带检查200.00(200h)250.00(250h)

运行效果

  • 通道0运行到 100小时bTips[0] = TRUE,HMI弹出”请保养主轴轴承”
  • 若未及时保养,运行到 120小时bAlarm[0] = TRUE,触发设备报警
  • 操作员完成保养后按下复位 → bReset[0] = TRUE → 计时归零,重新开始

七、优化建议

优化点说明
断电保持rActTimerInterger 应声明为 PERSISTENT 变量,断电后不丢失
调用周期建议用 1秒周期任务调用,而非 PLC 扫描周期内直接累加(避免扫描时间影响精度)
阈值上限rTipsrOverTime 应设置上限校验,防止误配置超大值导致永不触发
多级提示可扩展为三级:即将到期(90%)→ 到期提示(100%)→ 超时报警(120%)
日历模式如果需要按自然日保养(如每月1日),可增加日期判断逻辑

八、总结

这段ST程序虽然不长,但包含了三个关键设计:

  1. 时间累计策略:秒→分→时逐级进位,整点触发刷新
  2. HH.MM存储格式:用单一 REAL 变量同时表达小时和分钟,简化阈值比较
  3. 三段式保养判定:复位 → 提示 → 报警,逻辑清晰且可独立配置

核心思路就是:用一个循环管理20个通道,每个通道独立设置提示和报警阈值,时间到了自动提醒,保养完了一键复位。


本文代码基于 IEC 61131-3 结构化文本(ST)语言编写,适用于 CODESYS、倍福 TwinCAT、贝加莱 Automation Studio 等主流 PLC 平台。

← 返回博文列表