简介:面向西门子S7-1200/1500系列PLC工程师,提供适用于水处理、化工、能源等连续计量场景的流量累计功能块库,支持脉冲与模拟量输入累积,遵循IEC 61131-3标准,可直接在TIA Portal V15中导入调用,无需额外编译适配。资源包共26个文件,大小约1003KB,包含al15项目文件、完整backup备份、多个时间戳版本快照,以及XRef交叉引用、System配置、UserFiles自定义文件和Logs日志等结构化内容,另有png图示、xml数据与README说明辅助理解,目录清晰便于定位。已有53人学习该资源。工程人员可直接使用FB功能块进行参数化配置,绑定OB组织块与DB数据块,快速实现连续流体总量计量;同时保留中文命名目录,方便检索复用,适合需要标准化累积计量解决方案的PLC开发者。
1. 流量累计功能块库是什么:月底对不上账,多半是瞬时流量直接累加惹的祸
做水厂、市政管网、大棚灌溉这类项目的工程师,十有八九被流量累计折腾过。现场流量计给的是瞬时流量,月底报表要的却是累计量;很多人在博图里用梯形图“每个扫描周期加一次”,看着逻辑简单,到了结算时却对不上账。这套西门子TIA Portal V15专用流量累计功能块库,核心就是把瞬时流量积分、掉电保持、清零命令、单位换算这些容易翻车的细节封装成标准功能块,再配上完整项目文件和备份,拖进S7-1500或S7-1200项目里就能用。刚上手博图的新人可以照抄,老手也能拿它当模板,省掉每次重写累计逻辑的时间。
2. 用SCL搭建流量累计功能块:先确立积分模型,再谈代码
2.1 为什么选SCL而不是梯形图来写累计功能块
流量累计的核心是数学运算和状态记忆。梯形图的强项在逻辑联锁,而累计逻辑要做的除法、浮点累加、上下限判断,在SCL里读出来就是一行公式,在梯形图里却要拆成一长串比较和计算块。调试时SCL一眼能看出逻辑关系,别人接手维护也容易,这是选型上的第一点。
第二点,功能块本身应该用FB而不是FC。FB自带背景数据块(背景DB),静态变量可以做成保持性数据,这一步直接决定断电后累计量能不能保住。流量累计这种“写完就不想再碰”的逻辑,做成标准FB放进库,在项目之间拖来拖去复用,比每次重新复制FC省心得多。西门子博图V15的库面板里,一个FB从全局库拖进新项目,背景DB会自动跟着生成,这也是功能块库之所以叫“库”的原因。
2.2 积分模型:把瞬时流量折算到每个调用周期的增量
流量累计的本质是对瞬时流量做时间积分,更直白地说,是每个调用周期里“瞬时流量×时间片”的累加。为什么强调时间片?因为瞬时流量的单位是m³/h,一小时有3600秒,如果功能块每100毫秒被调用一次,那每个周期要加的值是:
每个周期增量(m³) = 瞬时流量(m³/h) × 周期(s) / 3600这句话是整个功能块库的核心,后面的代码都围绕它展开。周期设成可传入的参数,而不是在功能块内部写死,是因为不同项目调用位置不同——有的放在循环中断OB30里100ms调用一次,有的放在OB32里1秒调用一次。周期传得准,累计量才准;传错周期,逻辑再漂亮也是摆设。
下面是一段可直接抄进TIA Portal V15的SCL功能块骨架:
FUNCTION_BLOCK FB_FlowTotalizer VERSION : 0.1 VAR_INPUT i_FlowRate : REAL; // 瞬时流量,单位 m³/h i_CycleTime_s : REAL := 1.0; // 调用周期,单位 秒 i_ResetCmd : BOOL; // 清零命令,上升沿有效 END_VAR VAR_OUTPUT q_Total_m3 : LREAL; // 当前累计量,单位 m³ q_Valid : BOOL; // 流量信号是否有效 END_VAR VAR v_PrevReset : BOOL; // 上一次清零命令状态,用于上升沿检测 v_Total : LREAL; // 累计量内部存储,需在背景DB中设为保持 END_VAR BEGIN // 清零命令上升沿检测:按下瞬间清一次,持续按住不重复清 IF i_ResetCmd AND NOT v_PrevReset THEN v_Total := 0.0; END_IF; v_PrevReset := i_ResetCmd; // 流量与周期合法性判断,防止负流量和异常周期把累计带偏 IF i_FlowRate >= 0.0 AND i_CycleTime_s > 0.0 AND i_CycleTime_s <= 600.0 THEN // 瞬时流量 m³/h 除以3600得到每秒体积,再乘周期得到本周期增量 v_Total := v_Total + (REAL_TO_LREAL(i_FlowRate) * REAL_TO_LREAL(i_CycleTime_s)) / 3600.0; q_Valid := TRUE; ELSE q_Valid := FALSE; END_IF; // 输出当前累计量,供HMI和上位机读取 q_Total_m3 := v_Total; END_FUNCTION_BLOCK代码里的几个关键点:清零用了上升沿检测,i_ResetCmd AND NOT v_PrevReset是标准的沿提取写法,比电平清零安全得多;累计计算里先把REAL转成LREAL再乘除,避免小增量加进大数时被舍掉;i_CycleTime_s上限设600秒,防止有人误传一个巨大周期导致数据突变。这个FB的输入输出关系很干净:喂给它瞬时流量和调用周期,它吐累计量,清零命令单独走一路,调试时思路非常顺。
2.3 保持性设计:让掉电不丢累计量
功能块逻辑写得再对,背景DB的保持性没设,上电一样从零开始。在TIA Portal V15里,选中FB的背景DB(比如TOTALIZER_DB),在属性窗口中把“保持性”从“非保持”改成“保持”。这里的保持,指的是CPU掉电后,保持性存储区里这些变量的值不被清除。S7-1500的保持性存储区大小受CPU型号限制,导航到CPU属性→保持性存储区,能看到已用和剩余空间。
常见做法是:累计量这种一天到晚都在变的工艺数据,保持性存储区里只放累计值本身,像各种中间变量、上一次清零状态这类辅助变量就不要开保持,省空间。如果项目用的是S7-1200且固件不支持LREAL,可以把v_Total降级为REAL,代价是累计量到百万级以后精度下降,这时就要考虑把累计量拆成整数部分和小数部分分开存,具体拆分技巧会在第4章展开。
3. 把功能块库落地到TIA Portal V15项目:建库、调用、HMI联动一条线
3.1 从库面板拖一个FB到项目:全局库和项目库的区别
在博图右侧的“库”面板里,有“项目库”和“全局库”两类。项目库跟着当前项目走,项目文件发给别人时里面就带这些块;全局库存在本机工作区,跨项目复用。“专用流量累计功能块库”实际使用中建议放在全局库,这样下一个项目打开就能直接拖,不用反复导入。归档时也可以按项目名分目录,库文件、文档、程序备份三者分开,避免半年后找不到当初的版本。
建库的常规做法:在库面板新建一个名为FlowTotalizer_Lib的全局库,把FB_FlowTotalizer从“程序块”拖到库的“模板”或“类型”目录下,右键可以对库版本做管理。每次迭代后递增版本号,项目里引用的是某一固定版本,不会因为库更新导致已经运行的项目悄悄变逻辑。这里要注意一点:库文件和项目文件是两个不同的载体,备份项目时不要以为库也跟着备走了,库要单独归档。
3.2 用OB30固定周期调用FB,避开扫描周期误差
把功能块直接扔在OB1里调用也可以,但OB1的扫描周期会随着程序量、通讯任务波动,流量不变时累计速度也会漂。常见做法是专门开一个循环中断OB,在里面调用FB。循环中断OB的周期由硬件定时器决定,稳定得多。具体操作:在“添加新块”里选择“循环中断”,比如OB30,把中断时间设为100ms(0.1秒),然后在OB30里写上调用语句:
// OB30:每100ms执行一次流量累计 "TOTALIZER_DB"( i_FlowRate := "ProcessData".Flow, // 来自模拟量转换后的瞬时流量 i_CycleTime_s := 0.1, // 必须和OB30中断周期一致 i_ResetCmd := "HMI_Tags".ResetTotal // 操作员点击HMI清零按钮 );这段代码在OB30里每100毫秒被硬件中断触发一次。把i_CycleTime_s设为0.1是关键,它必须和OB30的周期严格一致;改中断周期时必须同步改这个参数,否则累计速度会按错误的时间片累加。TOTALIZER_DB是FB_FlowTotalizer的背景DB,实例化前缀可以自己改,但调用处的输入输出变量名要和FB接口定义一致。如果FB内部运算出错,它的ENO状态会变成FALSE,累计输出不再刷新,调试时要留意这个信号,别在HMI上误以为是流量为零。
提示:循环中断OB的执行时间要控制在几十毫秒以内,否则会影响主循环。流量累计本身只是几条浮点运算,不会拖慢OB30,但不要在OB30里去调用其他重型块。
3.3 HMI和上位机读累计量的注意点:跨网段通讯与清零时序
累计量最终要显示到触摸屏或监控画面上。q_Total_m3是LREAL类型(64位浮点),部分HMI或组态软件对64位浮点的支持不完整,最常见的现象是小数位丢失或者数值跳变。常见做法是在PLC里把LREAL转换成REAL后再给HMI,或者直接把累计值转成字符串格式传给HMI显示。后者在WINCC较常用,普通触摸屏上更省事的做法是直接显示REAL,但量程大时要接受精度损失。
跨网段通讯是另一个高频踩坑点。很多项目里PLC在工业以太网段(比如192.168.0.x),触摸屏在办公网段(比如192.168.1.x),中间隔路由器或网关。MCGS触摸屏跟西门子1500做跨网段通讯时,V15组态里触摸屏连接的IP要填PLC所在网段的IP,路由器路由表必须能转发这两个网段,否则通讯状态看着是“已连接”但数据不更新。调试时先在同一个网段里跑通,再改跨网段,能省一半排查时间。
清零时序上,上位机读累计量和PLC侧清零命令之间要有间隔。常见的错误是HMI脚本里“读当前值→写入清零变量”一气呵成,结果PLC刚把累计值清零,上位机读到的还是清零前的旧值,报表就缺了一段。常见做法是:上位机读取累计量成功后,延时几百毫秒再下发清零,或者PLC在清零前把当前累计快照存到另一个变量里供上位机事后读取。
4. 流量累计最容易翻车的5个坑:从扫描周期到单位倍率换算
这一章是这套功能块在实际项目里最容易出问题的五个地方,每一条都按“现象→原因→解决”来写,现场遇到类似的可以直接对号入座。
4.1 在OB1里直接累加:流量不变,累计速度却漂移
现象:同一个流量,白天累计走得快,晚上累计走得慢,操作员说这个累计是“随缘”的。
原因:OB1的扫描周期不是固定的。程序变大、通讯任务多、HMI读写频繁时,扫描周期可能从5ms漂到15ms。如果累计逻辑写成每扫一次加一勺,实际时间片就不固定,流量不变但累计速度一直在变的,基本都栽在这里。
解决:把功能块挪到循环中断OB里,比如OB30设100ms。如果项目已经写了一大半不想动OB结构,也可以保留OB1调用,但把周期参数改成动态计算:在功能块外部用一个系统时间戳变量记录上一次调用的时刻,每次执行时用当前时间戳减上次时间戳,得到实际经过的秒数,作为i_CycleTime_s传入。两者相比,固定周期OB明显省心。
4.2 REAL精度不够:累计值到千万级以后“加不上数”
现象:累计量到大约几百万后不再增长,或者增长一下就是一大截,报表完全没法看。
原因:REAL是32位浮点,有效精度约7位十进制。当累计值达到千万量级,浮点数的最小可分辨单位已经接近甚至超过1.0,每个周期加进去不到1的小增量会被舍入掉。很多水厂、化工项目一年累计几百万上千万吨,正好踩在这个精度边缘上。
解决:把功能块内部累计变量换成LREAL,这是最直接的方案。S7-1500完全支持,S7-1200要确认固件版本。另一个保底方案是把累计量拆成两个变量:DINT存整数部分,REAL存小数部分,小数满1就进位给整数,等于在软件里实现了“双浮点”精度。拆分核心代码很短:
// 小数部分累计,满1.0进位给整数部分 v_Frac := v_Frac + (REAL_TO_LREAL(i_FlowRate) * REAL_TO_LREAL(i_CycleTime_s)) / 3600.0; IF v_Frac >= 1.0 THEN v_Int := v_Int + 1; // 整数部分进位 v_Frac := v_Frac - 1.0; // 小数部分减掉进位的1 END_IF;这里v_Int是DINT,v_Frac是LREAL,整数部分只在进位时加1,永远不会因为REAL精度丢数。缺点是多个输出变量要处理,HMI显示要拼两个字段,但换来的是十年都不会累坏的总量。量程大的水务和冶金项目,强烈建议直接用拆分方案。
4.3 断电后累计从零开始:背景DB的保持性没有生效
现象:设备停电检修,再送电,累计量清零,操作员火冒三丈。
原因:背景DB的“保持性”属性没有开。TIA Portal V15里新建的DB默认是非保持的,掉电后RAM里的数据全部清掉,只有保持性区域的数据才保留。很多第一次用FB的同事就栽在这个默认设置上。
解决:选中背景DB,在属性里把“保持性”改为“保持”。下载项目时,如果CPU属性里设置了“重置为出厂设置”,保持性区域一样会被清空,所以断电恢复和程序重置是两件不同的事,都要覆盖测试一遍。另外S7-1500保持性存储区大小有上限,如果功能块里堆了大量保持变量,下载会报“保持性存储区不够”,常见做法是只对累计值v_Total开保持,辅助变量全部设非保持。
4.4 清零命令的沿触发陷阱:按一次清了三次
现象:操作员在HMI上点一下清零,累计值确实归零了,但几秒后又自动归零一次,或者干脆一直归零,流量已经重新开始累计但数字不动。
原因:HMI按钮变量是“电平”型,只要按钮被按下且保持,PLC侧看到的i_ResetCmd一直是TRUE。如果编程时直接写“i_ResetCmd为真就清零”,那么按钮按住多久就清多久,之后流量累计永远加不上。另一种情况是通信闪断导致标志被重复置位,出现了多次沿。
解决:功能块内部必须做上升沿检测,也就是第2章代码里的IF i_ResetCmd AND NOT v_PrevReset。这行在梯形图工程里被漏掉的比例很高,特别是从S7-200 SMART转博图的工程师容易忽略——S7-200里用沿指令很顺手,到了博图想不起来。沿检测的本质是“只响应0到1的变化瞬间”,按钮按住不刷新,只清一次。另外HMI侧清零按钮建议用瞬动型(按下置位、松开复位),而不是切换型。
4.5 单位倍率差60倍:m³/h和L/min的记量口径不一致
现象:瞬时流量显示和对账单总量对不上,现场拿流量计自带表头一比对,差60倍或者3600倍。
原因:流量计输出单位不一定都是m³/h,常见还有L/min、L/s、kg/h。功能块内部按m³/h的公式算,如果外部把L/min直接喂进来,数值要乘3.6;把L/s直接喂进来,要乘3600。往往是DCS组态那边有人做过一次换算,PLC侧又做一次,来回折腾反而错了。
解决:功能块入口只收统一单位的瞬时值,换算在调用前做干净。常用换算因子记下面这个表:
| 原始单位 | 转换为m³/h的换算因子 | 说明 |
|---|---|---|
| m³/h | 1.0 | 功能块默认单位 |
| L/min | 0.06 | 除以1000再乘以60 |
| L/s | 3.6 | 除以1000再乘以3600 |
| m³/s | 3600.0 | 每秒体积换算到小时 |
在调用FB前,把原始流量乘以对应因子再赋给i_FlowRate。也可以在功能块上增加一个单位选择输入i_UnitMode,内部用CASE语句选因子,但更推荐统一在预处理里换算,这样FB的边界更清晰,也便于仪表和DCS对照。
5. 功能块验证与备份管理:用PLCSIM校准精度,给项目留后悔药
5.1 用固定流量仿真验证累计精度
功能块写得再仔细,不上仿真机验证心里没底。TIA Portal V15自带PLCSIM,专门干这件事。常见做法是建一个最小工程:一个OB30,一个FB_FlowTotalizer实例,用常量表直接赋值,让i_FlowRate恒定等于3600.0,i_CycleTime_s等于0.1。
按公式算,3600 m³/h的流量下每秒累计1 m³,每小时3600 m³。仿真运行1小时太慢,我习惯再组一组周期参数快速跑:如果周期设成0.001秒,1秒就等于1小时的时间片,可以快速验证线性,但必须明确这只是逻辑验证手段,不能替代真实周期下的长时间运行。验证时重点盯三点:累计量是否随时间线性增长;清零命令按住不放时是否只清一次;中途强制断开仿真再恢复,累计值是否保持。
5.2 项目备份与库复用:版本管理和归档规范
仿真验证通过后,就该把资产留清楚了。项目文件在V15里是.ap15后缀,功能块库可以独立归档。我自己的习惯是:全局库文件(FlowTotalizer_Lib)和项目文件分开存,库文件单独放一个目录,项目文件按“客户名_项目名_日期_版本号”命名。每次改库里的功能块,都先在库面板里生成一个新版本,再归档一次库文件。即使某一次改坏了,还能从上一版本拉回来。这个习惯救过我不少次,有一回在库版本迭代中把清零逻辑的沿检测写丢了,现场已经用旧版本跑了两周,归档文件还在,直接回滚,省了一场大事故。
备份的意义不只是防丢失。新项目开工,把库拖进工程,把OB30和HMI变量的命名照着上一套项目的规范复制,组态时间至少省两天。当初找这套带完整项目文件的功能块库来参考,也是在一次现场报表对不上的事故之后——别人踩过的坑,就是最值钱的文档。希望帮到你。
本文还有配套的精品资源,点击获取