FUNCTION_BLOCK "模拟量转换"
TITLE = 模拟量输入转换
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : SDZYG2000
FAMILY : 77-1500
NAME : AI_OUT
VERSION : 1.0
//
// 模拟量输入量程批量转换
//
// Block Parameters
VAR_INPUT
ADDRESS : Int := 512; // 开始的PIW地址
NUM : Int := 1; // 仪表数量即多少个PIW地址
Sdata : DInt := 2;
DATA_NUM : DInt; // 用于存放数据的量程 偏差设定
VALUE_NUM : DInt; // 存放输出结果
END_VAR
VAR
K1 : Real;
K2 : Real;
END_VAR
VAR_TEMP
I : DInt; // 循环变量
IW_INT_VAL : Int;
IW_VAL : Real;
HI_VAL : Real;
LI_VAL : Real;
OF_VAL : Real;
DIP_VAL : Byte;
TEMP : Real;
END_VAR
BEGIN
//###########################################################
//采用FC105相同的计算公式OUT = ((FLOAT (IN) -K1)/(K2-K1)) * (HI_LIM-LO_LIM) + LO_LIM
//增加一个修正偏差公式改为OUT = ((FLOAT (IN) -K1)/(K2-K1)) * (HI_LIM-LO_LIM) + LO_LIM + OFFSET
//循环批量转换循环体
//##########################################################
(* //参考数据类型
TYPE "转换"
VERSION : 0.1
STRUCT
VALUE : Real; // 转换后输出值
ERR : Byte; // 错误值 通道值超出范围即输出0位为1
END_STRUCT;
END_TYPE
//-----------------
TYPE "量程"
VERSION : 0.1
STRUCT
H : Real := 1000.0; // 量程上限设定值
L : Real := 0.0; // 量程下限设定值
OFF : Real := 2.0; // 修正偏差设定值
DIP : Byte; // 双极性设置
END_STRUCT;
END_TYPE
*)
(* //参数DB块数据结构
DATA_BLOCK "转换结果"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
NON_RETAIN
STRUCT
Static_1 : Array[0..50] of "转换";
END_STRUCT;
BEGIN
END_DATA_BLOCK
//----------------------
DATA_BLOCK "DB10"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
NON_RETAIN
STRUCT
A11 : Array[0..50] of "量程";
END_STRUCT;
BEGIN
END_DATA_BLOCK
*)
FOR #I := 1 TO #NUM BY 1 DO
//读取IW地址以及数据块的参数
//------------------------------------------
(*#IW_INT_VAL := WORD_TO_INT(PEEK_WORD(area := 16#81, dbNumber := 0, byteOffset := #ADDRESS + (#I - 1) * 2));//数据有正负性,必须转换为INT格式*)
#IW_INT_VAL := WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber :=#Sdata, byteOffset := #ADDRESS + (#I - 1) * 2));//数据有正负性,必须转换为INT格式
#IW_VAL := DINT_TO_REAL(INT_TO_DINT(#IW_INT_VAL));
#HI_VAL := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14));
#LI_VAL := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14 + 4));
#OF_VAL := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14 + 8));
#DIP_VAL := PEEK_BYTE(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14 + 12);
//-------------------------------------------
//判断是否是双极性
//读取数据库参数判断是否是双极性,0为单极性,>=1为双极性并判断通道值是否溢出
//-----------------------------------------------------
IF #DIP_VAL >= 16#1 THEN
//双极性
#K1 := -27648.0;
#K2 := 27648.0;
//读取IW数值通过数值判断数值是否异常若异常则将异常状态写入数据块,异常就给错误字0位写1
IF #IW_INT_VAL <= -27649 OR #IW_INT_VAL >= 27649 THEN
POKE_BOOL(area := 16#84,
dbNumber := #VALUE_NUM,
byteOffset := (#I - 1) * 6 + 4,
bitOffset := 0,
value := TRUE);
#TEMP := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #VALUE_NUM, byteOffset := (#I - 1) * 6)); //不在量程范围内则读取当前输出的值给TEMP变量
// #TEMP := 0.0;//不在量程范围内输出为0;
ELSE
POKE_BOOL(area := 16#84,
dbNumber := #VALUE_NUM,
byteOffset := (#I - 1) * 6 + 4,
bitOffset := 0,
value := FALSE);
//若在量程范围内就做量程转换
//#TEMP := (#IW_VAL - #K1) / (#K2 - #K1) * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;
//算法优化
#TEMP := (#IW_VAL + 27648.0) / 55296.0 * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;
END_IF;
ELSE
//单极性
#K1 := 0.0;
#K2 := 27648.0;
//读取IW数值通过数值判断数值是否异常若异常则将异常状态写入数据块,异常就给错误字0位写1
IF (#IW_INT_VAL >= 27649) OR (#IW_INT_VAL <= -1) THEN
// IF #IW_INT_VAL<=-1 THEN
POKE_BOOL(area := 16#84, dbNumber := #VALUE_NUM, byteOffset := (#I - 1) * 6 + 4, bitOffset := 0,value := TRUE);
#TEMP := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #VALUE_NUM, byteOffset := (#I - 1) * 6));//不在量程范围内则读取当前输出的值给TEMP变量
//不在量程范围内输出为0;
// #TEMP := 0.0;
ELSE
POKE_BOOL(area := 16#84,
dbNumber := #VALUE_NUM,
byteOffset := (#I - 1) * 6 + 4,
bitOffset := 0,
value := FALSE);
//若在量程范围内就做量程转换
//#TEMP := (#IW_VAL - #K1) / (#K2 - #K1) * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;
//算法优化
#TEMP := #IW_VAL / 27648.0 * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;
END_IF;
END_IF;
//-------------------------------------------------------
POKE(area := 16#84,dbNumber := #VALUE_NUM, byteOffset := (#I - 1) * 6,value := REAL_TO_DWORD(#TEMP));
END_FOR;
END_FUNCTION_BLOCK