為什么要解耦?
解釋這個問題之前,需要先大致介紹下LBP的功能。與以往所有西門子官方以及各民間組織提供的PLC庫函數(shù)不同,LBP實現(xiàn)了多觸摸屏的高仿彈出窗口設計。
所謂高仿,即其實原本觸摸屏是不支持窗口彈出的,或者功能復雜,嚴重依賴觸摸屏的編程功能,不容易實現(xiàn)標準化。
所以LBP就通過在PLC中的邏輯處理,判斷到觸摸屏上操作某個設備圖標時,程序中將此設備的所有參數(shù)的運行數(shù)據(jù)傳送到一個供觸摸屏通訊的公共數(shù)據(jù)區(qū),而觸摸屏上跳轉到設備的相關設置頁面,感覺上像是彈出了窗口。而這個彈出窗口與正常電腦上的彈出窗口不同之處僅在于不能同時彈出多個,以及彈出時是滿屏的,不能看到運行畫面的底圖。這些都不重要,無所謂。
當然,這個功能的實現(xiàn)本身也沒什么高難度,許多同行在具體工程項目中有類似需求時,也可以通過繁雜的編程和數(shù)據(jù)處理實現(xiàn)。然而LBP這里不僅僅實現(xiàn),而且實現(xiàn)了標準化可重復使用,這就很了不起。
所以LBP中的每一個設備功能塊,其實現(xiàn)的功能都是兩部分,一部分傳統(tǒng)的這個設備的控制邏輯,另一部分則是對觸摸屏數(shù)據(jù)的處理。
傳統(tǒng)的設備控制邏輯,所有的庫其實都大同小異,甚至每個人也都自己當場編制設計一個簡單的庫。無非細節(jié)功能和畫面的精致程度不同而已。甚至,如果觸摸屏數(shù)據(jù)處理部分可以實現(xiàn)標準化,用一個 標準的程序模塊實現(xiàn), 那么控制邏輯部分隨便用一個已有的庫功能,也能實現(xiàn)LBP同樣的效果。
所以,把這兩部分的功能解耦開,對于LBP功能移植到其它平臺的PLC,相當重要。在移植過程中,可以不必兩部分功能相互干擾,影響移植的實現(xiàn)了。
而實際上,在移植到SMART 200這樣的小PLC時,原本的程序模式根本無法實現(xiàn)。首先,觸摸屏功能中包含了大量的對數(shù)組數(shù)據(jù)的處理,占用了大量的靜態(tài)變量和臨時變量數(shù)據(jù)區(qū),對方PLC的程序功能塊根本不能容納這么大的數(shù)據(jù)量。
其次,LBP功能邏輯中做了太多冗余功能,導致管腳數(shù)目太多,以至于在向SMART移植的時候,管教數(shù)量很容易就超出了其允許的最多22個管腳的限制。那么我就想,如果我用不到那么多功能的話,我何不繼續(xù)使用以前的功能塊,只要接口定義部分和LBP的定義兼容舊好了呀!
而至于LBP的接口定義使用了多個UDT,甚至UDT的嵌套,我們還需要對UDT部分進行簡化統(tǒng)一,是另外一個方面的話題。
而在實際調試過程中,我不僅僅用自己的功能塊實現(xiàn)了和LBP的對接,甚至還按自己喜歡的方式做了觸摸屏數(shù)據(jù)的整理和傳送,也實現(xiàn)了同樣的功能。
當在移植的過程中遇到系統(tǒng)資源限制無法直接實現(xiàn)的時候,僅保留原接口的定義,保證觸摸屏和WINCC的數(shù)據(jù)接口不變,原畫面模板可以直接進行通訊控制,這種移植也是可以接受的。
等于是,最后我們可以只保留將LBP的接口定義作為一種標準,煙臺方法基于LBP接口定義來做標準化。
而這一切,都來自于先要對LBP原功能塊解耦。
以最普通的MOTOR塊LBP_MTR為例,其所有源程序在本文最后。然而其篇幅太長,這里只截取其region描述表:
所有段落中,框出來的兩個段落:
REGION:read panel request
REGION:write outputs for Panel
這是為觸摸屏數(shù)據(jù)接口服務的。而其余的段落則全部都是其正常的控制邏輯。
那么將功能塊拆分為2個,其實就是把FB塊復制2份,分別叫做L1和L2
L1部分刪除2個觸摸屏相關段落。
L2部分只保留此2段落,而刪除所有其它段落,以及保留一小段重復的段落:
IF "PANELS_NO" > 0 THEN
#tempPanelNo?:= "PANELS_NO";
ELSE
#tempPanelNo?:= 1;
END_IF;
然后在L2中,兩端程序的中間,建立一個多重背景調用L1,并將輸入輸出管腳原名字填入。
即完成了原程序塊的簡單解耦。這一點技巧,在本人專著《PLC標準化編程原理與方法》中,有重點講述。雖然技能很簡單,門檻不高,然而卻是標準化方法中經常用到的非常重要的技能。
當然,程序塊解耦分別建立完成后,還可以對各自的變量表中未用到的變量分別刪除。這一點, TIA PORTAL的功能還不夠強大,不能自動顯示或者用一個指令就查找出來。需要右鍵指向每一個變量,列表中可以選擇“轉至下一個使用點”。而如果這個變量程序中未用到,則命令顯示為灰色。則可以刪除。
我們現(xiàn)在來看L1程序,如果沒有觸摸屏,而只有WINCC,那么功能完全可以直接應用,WINCC數(shù)據(jù)接口直接訪問statDataMtr,這是一個UDT數(shù)據(jù)結構,包含了一個設備的所有控制命令和狀態(tài)字。
而來看L2程序,邏輯只是幾個循環(huán)調用,進行數(shù)據(jù)比較和傳送,和MTR類型幾乎完全沒有關系。未來解耦更多設備功能塊之后,會發(fā)現(xiàn)這個部分的程序幾乎完全相同。唯一不同的是與statDataMtr名字相關的部分,需要更改為另外的設備符號對應的名字。 即僅僅數(shù)據(jù)結構有不同導致。如果高級語言,這里肯定可以做成一個通用的程序功能塊實現(xiàn)。而在PLC系統(tǒng)中,要做到通用就沒那么容易了。暫時情況下,只能每個L2,都復制一遍,并做細節(jié)修改。
LBP_Mtr FB2001??? ? ? ?
REGION header and description
//=============================================================================
//?Siemens
//?(c)Copyright (2019) All Rights Reserved
//-----------------------------------------------------------------------------
//?Library: LBP
//?Tested with: S7-1500 CPU 1516-3 PN/DP V2.5
//?Engineering: TIA V15
//?Restrictions: needs FB "LibBPL_Log15",and data types: "LibBPL_typeMtr..."
//?Requirements: no specific - designed for S7-1200/1500
//?Functionality: motor control - single speed, single rotating direction
//--------------------------------------------------------------------------------------------
//?Change log table:
//?Version? Date??????? Expert in charge??? Changes applied
//?01.00.00 18.05.2017? RW????????????????? First released version
//?01.00.02 15.01.2018? RW????????????????? renamed to LibBPL, added input indInterlock
//?01.00.03 29.03.2018? RW????????????????? fix status dword
//?01.01.00 03.04.2018? RW????????????????? only versioning
//?01.02.00 17.01.2019? MC????????????????? TIA PORTAL V15 Update with UDTs
//?02.00.00 01.08.2019? JM????????????????? Release V2 of LBP
//============================================================================================
//
//?------------------- HMI status ---------------------------------------------
//?00 - Off???????????? 08 - Trip Error????????????? 16 - Ext. Error Flag
//?01 - On????????????? 09 - Ext. Error????????????? 17 - Timeout Error
//?02 - Auto??????????? 10 - Interlock?????????????? 18 - Plausibility Error?????
//?03 - Local?????????? 11 - Repair????????????????? 19 - Operating Hours Limit Reached
//?05 - Run Down??????? 13 - Collect Warning???????? 20 - Switch Counter Limit Reached
//?06 - Run Up????????? 14 - Collect Error?????????? 21 - Ext. Warning
//?07 - Auto Command??? 15 - Trip Error Flag
END_REGION
REGION initialization
#tempReset?:= FALSE;
#tempIntError?:= w#16#0;
END_REGION
REGION read inputs
#statDataMtr.statusHMI.identName:=?#identName;
#statDataMtr.settingsPLC.timeout?:= #timeout;
IF?"PANELS_NO" > 0 THEN // When PANELS_NO=0 then would be compilation error due to wrong array index
#tempPanelNo?:= "PANELS_NO";
ELSE
#tempPanelNo?:= 1;
END_IF;
END_REGION
REGION read panel request
IF?"PANELS_NO" > 0 THEN
FOR?#tempPanelIndex := 1 TO #tempPanelNo DO
#statPanels[#tempPanelIndex]?:= #panels[#tempPanelIndex].mtr;
#statIdentNames[#tempPanelIndex]?:= #panels[#tempPanelIndex].identName;
IF?#statIdentNames[#tempPanelIndex] <> #statOldIdentNames[#tempPanelIndex] THEN
#statFirstCalls[#tempPanelIndex]?:= true;
#statOldIdentNames[#tempPanelIndex]?:= #statIdentNames[#tempPanelIndex];
ELSE
#statFirstCalls[#tempPanelIndex]?:= false;
END_IF;
END_FOR;
FOR?#tempPanelIndex := 1 TO #tempPanelNo DO
IF?(NOT #statFirstCalls[#tempPanelIndex])
AND?(#statPanels[#tempPanelIndex].settingsHMI <> #statOldPanels[#tempPanelIndex])
AND?(#statIdentNames[#tempPanelIndex] = #statDataMtr.statusHMI.identName) THEN
#statDataMtr.settingsHMI?:= #statOldPanels[#tempPanelIndex]
:=?#statPanels[#tempPanelIndex].settingsHMI;
#statFirstCalls[#tempPanelIndex]?:= false;
END_IF;
END_FOR;
END_IF;
END_REGION
REGION overwrite settings from HMI
IF?#statDataMtr.settingsHMI.overwrite.%X0 = FALSE THEN
#tempTimeOut?:= #timeout;
ELSE
#tempTimeOut?:= #statDataMtr.settingsHMI.timeout;
END_IF;
END_REGION
REGION repair mode
IF?NOT #indRepair AND #statDataMtr.statusHMI.msgStatus.repair THEN
#instFbLog15(codeWrite?:= #LOG_REPAIR_OFF);
END_IF;
IF?#indRepair AND NOT #statDataMtr.statusHMI.msgStatus.repair THEN
#instFbLog15(codeWrite?:= #LOG_REPAIR_ON);
END_IF;
END_REGION
REGION trip message
IF?NOT #indTripOk AND NOT #statDataMtr.statusHMI.msgStatus.errorTrip AND NOT #indRepair THEN
#statDataMtr.statusHMI.msgStatus.errorTrip?:= TRUE;
#instFbLog15(codeWrite?:= #LOG_ERR_TRIP);
END_IF;
#statDataMtr.statusHMI.msgStatus.errorFlagTrip?:= NOT #indTripOk;
END_REGION
REGION external error message
IF?#indErr AND NOT #statDataMtr.statusHMI.msgStatus.errorExt AND NOT #indRepair THEN
#statDataMtr.statusHMI.msgStatus.errorExt?:= TRUE;
#instFbLog15(codeWrite?:= #LOG_ERR_EXT);
END_IF;
#statDataMtr.statusHMI.msgStatus.errorFlagExt?:= #indErr;
END_REGION
REGION timeout control
#instTONCtrl(IN?:= ((#statStatus.ctrl AND NOT #indOn) OR (NOT #statStatus.ctrl AND NOT #indOff) AND NOT #indRepair),
PT?:= #tempTimeOut);
IF?#instTONCtrl.Q AND NOT #statDataMtr.statusHMI.msgStatus.errorTimeout THEN
#instFbLog15(codeWrite?:= #LOG_ERR_TIMEOUT);
END_IF;
#statDataMtr.statusHMI.msgStatus.errorTimeout?:= #statDataMtr.statusHMI.msgStatus.errorTimeout OR #instTONCtrl.Q;
END_REGION
REGION plausibility/timeout check
#instTONPlaus(IN?:= ((#indOff AND #indOn) OR (NOT #indOff AND NOT #indOn) AND NOT #indRepair),
PT?:= #tempTimeOut);
IF?#instTONPlaus.Q AND NOT #statDataMtr.statusHMI.msgStatus.errorPlaus THEN
#instFbLog15(codeWrite?:= #LOG_ERR_PLAUS);
END_IF;
#statDataMtr.statusHMI.msgStatus.errorPlaus?:= #instTONPlaus.Q;
END_REGION
REGION collect error
#statDataMtr.statusHMI.msgStatus.collectError?:= #statDataMtr.statusHMI.msgStatus.errorTrip OR #statDataMtr.statusHMI.msgStatus.errorExt OR #statDataMtr.statusHMI.msgStatus.errorTimeout OR #statDataMtr.statusHMI.msgStatus.errorPlaus;
#collectError?:= #statDataMtr.statusHMI.msgStatus.collectError;
#statStatus.ctrlMan?:= #statStatus.ctrlMan AND NOT #statDataMtr.statusHMI.msgStatus.collectError;
END_REGION
REGION collect warning
#statDataMtr.statusHMI.msgStatus.warningExt?:= #indWarn;
#statDataMtr.statusHMI.msgStatus.collectWarning?:= #statDataMtr.statusHMI.msgStatus.warningExt;
#collectWarning?:= #statDataMtr.statusHMI.msgStatus.collectWarning;
END_REGION
REGION collect maintenance
#statDataMtr.statusHMI.msgStatus.collectMaintenance?:= #statDataMtr.statusHMI.msgStatus.opHoursLimitReached OR #statDataMtr.statusHMI.msgStatus.switchCounterLimitReached;
#collectMaintenance?:= #statDataMtr.statusHMI.msgStatus.collectMaintenance;
END_REGION
REGION new status of external release
IF?NOT #statDataMtr.statusHMI.msgStatus.release AND #indRelease THEN
#instFbLog15(codeWrite?:= #LOG_RELEASE_ON);
END_IF;
IF?#statDataMtr.statusHMI.msgStatus.release AND NOT #indRelease THEN
#instFbLog15(codeWrite?:= #LOG_RELEASE_OFF);
END_IF;
END_REGION
REGION log interlock
IF?#statDataMtr.statusHMI.msgStatus.interlock AND NOT #indInterlock THEN
#instFbLog15(codeWrite?:= #LOG_INTLCK_OFF);
ELSIF?NOT #statDataMtr.statusHMI.msgStatus.interlock AND #indInterlock THEN
#instFbLog15(codeWrite?:= #LOG_INTLCK_ON);
END_IF;
END_REGION
REGION status detection
#statDataMtr.statusHMI.msgStatus.off?:= #indOff;
#statDataMtr.statusHMI.msgStatus.on?:= #indOn;
#statDataMtr.statusHMI.msgStatus.repair?:= #indRepair;
#statDataMtr.statusHMI.msgStatus.local?:= #indLocal;
#statDataMtr.statusHMI.msgStatus.release?:= #indRelease;
#statDataMtr.statusHMI.msgStatus.interlock?:= #indInterlock;
#statDataMtr.statusHMI.msgStatus.autoCommand?:= #cmdAutOn;
#statStatus.ctrlAut?:= #cmdAutOn;
#statStatus.ctrlLoc?:= #cmdLocOn;
END_REGION
REGION read commands
#instR_TrigAut(CLK?:= #cmdAut);
#instR_TrigReset(CLK?:= #cmdReset);
#statCommand.off?:= #statDataMtr.settingsHMI.cmd.%X0;
#statCommand.on?:= #statDataMtr.settingsHMI.cmd.%X1;
#statCommand.manual?:= #statDataMtr.settingsHMI.cmd.%X2;
#statCommand.auto?:= #statDataMtr.settingsHMI.cmd.%X3 OR (#instR_TrigAut.Q AND NOT #statDataMtr.settingsHMI.overwrite.%X7);
#statCommand.reset?:= #statDataMtr.settingsHMI.cmd.%X4 OR #instR_TrigReset.Q;
IF?#statDataMtr.settingsHMI.overwrite.%X15 THEN
#instFbLog15(codeWrite?:= #LOG_CHECK);
#statDataMtr.settingsHMI.overwrite.%X15?:= FALSE;
END_IF;
END_REGION
REGION clear/#reset commands and errors
#statDataMtr.settingsHMI.cmd?:= 0;
IF?#statCommand.resetRepeat THEN
#statDataMtr.statusHMI.msgStatus.errorExt?:= #statDataMtr.statusHMI.msgStatus.errorFlagExt;
END_IF;
#statCommand.resetRepeat?:= #statCommand.reset;
IF?#statCommand.reset THEN
#instFbLog15(codeWrite?:= #LOG_CMD_RESET);
#statDataMtr.statusHMI.msgStatus.errorTrip?:= #statDataMtr.statusHMI.msgStatus.errorFlagTrip;
#statDataMtr.statusHMI.msgStatus.errorExt?:= #statDataMtr.statusHMI.msgStatus.errorFlagExt;
#statDataMtr.statusHMI.msgStatus.errorTimeout?:= false;
#statDataMtr.statusHMI.msgStatus.errorPlaus?:= false;
#tempReset?:= TRUE;
END_IF;
#reset?:= #tempReset;
END_REGION
REGION mode remote automatic/manual
IF?#statCommand.auto AND NOT #statDataMtr.statusHMI.msgStatus.local AND NOT #statDataMtr.statusHMI.msgStatus.collectError AND NOT #statDataMtr.statusHMI.msgStatus.auto THEN
#instFbLog15(codeWrite?:= #LOG_CMD_AUT);
#statDataMtr.statusHMI.msgStatus.auto?:= true;
END_IF;
IF?#statCommand.manual OR #statDataMtr.statusHMI.msgStatus.collectError AND #statDataMtr.statusHMI.msgStatus.auto THEN
#instFbLog15(codeWrite?:= #LOG_CMD_MAN);
#statDataMtr.statusHMI.msgStatus.auto?:= false;
END_IF;
#statAuto?:= #statDataMtr.statusHMI.msgStatus.auto;
#statManual?:= NOT #statDataMtr.statusHMI.msgStatus.auto AND NOT #statDataMtr.statusHMI.msgStatus.local;
END_REGION
REGION mode local
IF?NOT #statLocal AND #statDataMtr.statusHMI.msgStatus.local THEN
#instFbLog15(codeWrite?:= #LOG_MODE_LOC_ON);
END_IF;
IF?#statLocal AND NOT #statDataMtr.statusHMI.msgStatus.local THEN
#instFbLog15(codeWrite?:= #LOG_MODE_LOC_OFF);
END_IF;
#statLocal?:= #statDataMtr.statusHMI.msgStatus.local;
//?manual commands
IF?#statCommand.on THEN
#statStatus.ctrlMan?:= TRUE;
END_IF;
IF?#statCommand.off THEN
#statStatus.ctrlMan?:= FALSE;
END_IF;
END_REGION
REGION takeover automatic/local cmmand to manual command
IF?NOT #statDataMtr.statusHMI.msgStatus.local AND #statDataMtr.statusHMI.msgStatus.auto THEN
#statStatus.ctrlMan?:= #statStatus.ctrlAut;
END_IF;
IF?#statDataMtr.statusHMI.msgStatus.local THEN
#statStatus.ctrlMan?:= #statStatus.ctrlLoc;
END_IF;
END_REGION
REGION motor control
#tempBool?:= false;
IF?NOT #statDataMtr.statusHMI.msgStatus.collectError AND NOT #statDataMtr.statusHMI.msgStatus.repair THEN
IF?#statDataMtr.statusHMI.msgStatus.local THEN
#tempBool?:= #statStatus.ctrlLoc;
ELSIF?#statDataMtr.statusHMI.msgStatus.auto THEN
#tempBool?:= #statStatus.ctrlAut;
ELSE
#tempBool?:= #statStatus.ctrlMan;
END_IF;
END_IF;
#tempNoRelease?:= #tempBool AND NOT #statStatus.ctrl AND NOT #statDataMtr.statusHMI.msgStatus.release;
#instR_TrigNoRelease(CLK?:= #tempNoRelease);
IF?#tempNoRelease THEN
#tempBool?:= FALSE;
#statStatus.ctrlMan?:= FALSE;
IF?#instR_TrigNoRelease.Q THEN
#instFbLog15(codeWrite?:= #LOG_NO_RELEASE);
#instFbLog15(codeWrite?:= #LOG_NO_RELEASE);
END_IF;
END_IF;
#tempBool?:= #tempBool AND NOT #statDataMtr.statusHMI.msgStatus.interlock;
IF?NOT #tempBool AND #statStatus.ctrl THEN
#instFbLog15(codeWrite?:= #LOG_OFF);
END_IF;
IF?#tempBool AND NOT #statStatus.ctrl THEN
#instFbLog15(codeWrite?:= #LOG_ON);
END_IF;
#statStatus.ctrl?:= #tempBool;
#on?:= #statStatus.ctrl;
//?reset commands
#statCommand.reset?:= false;
#statCommand.auto?:= false;
#statCommand.manual?:= false;
#statCommand.on?:= false;
#statCommand.off?:= false;
END_REGION
REGION maintenance: switching count and operating hours
//統(tǒng)計啟停次數(shù)和運行時間
REGION?read system time
#tempInt?:= RD_SYS_T(#tempDTL);
IF?#tempInt <> 0 THEN
#tempIntError?:= #tempIntError OR #ERR_RDSYST;
END_IF;
END_REGION
IF?NOT #statOnOld AND #indOn THEN
#statDataMtr.settingsHMI.maintenance.switches?:= #statDataMtr.settingsHMI.maintenance.switches + 1;
END_IF;
#statOnOld?:= #indOn;
IF?#indOn THEN
#tempTime?:= T_DIFF(IN1 := #tempDTL, IN2 := #instLastTime);
#statOpMsecs?:= #statOpMsecs + #tempTime;
IF?#statOpMsecs > #ONE_HOUR THEN
#statOpMsecs?:= #statOpMsecs - #ONE_HOUR;
#statDataMtr.settingsHMI.maintenance.opHours?:= #statDataMtr.settingsHMI.maintenance.opHours + 1;
END_IF;
END_IF;
IF?#statDataMtr.settingsHMI.maintenance.switches >= #statDataMtr.settingsHMI.switches AND #statDataMtr.settingsHMI.switches > 0 THEN
#statDataMtr.statusHMI.msgStatus.switchCounterLimitReached?:= true;
ELSE
#statDataMtr.statusHMI.msgStatus.switchCounterLimitReached?:= false;
END_IF;
IF?(#statDataMtr.settingsHMI.maintenance.opHours >= #statDataMtr.settingsHMI.opHours) AND (#statDataMtr.settingsHMI.opHours > 0) THEN
#statDataMtr.statusHMI.msgStatus.opHoursLimitReached?:= true;
ELSE
#statDataMtr.statusHMI.msgStatus.opHoursLimitReached?:= false;
END_IF;
REGION?save system time for next cycle
#instLastTime?:= #tempDTL;
END_REGION
END_REGION
REGION write mode/status
#modeAut?:= #statDataMtr.statusHMI.msgStatus.auto AND NOT #statDataMtr.statusHMI.msgStatus.local;
#statDataMtr.statusHMI.msgStatus.runDown?:= NOT #statStatus.ctrl AND NOT #statDataMtr.statusHMI.msgStatus.off;
#statDataMtr.statusHMI.msgStatus.runUp?:= #statStatus.ctrl AND NOT #statDataMtr.statusHMI.msgStatus.on;
END_REGION
REGION write internal error
#intError?:= #tempIntError;
#statDataMtr.log15?:= #instFbLog15.statData;
END_REGION
REGION write outputs for Panel??
IF?"PANELS_NO" > 0 THEN
#tempPanel.settingsPLC?:= #statDataMtr.settingsPLC;
#tempPanel.settingsHMI?:= #statDataMtr.settingsHMI;
#tempPanel.statusHMI?:= #statDataMtr.statusHMI;
#tempPanel.alarms1.%X0?:= #statDataMtr.statusHMI.msgStatus.off;
#tempPanel.alarms1.%X1?:= #statDataMtr.statusHMI.msgStatus.on;
#tempPanel.alarms1.%X2?:= #statDataMtr.statusHMI.msgStatus.auto;
#tempPanel.alarms1.%X3?:= #statDataMtr.statusHMI.msgStatus.local;
#tempPanel.alarms1.%X4?:= #statDataMtr.statusHMI.msgStatus.release;
#tempPanel.alarms1.%X5?:= #statDataMtr.statusHMI.msgStatus.runDown;
#tempPanel.alarms1.%X6?:= #statDataMtr.statusHMI.msgStatus.runUp;
#tempPanel.alarms1.%X7?:= #statDataMtr.statusHMI.msgStatus.errorTrip;
#tempPanel.alarms1.%X8?:= #statDataMtr.statusHMI.msgStatus.errorExt;
#tempPanel.alarms1.%X9?:= #statDataMtr.statusHMI.msgStatus.interlock;
#tempPanel.alarms1.%X10?:= #statDataMtr.statusHMI.msgStatus.repair;
#tempPanel.alarms1.%X11?:= #statDataMtr.statusHMI.msgStatus.collectMaintenance;
#tempPanel.alarms1.%X12?:= #statDataMtr.statusHMI.msgStatus.collectWarning;
#tempPanel.alarms1.%X13?:= #statDataMtr.statusHMI.msgStatus.collectError;
#tempPanel.alarms1.%X14?:= #statDataMtr.statusHMI.msgStatus.errorFlagTrip;
#tempPanel.alarms1.%X15?:= #statDataMtr.statusHMI.msgStatus.errorFlagExt;
#tempPanel.alarms2.%X0?:= #statDataMtr.statusHMI.msgStatus.errorTimeout;
#tempPanel.alarms2.%X1?:= #statDataMtr.statusHMI.msgStatus.errorPlaus;
#tempPanel.alarms2.%X2?:= #statDataMtr.statusHMI.msgStatus.opHoursLimitReached;
#tempPanel.alarms2.%X3?:= #statDataMtr.statusHMI.msgStatus.switchCounterLimitReached;
#tempPanel.alarms2.%X4?:= #statDataMtr.statusHMI.msgStatus.warningExt;
#tempPanel.alarms2.%X5?:= #statDataMtr.statusHMI.msgStatus.autoCommand;
//?Comfort symbols- transfer variables
#statSymbolMtr.identName?:= #statDataMtr.statusHMI.identName;
#statSymbolMtr.note?:= #statDataMtr.settingsHMI.note;
#statSymbolMtr.off?:= #statDataMtr.statusHMI.msgStatus.off;
#statSymbolMtr.on?:= #statDataMtr.statusHMI.msgStatus.on;
#statSymbolMtr.auto?:= #statDataMtr.statusHMI.msgStatus.auto;
#statSymbolMtr.local?:= #statDataMtr.statusHMI.msgStatus.local;
#statSymbolMtr.repair?:= #statDataMtr.statusHMI.msgStatus.repair;
#statSymbolMtr.collectMaintenance?:= #statDataMtr.statusHMI.msgStatus.collectMaintenance;
#statSymbolMtr.collectWarning?:= #statDataMtr.statusHMI.msgStatus.collectWarning;
#statSymbolMtr.collectError?:= #statDataMtr.statusHMI.msgStatus.collectError;
#statSymbolMtr.errorFlagTrip?:= #statDataMtr.statusHMI.msgStatus.errorFlagTrip;
#statSymbolMtr.interlock?:= #statDataMtr.statusHMI.msgStatus.interlock;
#statSymbolMtr.alarmsInfo1?:= #statDataMtr.settingsHMI.alarmsInfo1;
#statSymbolMtr.alarmsAck?:= #statDataMtr.settingsHMI.alarmsAck;
#statSymbolMtr.alarms1?:= #tempPanel.alarms1;
#statSymbolMtr.alarms2?:= #tempPanel.alarms2;
FOR?#tempPanelIndex := 1 TO #tempPanelNo DO
IF?(#panels[#tempPanelIndex].identName = #statDataMtr.statusHMI.identName) THEN
#statOldIdentNames[#tempPanelIndex]?:= #statDataMtr.statusHMI.identName;
#statOldPanels[#tempPanelIndex]?:= #statDataMtr.settingsHMI;
#panels[#tempPanelIndex].mtr?:= #tempPanel;
#panels[#tempPanelIndex].log15?:= #instFbLog15.statData;
#panels[#tempPanelIndex].opStation?:= #statDataMtr.settingsHMI.opStation;
#panels[#tempPanelIndex].note?:= #statDataMtr.settingsHMI.note;
END_IF;
END_FOR;
END_IF;
END_REGION
編輯:黃飛
?
評論
查看更多