|
心灵微语 世界上的一队小小的漂泊者呀,请留下你们的足印在我的文字里。 Troupe of little vagrants of the world, leave your footprints in my words. 当然了,这也是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 INT; 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 INT; 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 INT; CheckXOR_V WORD; 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 INT; HMIXOR_V INT; END_VAR VAR_OUTPUT CheckADD_V INT; CheckXOR_V WORD; 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”就行了。
|