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.45 | 100小时又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→ 计时归零,重新开始
七、优化建议
| 优化点 | 说明 |
|---|---|
| 断电保持 | rActTime 和 rInterger 应声明为 PERSISTENT 变量,断电后不丢失 |
| 调用周期 | 建议用 1秒周期任务调用,而非 PLC 扫描周期内直接累加(避免扫描时间影响精度) |
| 阈值上限 | rTips 和 rOverTime 应设置上限校验,防止误配置超大值导致永不触发 |
| 多级提示 | 可扩展为三级:即将到期(90%)→ 到期提示(100%)→ 超时报警(120%) |
| 日历模式 | 如果需要按自然日保养(如每月1日),可增加日期判断逻辑 |
八、总结
这段ST程序虽然不长,但包含了三个关键设计:
- 时间累计策略:秒→分→时逐级进位,整点触发刷新
- HH.MM存储格式:用单一 REAL 变量同时表达小时和分钟,简化阈值比较
- 三段式保养判定:复位 → 提示 → 报警,逻辑清晰且可独立配置
核心思路就是:用一个循环管理20个通道,每个通道独立设置提示和报警阈值,时间到了自动提醒,保养完了一键复位。
本文代码基于 IEC 61131-3 结构化文本(ST)语言编写,适用于 CODESYS、倍福 TwinCAT、贝加莱 Automation Studio 等主流 PLC 平台。