心靈微語
世界上的一隊小小的漂泊者呀,請留下你們的足印在我的文字裡。
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”就行了。
閱讀更多 工控自動化聯盟 的文章