心灵微语
世界上的一队小小的漂泊者呀,请留下你们的足印在我的文字里。
Troupe of little vagrants of the world, leave your footprints in my words.
使用情况:PLC一次需要传递大量数据给HMI;反之亦然!
当然了,这也是WinCC的一个小漏洞,就是在Tags点数有限的情况下,可以使用这种方法来扩展点数。
提醒:此方式下。PLC与HMI只能使用“字节”进行交互。
以下重点阐述“浮点数”交互的问题!关于“DINT”或“INT”,大家可以参照“浮点数”的交互方式。其实“浮点数”交互时,依据的也就是“DINT”型数据。
举例:REAL:A(保留小数点后两位)
DINT:B
推导:B=REAL_To_DINT(A*100.0)
A= DINT_To_REAL(B)/100.0
通过上述,我们很容易得出一个结论:可以操作的“浮点数”范围应限制在“-21474836.48~21474836.47”内,也就是其扩大100倍后,在一个“DINT”范围内。
这里建议大家将“浮点数”范围限制在“-20000000.00~20000000.00”,当超出范围时,HMI和PLC中应有相应的防护、报警措施。(以下文中并没有具体给出防护、报警措施)
数据交互时,为了保证数据的有效性,①这里还简单的做了一下“和校验”,当然亦可以扩展其他的校验方式。(校验必须要有)②还需要增加检验 “PLC与HMI”是否断线从而保证交互数据的有效性!
“PLC与HMI”之间断线判断方法:
PLC发送递增数据至HMI,判断“当前周期数据”与“上一周期数据”是否不一样: ①“不相等”,即通讯正常; ②“相等”,且持续“一段时间”(5~10秒),即通讯异常!
反之:HMI发送递增数据至PLC,判断方法和上面一样!
一、数据方向:
---PLC To HMI(HMI From PLC)
1、PLC工作:
PLC创建“DB1”数据块,注意创建的数据类型是“DINT”;
将浮点数转换为双整数,并存入DB1中。(这里将要传递的数据,逐一转换后,存入DB1中)
定义:REAL:A(保留小数点后两位) DINT:B
推导:B= REAL_To_DINT(A*100.0)
PLC中计算和校验,注意这里的数据类型是”DINT”和“DWORD”。
提供给HMI做判断!
2、HMI工作:
创建“原始数据类型”变量,这里建议:一个“原始数据类型”变量最多可以有400个字节,即100个“REAL”数据或“DINT” 数据
若想交互更多数据,可以新建多个“原始数据类型”变量。
但一定要注意传输量限制(小于16K)。
创建显示用的“内部变量”
创建脚本程序
//***************************************************************************************
// Define Variable定义变量
// Define Read Variable
BYTE Read_A [400] ; // HMI From PLC ReallyVariable
DWORD Read_B [100] ; // Change Type Variable
LONG Read_C [100] ; // Change Type Variable
FLOAT Read_D [100] ; // HMI Variable
DWORD Read_E , Read_F ;
// Public Variable
INT i , j ;
// Read Program
// HMI Read PLC读取数据
GetTagRaw ( "Read_Raw0" , Read_A , 400 ) ;
// HMI From PLC Really Variable拼装数据
for(i=0;i<100;i++)
{
j = i * 4 ;
Read_B [ i ] = ( DWORD ) ( ( Read_A [ j ] * 16777216 ) +( Read_A [ j + 1 ] * 65536 ) + ( Read_A [ j + 2 ] * 256 ) + Read_A [ j + 3 ] );
}
// Change Variable Type数据类型转换和数据校验计算
// Value Check
Read_E =0 ;
for ( i = 0 ; i < 100 ; i++ )
{
Read_E = Read_E + Read_B [ i ] ; // Value Check
Read_C [ i ] = ( LONG ) Read_B [ i ] ; // Change Variable Type
Read_D [ i ] = ( ( FLOAT ) Read_C [ i ] ) / 100.0; // ChangeVariable Type
}
Read_F = Read_E ^ 0xFFFFFFFF ; // Value Check
// Gain PLC Variable数据写入“内部变量”中
SetTagFloat ( "Read0" ,Read_D [ 0 ] ) ;
SetTagFloat ( "Read1" ,Read_D [ 1 ] ) ;
SetTagFloat ( "Read2" ,Read_D [ 2 ] ) ;
SetTagFloat ( "Read3" ,Read_D [ 3 ] ) ;
SetTagFloat ( "Read4" ,Read_D [ 4 ] ) ;
// ......此处省略
SetTagFloat ( "Read95" ,Read_D [ 95 ] ) ;
SetTagFloat ( "Read96" ,Read_D [ 96 ] ) ;
SetTagFloat ( "Read97" ,Read_D [ 97 ] ) ;
SetTagFloat ( "Read98" ,Read_D [ 98 ] ) ;
SetTagFloat ( "Read99" ,Read_D [ 99 ] ) ;
以下是数据校验判断(判断来至PLC的校验数据)
if ( ( Read_E == GetTagDWord( "Read_Check1" ) )& ( Read_F == GetTagDWord( "Read _Check2" ) ) )
{
SetTagBit ( "Read_Good" , 1 ) ;
SetTagBit ( "Read_Bad" , 0 ) ;
}
else
{
SetTagBit ( "Read_Good" , 0 ) ;
SetTagBit ( "Read_Bad" , 1 ) ;
}
//***************************************************************************************
扩展:
当需要交互更多数据时,若想交互500个“浮点数”。只需要增加以下部分:(以下为举例)
(以下程序为了可读性,定义的变量较多,当然也可以适当的减少!)
/***************************************************************************************
// Define Variable定义变量
// Define Read Variable
BYTE Read_A0 [400] ;
BYTE Read_A1 [400] ;
BYTE Read_A2 [400] ;
BYTE Read_A3 [400] ;
BYTE Read_A4 [400] ;
DWORD Read_B0 [100] ;
DWORD Read_B1 [100] ;
DWORD Read_B2 [100] ;
DWORD Read_B3 [100] ;
DWORD Read_B4 [100] ;
LONG Read_C0 [100] ;
LONG Read_C1 [100] ;
LONG Read_C2 [100] ;
LONG Read_C3 [100] ;
LONG Read_C4 [100] ;
FLOAT Read_D0 [100] ;
FLOAT Read_D1 [100] ;
FLOAT Read_D2 [100] ;
FLOAT Read_D3 [100] ;
FLOAT Read_D4 [100] ;
DWORD Read_E , Read_F ;
// Public Variable
INT i , j ;
// Read Program
// HMI Read PLC读取数据
GetTagRaw ( "Read_Raw0" , Read_A0 , 400 ) ;
GetTagRaw ( "Read_Raw1" , Read_A1 , 400 ) ;
GetTagRaw ( "Read_Raw2" , Read_A2 , 400 ) ;
GetTagRaw ( "Read_Raw3" , Read_A3 , 400 ) ;
GetTagRaw ( "Read_Raw4" , Read_A4 , 400 ) ;
// HMI From PLC Really Variable拼装数据
for(i=0;i<100;i++)
{
j = i * 4 ;
Read_B0 [ i ] = ( DWORD ) ( ( Read_A0 [ j ] * 16777216 )+ ( Read_A0 [ j + 1 ] * 65536 ) + ( Read_A0 [ j + 2 ] * 256 ) + Read_A0 [ j + 3] ) ;
Read_B1 [ i ] = ( DWORD ) ( ( Read_A1 [ j ] * 16777216 )+ ( Read_A1 [ j + 1 ] * 65536 ) + ( Read_A1 [ j + 2 ] * 256 ) + Read_A1 [ j + 3] ) ;
Read_B2 [ i ] = ( DWORD ) ( ( Read_A2 [ j ] * 16777216 )+ ( Read_A2 [ j + 1 ] * 65536 ) + ( Read_A2 [ j + 2 ] * 256 ) + Read_A2 [ j + 3] ) ;
Read_B3 [ i ] = ( DWORD ) ( ( Read_A3 [ j ] * 16777216 )+ ( Read_A3 [ j + 1 ] * 65536 ) + ( Read_A3 [ j + 2 ] * 256 ) + Read_A3 [ j + 3] ) ;
Read_B4 [ i ] = ( DWORD ) ( ( Read_A4 [ j ] * 16777216 )+ ( Read_A4 [ j + 1 ] * 65536 ) + ( Read_A4 [ j + 2 ] * 256 ) + Read_A4 [ j + 3] ) ;
}
// Change Variable Type数据类型转换和数据校验计算
// Value Check
Read_E =0 ;
for ( i = 0 ; i < 100 ; i++ )
{
Read_E = Read_E + Read_B0 [ i ] + Read_B1 [ i ] + Read_B2[ i ] + Read_B3 [ i ] + Read_B4 [ i ] ;
Read_C0 [ i ] = ( LONG ) Read_B0 [ i ] ;
Read_C1 [ i ] = ( LONG ) Read_B1 [ i ] ;
Read_C2 [ i ] = ( LONG ) Read_B2 [ i ] ;
Read_C3 [ i ] = ( LONG ) Read_B3 [ i ] ;
Read_C4 [ i ] = ( LONG ) Read_B4 [ i ] ;
Read_D0 [ i ] = ( ( FLOAT ) Read_C0 [ i ] ) / 100.0;
Read_D1 [ i ] = ( ( FLOAT ) Read_C1 [ i ] ) / 100.0;
Read_D2 [ i ] = ( ( FLOAT ) Read_C2 [ i ] ) / 100.0;
Read_D3 [ i ] = ( ( FLOAT ) Read_C3 [ i ] ) / 100.0;
Read_D4 [ i ] = ( ( FLOAT ) Read_C4 [ i ] ) / 100.0;
}
Read_F = Read_E ^ 0xFFFFFFFF ;
/***************************************************************************************
本文内容提供下载:
在自动化制造公众号聊天界面
回复“数据”,直接下载
二、数据方向:
----PLC From HMI(HMI To PLC)
1、PLC工作:
PLC创建“DB3”数据块,注意创建的数据类型是“DINT”;
取出DB3中数据,将双整数转换为浮点数。(这里将要转换的数据,逐一从DB3中取出,进行转换)
定义:REAL:A(保留小数点后两位) DINT:B
推导:A= DINT_To_REAL(B)/100.0
PLC中计算“和校验”,注意这里的数据类型是”DINT”和“DWORD”。
判断来至HMI的“校验数据”!
2、HMI工作:
创建“原始数据类型”变量,这里建议:一个“原始数据类型”变量最多可以有400个字节,即100个“REAL”数据或“DINT” 数据。
若想交互更多数据,可以新建多个“原始数据类型”变量。
但一定要注意传输量限制(小于16K)。
创建设置用的“内部变量”
创建脚本程序
//***************************************************************************************
// Define Variable定义变量
// Define Write Variable
BYTE Write_A [400] ; // HMI To PLC Really Variable
DWORD Write_B [100] ; // Change Type Variable
LONG Write_C [100] ; // Change Type Variable
FLOAT Write_D [100] ; // HMI Variable
DWORD Write_E , Write_F ;
// Public Variable
INT i , j ;
// Write Program
// Gain HMI Variable获取HMI设置的数据,即“内部变量”的数据
Write_D [ 0 ] = GetTagFloat ( "Write0" ) ;
Write_D [ 1 ] = GetTagFloat ( "Write1" ) ;
Write_D [ 2 ] = GetTagFloat ( "Write2" ) ;
Write_D [ 3 ] = GetTagFloat ( "Write3" ) ;
Write_D [ 4 ] = GetTagFloat ( "Write4" ) ;
// ......此处省略
Write_D [ 95 ] = GetTagFloat ( "Write95" );
Write_D [ 96 ] = GetTagFloat ( "Write96" ) ;
Write_D [ 97 ] = GetTagFloat ( "Write97" ) ;
Write_D [ 98 ] = GetTagFloat ( "Write98" ) ;
Write_D [ 99 ] = GetTagFloat ( "Write99" ) ;
// Change Variable Type 数据类型转换和数据校验计算
// Value Check
Write_E =0 ;
for ( i = 0 ; i < 100 ; i++ )
{
Write_C [ i ] = ( LONG ) ( Write_D [ i ] * 100.0 ) ; // ChangeVariable Type
Write_B [ i ] = ( DWORD ) Write_C [ i ] ; // ChangeVariable Type
Write_E = Write_E + Write_B [ i ] ; // ValueCheck
}
Write_F = Write_E ^ 0xFFFFFFFF ; // Value Check
// HMI To PLC Really Variable拆分数据
for ( i = 0 ; i < 100 ; i++ )
{
j = i * 4 ;
Write_A [ j ] = ( BYTE ) ( Write_B [ i ] / 16777216 ) ;
Write_A [ j + 1 ] = ( BYTE ) ( ( Write_B [ i ] %16777216) / 65536 ) ;
Write_A [ j + 2 ] = ( BYTE ) ( ( ( Write_B [ i ]%16777216 ) % 65536 ) / 256 ) ;
Write_A [ j + 3 ] = ( BYTE ) ( ( ( Write_B [ i ]%16777216 ) % 65536 ) % 256 ) ;
}
// HMI Write PLC 写入数据
SetTagRaw ( "Write_Raw0" , Write_A , 400 ) ;
SetTagDWord ( "Write_Check1" , Write_E) ;
SetTagDWord ( "Write_Check2" ,Write_F ) ;
//***************************************************************************************
扩展:
当需要交互更多数据时,若想交互500个“浮点数”。只需要增加以下部分:(以下为举例)
(以下程序为了可读性,定义的变量较多,当然也可以适当的减少!)
可以参照上文“PLC To HMI(HMI From PLC)”内容!
“REAL”数据交互时,PLC端使用的子程序:
//***************************************************************************************
定义:REAL:A(保留小数点后两位)
DINT:B
推导:B= REAL_To_DINT(A*100.0)
FUNCTION FC1:VOID
TITLE = 'Block Title'
VERSION: '1.0'
AUTHOR: BXL
// Block Parameters
VAR_INPUT
InV:REAL;
END_VAR
VAR_OUTPUT
OutV:DINT;
END_VAR
BEGIN
OutV:=TRUNC(InV*100.0);
END_FUNCTION
//***************************************************************************************
//***************************************************************************************
定义:REAL:A(保留小数点后两位)
DINT:B
推导:A= DINT_To_REAL(B)/100.0
FUNCTION FC3:VOID
TITLE = 'Block Title'
VERSION: '1.0'
AUTHOR: BXL
// Block Parameters
VAR_INPUT
InV:DINT;
END_VAR
VAR_OUTPUT
OutV:REAL;
END_VAR
VAR_TEMP
TempV:REAL;
END_VAR
BEGIN
TempV:=DINT_TO_REAL(InV);
OutV:=TempV/100.0;
END_FUNCTION
//***************************************************************************************
//***************************************************************************************
PLC端产生校验数据,提供个HMI端判断使用
FUNCTION FC11:VOID
TITLE = 'Block Title'
VERSION: '1.0'
AUTHOR: BXL
// Block Parameters
VAR_INPUT
DBx:WORD;
Address:INT;
Number:INT;
END_VAR
VAR_OUTPUT
CheckADD_V:DINT;
CheckXOR_V:DWORD;
END_VAR
VAR_TEMP
TempAddress:INT;
TempNumber:INT;
END_VAR
BEGIN
TempAddress:=Address;
CheckADD_V:=0;
FOR TempNumber:=1 TO Number BY 1 DO
CheckADD_V:=CheckADD_V+DWORD_TO_DINT(WORD_TO_BLOCK_DB(DBx).DD[TempAddress]);
TempAddress:=TempAddress+4;
END_FOR;
CheckXOR_V:=DINT_TO_DWORD(CheckADD_V) XOR 16#FFFFFFFF;
END_FUNCTION
//***************************************************************************************
//***************************************************************************************
PLC判断HMI端提供的校验数据
FUNCTION FC33:VOID
TITLE = 'Block Title'
VERSION: '1.0'
AUTHOR: BXL
// Block Parameters
VAR_INPUT
DBx:WORD;
Address:INT;
Number:INT;
HMIADD_V:DINT;
HMIXOR_V:DINT;
END_VAR
VAR_OUTPUT
CheckADD_V:DINT;
CheckXOR_V:DWORD;
Check_Good:BOOL;
Check_Bad:BOOL;
END_VAR
VAR_TEMP
TempAddress:INT;
TempNumber:INT;
END_VAR
BEGIN
TempAddress:=Address;
CheckADD_V:=0;
FOR TempNumber:=1 TO Number BY 1 DO CheckADD_V:=CheckADD_V+DWORD_TO_DINT(WORD_TO_BLOCK_DB(DBx).DD[TempAddress]);
TempAddress:=TempAddress+4;
END_FOR;
CheckXOR_V:=DINT_TO_DWORD(CheckADD_V) XOR 16#FFFFFFFF;
IF (CheckADD_V=HMIADD_V) AND (CheckXOR_V=(DINT_TO_DWORD(HMIXOR_V)))THEN
Check_Good:=TRUE;
Check_Bad:=FALSE;
ELSE
Check_Good:=FALSE;
Check_Bad:=TRUE;
END_IF;
END_FUNCTION
//***************************************************************************************
“DINT”数据交互时,PLC的操作:
和“REAL”数据交互时一样,就是少了“数据类型”转换的操作过程。
“DINT”数据交互时,HMI的操作:
脚本事例如下,其他内容都一样,只要注意“内部变量”的数据类型为“DINT”就行了。
网友评论