西门子官网的程序是用德文书写的。必须将语言给位德文才可以使用。现将内部的程序转发。
建立一个FB块
IN中建立
名称 VALUE 数据类型 real
名称 Interval 数据类型 time 计量单位的时间例如:30M3/H 则输入 T#1H
名称 Cycle 数据类型 time 扫描循环的时间 放在OB35中则是T#100ms OB36则是T#50ms
名称 Com_RST 数据类型 bool 复位开关,ON时清零,需要在扫描时间内,需要将此位置位时间大于
//////////////////////////////////OB35的中断扫描时间。
OUT中建立
名称 TOTAL 数据类型 real 累计值
Stat中建立
名称 Accum 数据类型 real
Temp中建立
名称 tInterval 数据类型 real
名称 tCycle 数据类型 real
程序段1中输入
A #COM_RST
JCN NW2
L 0.0
T #ACCUM
T #TOTAL
SET
SAVE
BEU
程序段2中输入
NW2: NOP 0
L #INTERVAL
DTR
T #tINTERVAL
L #CYCLE
DTR
T #tCYCLE
程序段3中输入
L #VALUE
L #tCYCLE
*R
L #tINTERVAL
/R
L #ACCUM
+R
T #ACCUM
T #TOTAL
程序段4中输入
SET
SAVE
BEU
保存为FB功能块
说明:次功能块只能接受real值。直接读取上来的值需要经过fc105的转换后或自行转换为32位浮点数后再使用。
应用实例:
你觉得有用,帮忙顶一下。
上面的例子在累计数特别大时,容易出现计数不准,偏差比较大。下面的程序更改后比较好点。
代码如下:
文字的上传不上来。用图片粘贴吧。
提供一个工程附件。累计块为FC1001.
附件内包含源程序,以及简易的模拟量转换源码。以及自己编写的一点逻辑程序源码。
1200&1500代码
FUNCTION_BLOCK "TOT"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : Tyfixn
VERSION : 0.1
VAR_INPUT
_Hi : Real; // 现场流量计,上限量程。
_InterVal : Time; // 此时间为量程中标定的时间。例如30m3/h则为1h,30L/m则为60s,
_Cycle : Time; // 次时间为循环扫描时间,例如OB35则为100ms,OB32则为1s
_inPV : Real; // 实际输入值。
_inLoQC : Real; // 小信号切除值。
END_VAR
VAR_OUTPUT
_TOT_value : Real; // 累计值
END_VAR
VAR_IN_OUT
_Start_Stop : Bool; // 启动停止累计操作端。
_Com_RST : Bool; // 复位操作端。此端口置1后自动复位。
END_VAR
VAR
_TOTAL_L : Real; // 流量累计输出值,低位。
_TOTAL_H : Real; // 流量累计输出值,高位。
_start_Temp : Bool;
END_VAR
VAR_TEMP
_t_Value : Real;
_t_Cycle : Real;
_t_InterVal : Real;
_var1 : Real;
END_VAR
BEGIN
#_t_Cycle := DINT_TO_REAL(TIME_TO_DINT(#_Cycle)); //将时间数据转换为实数。
#_t_InterVal := DINT_TO_REAL(TIME_TO_DINT(#_InterVal)); //将时间数据转换为实数。
//#_var1 := SCALE(IN := #_inPV, HI_LIM := #_Hi, LO_LIM := 0, BIPOLAR := 0, OUT => #_t_Value);
//复位清零操作
IF #_Com_RST THEN
#_TOTAL_H := 0;
#_TOTAL_L := 0;
#_Com_RST := FALSE;
END_IF;
//切除小信号,当低于切除值时,将累积信号置0;
IF #_inPV > #_inLoQC THEN
#_var1 := 0;
ELSE
#_var1 := #_inPV;
END_IF;
//当输入启动信号到达后,立即开启累积计数,当启动信号停止(结束)后,判断信号值是否到0,到0后立即停止累积计数。
//下面这节是根据实际工况改写的一节延时计量,
//
// IF #_Start_Stop THEN
// #_start_Temp := 1;
// ELSIF #_var1 = 0 THEN
// #_start_Temp := 0;
// END_IF;
//
//正常使用下面这一节
IF #_Start_Stop THEN
#_start_Temp := 1;
ELSE
#_start_Temp := 0;
END_IF;
//开始累积
IF #_start_Temp THEN
#_TOTAL_L := #_var1 * #_t_Cycle / #_t_InterVal + #_TOTAL_L;
END_IF;
//消除极大数加极小数的累加错误
IF #_TOTAL_L > 1000.0 THEN
#_TOTAL_H := #_TOTAL_H + 1;
#_TOTAL_L := #_TOTAL_L - 1000.0;
END_IF;
//输出结果
#_TOT_value :=( #_TOTAL_H * 1000)+ #_TOTAL_L;
END_FUNCTION_BLOCK
更改一个小错误。
回复内容:
对: 撞破烂钟——王者之师 引用 tyfeixian 的回复内容: 引用 撞破烂钟... 内容的回复!
本来不想回复的。真不知道你是不是编程的人员?
在FB块中预留了一个BOOL量的接口COM_RST,已说明这个接口为ON的时间不少于扫描时间(及OB30-38的中断事件),在上位机Wincc中,在STEP7中的OB10提供的时间中,难道不能够触发此接口吗?
本段程序只是提供一个累计值,而且留出了必须的接口,为能够在OB36中(及50ms时间)多个累计能够中断响应过来,只做了累计的计算。
向你说的日报月报年报等等需要自动清零,完全可以在主程序中加个比较判断触发清零。
上位机的报表自动保存也是变量触发,这个变量也可以触发清零。
有太多的方法。请您动动脑筋吧。