ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

S7-1500流量累积的博途实现:从原理到SCL编程

S7-1500流量累积的博途实现:从原理到SCL编程 简介西门子S7-1500 PLC流量累积数据处理案例基于博途STEP7环境编写面向自动化、电气工程及计算机等相关专业学生、教师与企业工程师适用于课程设计、毕业设计及项目初期验证等场景。压缩包共9个文件主要包含ap13项目文件、xml配置文件、plf与idx组态索引文件以及一个项目备份压缩包整体仅4.61MB便于直接导入TIA Portal查看程序结构和在线仿真调试。案例代码已经过完整运行测试功能确认无误重点展示了流量信号的采集转换、累积计算、数据块存储与处理流程有助于理解西门子PLC中模拟量处理、定时中断和DB块应用等关键知识点。读者既可对照案例学习工程化编程思路也能在此基础上修改参数、添加功能满足不同控制需求。该资源已有213人学习浏览对PLC入门者与进阶开发者均具参考价值。1. 为什么说 S7-1500 流量累积不只是“流量乘以时间”做水处理或能源管理的同行应该都遇到过这个场景现场有台西门子S7-1500博途TIA Portal里已经做好了模拟量采集上位机要的是每天的流量累计值而不是瞬时流量。你一边翻STEP7帮助一边想着是不是用TON累加结果发现精度和掉电保持都处理不干净。流量累积数据处理的核心就三件事用循环中断固定采样周期、把瞬时流量按时间积分、把累积结果放到带掉电保持的DB里。下面直接讲博途STEP7里一套可复现的S7-1500流量累积方案适合刚入门西门子PLC编程的工程师也给正在调流量计积算的老手一些参数参考。2. 流量累积的原理与博途STEP7选型从瞬时流量到累积量2.1 流量累积的基本公式为什么离散采样必须考虑周期抖动流量累积在数学上就是对瞬时流量做时间积分。设瞬时流量为 Q(t)单位是 m3/h从 T0 到 T1 的累积体积 V ∫ Q(t) dt。PLC 只能做离散采样所以实际实现变成 V Σ Q_i * Δt_i其中 Q_i 是第 i 次采样的瞬时流量Δt_i 是这次采样距上次采样的真实时间间隔。如果每次都按固定的 100ms 中断周期计算公式可以简化为 V T * Σ Q_i但这里有个隐患中断周期不是绝对准确相邻两次启动之间的间隔可能有零点几毫秒到几毫秒的抖动更糟的是某个周期被高优先级中断挤掉。按固定 T 计算累加时间越长误差越明显。所以我在写这一步时会刻意把 Δt_i 也给算进去。SCL 里可以直接读取系统时间戳或者更简单的方法是在循环中断 OB 里用一个静态变量记录上次扫描的系统时钟然后算真实间隔。这样即使中断有抖动累计结果也不会跟着漂。下面这段是 S7-1500 中常见的积分核心逻辑// 循环中断 OB30 中调用每 100ms 一次 // 输入: gFlowInstant 瞬时流量 REAL 单位 m3/h // 静态变量: prevTime DTL 上次时间戳, total LREAL 累积量 IF firstRun THEN prevTime : GET_SYSTEM_TIME(); firstRun : FALSE; RETURN; END_IF; nowTime : GET_SYSTEM_TIME(); // TIME_BETWEEN 返回 TIME 类型单位 ms转小时处理 deltaT : TIME_TO_REAL(TIME_BETWEEN(prevTime, nowTime)) / 3600000.0; total : total gFlowInstant * deltaT; prevTime : nowTime;这里把时间戳和间隔计算放到了中断里而不是在 OB1 里用 TON 凑周期原因后面细说。参数上注意gFlowInstant必须已经做过量程转换单位保持一致否则累积结果会直接放大或缩小 60 倍甚至 3600 倍。2.2 为什么用循环中断 OB 而不是定时器 TON很多刚开始做西门子PLC编程的朋友习惯用 TON 做定时触发。TON 本身没问题问题在于它放在 OB1 里时启动和停止的时机依赖扫描周期。当 OB1 里面有 PID、通信或大量位运算时扫描周期可能从 5ms 跳到 20ms用 TON 叠加出来的“周期”根本不稳定。而且 TON 只负责逻辑延时不会自动给你一个均匀的采样时钟你需要自己判断 started 到 done 的时刻代码写起来绕。S7-1500 的循环中断 OB如 OB30是由系统时钟触发的硬件级定时中断不受 OB1 扫描时间影响默认时间单位是 ms可以在属性里设置 10ms、100ms、1s 等。我用得最多的是 100ms 和 1s瞬时流量变化快的场合用 100ms平稳的管道流量用 1s 也够CPU 负载还会低一点。下面这张表是我在项目中常用的对比供选型时参考。触发方式稳定性最小周期精度风险典型用途OB1 TON受扫描周期波动影响受扫描周期限制高简单逻辑延时不适合流量累积OB30 循环中断硬件定时可靠可设 10ms低流量累积、PID 采样OB10 时间中断按日历触发1 秒中日报表、整点记录需要提醒的是循环中断的周期设得太短会占用大量 CPU 时间片。如果 S7-1500 同时在跑运动控制或 PROFINET 实时通信把 OB30 周期从 100ms 改到 10ms 之前最好先看一下 CPU 的诊断缓冲区里是否出现“循环中断超时”的提示。2.3 数据类型与 DB 设计REAL 还是 LREAL累积值存哪里流量瞬时值从模拟量模块过来后一般是 INT 或 REAL。S7-1500 原生支持 REAL我建议统一用 REAL 存瞬时流量累积量则要看总量级。举个例子管道流量 100 m3/h连续运行一年累积量是 876000 m3。REAL 的精度大约是 7 位有效数字到 876000 时有效分辨率只剩 0.1 m3 左右看起来还行但如果累积好几年总量到 500 万 m3 之后REAL 的分辨率可能已经超过 0.5 m3这对贸易结算来说是不可接受的。这时候两个选择一个是累积量用 LREAL64 位浮点S7-1500 支持但注意 LREAL 的运算在低端 CPU 上会稍微慢一点另一个是把累积量拆成两个 REAL一个存整数部分一个存小数部分每次累加后做进位。我一般优先用 LREAL因为代码简单而且 S7-1500 的算力足够。DB 里还有一个点不能忘累积量对应的 DB 变量要勾选 Remanence保持性否则 PLC 掉电后总量归零现场要骂人的。博途里右键 DB 变量在属性里可以找到 Remanence 设置选择 “Retain” 即可。除了累积量本身上次时间戳和初始化标志也要设为保持不然重启后时间基准会断掉。3. 在博途TIA Portal中编写S7-1500流量累积程序的落地步骤3.1 创建项目与硬件组态建立 PLC 变量表在博途 V16 或更高版本V17/V18 也行里新建项目后添加 S7-1500 CPU再把 AI 模块插入机架。模拟量模块的通道地址不是手动填的TIA Portal 会自动分配比如 IW64。随后在 PLC 变量表里把会用到的点建好命名尽量见名知意。最基础的一套变量在下面表里后面写的 SCL 程序就基于这张表。符号名地址/数据块数据类型含义AI_Flow_RawIW64INT流量变送器经模拟量模块输入的原始值HMI_ResetTotalDB1.HMI_ResetTotalBOOL上位机或触摸屏触发清零Flow_InstantDB1.Flow_InstantREAL量程转换后的瞬时流量 m3/hTotal_AccumDB1.Total_AccumLREAL累积流量 m3不建议直接拿 IW64 参与累积如果以后仪表量程或偏置变了你得改好几处程序。先把原始值转换成一个独立的 Flow_Instant再交给累积函数这是模块化编程的基本习惯。3.2 用 SCL 写一个可复用的流量累积 FB在博途中插入一个 FB语言选择 SCL名字可以叫FlowTotalizer。这个 FB 要能复用所以输入输出都用形参不直接访问全局变量。完整的核心代码如下FUNCTION_BLOCK FlowTotalizer { S7_Optimized_Access : TRUE } VERSION : 0.1 NON_RETAIN VAR_INPUT InstantFlow : REAL; // 瞬时流量单位 m3/h Reset : BOOL; // 复位累积量 END_VAR VAR_OUTPUT Total : LREAL; // 累积量单位 m3 END_VAR VAR init : BOOL : FALSE; // 第一次扫描标志 prevTime : DTL; // 上次采样的系统时间 nowTime : DTL; // 本次采样的系统时间 deltaT : REAL; // 实际时间间隔单位小时 END_VAR // 复位清空累计值并重新建立时间基准 IF Reset THEN Total : 0.0; init : FALSE; END_IF; // 第一次扫描只记录时间不累加避免从电源接通瞬间开始误算 IF NOT init THEN prevTime : GET_SYSTEM_TIME(); init : TRUE; RETURN; END_IF; nowTime : GET_SYSTEM_TIME(); // TIME_BETWEEN(prevTime, nowTime) 返回 TIME 类型单位 ms deltaT : TIME_TO_REAL(TIME_BETWEEN(prevTime, nowTime)) / 3600000.0; Total : Total LREAL_TO_REAL(InstantFlow) * deltaT; prevTime : nowTime;这段代码有几个地方要在参数层面确认Reset是电平型不是边沿型。如果 HMI 上一个复位按钮按下再松开必须用R_TRIG生成一个脉冲或者干脆让上位机保持 100ms 以上的高电平。GET_SYSTEM_TIME返回的是 CPU 系统时间函数名在博途不同版本中基本一致我用 V16 和 V20 都没有问题。TIME_TO_REAL把毫秒数转成 REAL再除以 3600000 就是小时。提示如果库版本里找不到TIME_BETWEEN可以改用T_DIFF效果一样或者把 DTL 先转成 LDT 再手动做减法。如果不想用GET_SYSTEM_TIME也可以直接利用 OB30 的启动信息它在 OB 内部可用但复用性差所以我更推荐上面的写法。3.3 在主程序里调用 FB并配置循环中断 OB30FB 写好后在主 OB1 里或者直接在 OB30 里调用。因为流量累积只关心时间间隔不需要在 OB1 里扫描所以最常见的做法是把 FB 放在 OB30 中让累积动作被周期中断驱动。OB30 默认就是 100ms 周期如果你要改双击 OB30在属性里找到“循环时间”设置。调用代码写在一段 SCL 里即可FlowTotalizer_Instance( InstantFlow : Flow_Instant, Reset : HMI_ResetTotal, Total : Total_Accum );如果你把Total定义成 FB 的输出那么它不会自动保持。要保证掉电不丢建议把Total改成一个VAR_IN_OUT并传入 DB 里的保持性变量。比如先在 DB1 里建一个Total_Accum属性改成Retain再把这个变量挂到Total接口上。这样掉电后 CPU 重新启动整个累积过程从掉电前的数值继续。3.4 连接模拟量输入与量程转换确认瞬时流量单位流量累积的入口是Flow_Instant它必须是从模拟量原始值转换出来的标准工程量。如果变送器输出 4-20mA对应 0-100 m3/h原始值AI_Flow_Raw的范围是 0~27648单极性。量程转换可以直接在 OB1 里用NORM_X和SCALE_X也可以手动算我一般写一行 SCLFlow_Instant : (AI_Flow_Raw / 27648.0) * 100.0;注意这里的前提是变送器已经做了零点和满度校准4mA 对应 020mA 对应 100 m3/h。如果你的仪表用的是 0-10V 但把 0V 对应 0也是一样的公式。唯一要小心的是有的变送器把 4mA 对应某个底值而不是 0比如自带显示的流量计下限是 1 m3/h那就得先做线性偏移Flow_Instant : 1.0 (AI_Flow_Raw / 27648.0) * 99.0;这类偏置如果搞错累积量在一开始就会有固定误差并且误差会随时间线性增长现场核对总量时很难定位。建议在博途的监控表里同时看AI_Flow_Raw和Flow_Instant用标准信号源或者手操器给一个已知流量值先把比例调对再管累积。4. S7-1500流量累积的常见坑与参数调整4.1 采样周期 vs 中断周期丢了周期怎么办循环中断不是不会丢周期的。当 CPU 被高优先级 OB 占用或者 OB30 自身的执行时间超过设定周期博途会在诊断缓冲区里记录事件“循环中断 OBs 的启动时间已超出”。一旦出现这个提示说明你的累积周期不是名义上的 100ms 了而程序还按 100ms 计算累积量就会偏小。这时候除了优化 OB30 里的指令最有效的办法是把累积量的计算改成时间戳差值法也就是第 2.1 节里的做法。这样即使某次中断晚了几毫秒deltaT会变长该补的时间照样补回来。现象可能原因处理方式累积值偏小中断周期被抢占程序仍按名义周期算使用时间戳差值法累积值偏大deltaT 单位把毫秒当日历秒检查除法从 3600000 写成 3600累积值突然跳变掉电恢复后时间戳保持与当前时间差很大上电后重新初始化 prevTime如果你用的是 OB1 里的定时器那么 OB1 扫描周期一波动定时器周期也会波动而且你还感知不到这是最危险的。我的原则是流量累积必须放在固定周期中断 OB 里并且要保留真实时间间隔用于修正。4.2 累积量溢出、清零与掉电保持的取舍LREAL 的数值范围很大正常工况下几乎不可能溢出。但清零逻辑要小心如果Reset是 HMI 上的一个带保持的按钮可能导致每个扫描周期都触发清零。正确做法是在 OB1 里生成一个上升沿脉冲然后置位一个单独的Reset_Command累积 FB 再对这个命令信号执行清零。实际上我遇到过因为 HMI 上开关量没做脉冲导致流量累积值一直归零的情况查了两小时才定位到。关于掉电保持博途里有两个办法一是把 FB 的实例 DB 改成保持型这样所有静态变量都保持二是把Total接口放到一个单独的保持型 DB 里FB 内只操作这个接口。方案一省事但会把中间变量也保持占用保持存储区方案二更精准适合希望每次上电都重置时间戳的场合。我比较推荐方案二因为prevTime和init这些中间变量在上电后必须重新初始化如果也跟着保持程序会在旧时间戳基础上硬算容易产生一个非常大的 deltaT累积量会猛跳一大截。4.3 博途SCL中TON怎么用为什么不能用TON做流量累积“博途SCL中TON怎么用”是很多入门者会搜的问题。TON 在 SCL 里可以直接以函数块方式调用例如TON_Instance( IN : #startCondition, PT : T#1S, Q #done, ET #elapsed);这段代码的逻辑是IN为 TRUE 后计时计时到 PT 后Q置 TRUEIN为 FALSE 时ET清零。单独看它没有问题但你要是想做流量累积TON 只能提供一个“到点脉冲”累积还是在 OB1 里做。OB1 扫描周期一变你得到的累积间隔就不是 1s可能是逐次扫描的随机值。而且 TON 在 OB1 里运行时如果 OB1 被中断TON 的计时依然按系统时钟走但你的采样动作没有同步发生瞬时流量值还是上一次扫描的旧值这就会造成“时间到了但数据是旧的”的系统误差。所以我的做法是TON 留在 OB1 里做设备逻辑顺控流量累积全部走 OB30 和 GET_SYSTEM_TIME。如果搜索博途 TON 的时候你搜到了很多教程先别急着把流量累积也套进去看你手里有没有一个固定的中断源。4.4 仿真与在线调试用监控表验证累积误差流量累积程序调试不能光看 HMI 上的数字跳不跳要能验证单位时间内增量和瞬时流量是否对得上。博途的仿真功能支持 S7-1500虽然没有模拟量硬件但可以给AI_Flow_Raw强制一个数值。步骤如下先把 OB30 周期设为 1000ms然后在监控表里把Flow_Instant强制成 60.0m3/h跑 10 分钟理论累积量应该是 60.0 * 10 / 60 10.0 m3。如果监控值不是 10.0优先检查deltaT的单位。很多新手把 MS 直接当成秒导致累积结果放大 3600 倍。另一个坑是博途仿真里的系统时间会跟随电脑时间但如果你中途改过 OB30 周期或下载过程序时间戳不会断裂因为GET_SYSTEM_TIME读的是绝对时间不依赖 OB 调用次数。这比用计数器加假设的周期靠谱得多。验证时建议做一个简单的离线累加表记录每分钟结束时的Total差值和该分钟内Flow_Instant的平均值做对比偏差超过 0.5% 就要回头查量程转换和中断周期配置。5. 进阶技巧按日期自动切换日累积量并缓存昨日结存量5.1 读取系统日期判断是否跨天现场报表通常需要“今日累积量”和“昨日累积量”。与其等上位机去读总累积量做差分不如在 PLC 里直接维护两日累计。在 S7-1500 里GET_SYSTEM_TIME返回的 DTL 结构带有年、月、日字段SCL 可以直接读取并比较。在 OB30 中调用流量累积 FB 后增加一段跨天判断nowDate : GET_SYSTEM_TIME(); IF (nowDate.YEAR curDate.YEAR) OR (nowDate.MONTH curDate.MONTH) OR (nowDate.DAY curDate.DAY) THEN yestTotal : todayTotal; todayTotal : 0.0; curDate : nowDate; END_IF; todayTotal : todayTotal InstantFlow * deltaT;这段代码里curDate需要是 DTL 类型且掉电保持yestTotal和todayTotal建议用 LREAL。注意跨天判断放在累积计算之前这样不会把新一天的第一笔流量算到昨日。如果你希望昨日值在跨天后保持一整天可以把yestTotal设置成保持型并在上位机确认后再手动复位。5.2 掉电恢复时的日期处理如果 PLC 停机一天以上才上电curDate因为保持属性仍然是旧日期上电第一周期会立即触发跨天todayTotal清零yestTotal变成停机前一天的累积值。这个行为一般符合“昨日结存量”的定义。真正要小心的是todayTotal在停机期间的累计丢失如果工艺要求不能丢量就得靠仪表侧的机械计数器或者断电续存模块兜底。PLC 的程序再怎么优化也只能保证上电后的计算连续性。5.3 用仿真验证跨天逻辑把 Windows 系统时间改到 23:59:59或者直接用博途仿真里的系统时间功能运行 1 秒后即可看到yestTotal被赋值。仿真中还要验证日期边界在月底或年底是否正常因为 DTL 的月份进位是系统完成的不需要你写闰年判断。最后用一张表记录验证结果开始时今日值、昨日值、跨天后的今日值三者前后关系必须对得上。这一步做完流量累积程序就可以放心交付了。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进