Esempio applicativo di sincronizzazione
In questa applicazione di esempio, l'applicazione controlla la sincronizzazione dei dati nel sistema di ridondanza. L'esempio mostra come attivare le fasi di sincronizzazione tramite le POU della libreria e come analizzare i dati di stato del sistema di ridondanza. Una visualizzazione mostra questi stati e fornisce comandi di ridondanza. La visualizzazione è un'interfaccia per un utente.
Il sistema di ridondanza è costituito dai due REDU01
e REDU01
CODESYS Control Win controllori. La visualizzazione viene eseguita su a CODESYS TargetVisu.
Configurazione
Oggetto nell'albero dei dispositivi | Impostazioni |
---|---|
Di alto livello |
![]() |
Configurazione attività | ![]() |
Configurazione di ridondanza | |
PLC 2 |
|
Generale | ![]() |
Collegamento di ridondanza | ![]() |
Visualizzazione | ![]() |
Nel Aree Registrate | ![]() |
Dati globali
GVL
(* Variables synchronized at Redundancy synchronization. Synchronization happens - on bootup of the second PLC - on call to RedundancySynchronizeData - in every task cycle if setting is active in cfg file of both PLCs: [CmpRedundancy] DataSyncAlways=1 *) VAR_GLOBAL globalvar1: INT; arr1 : ARRAY [0..10000] OF DWORD; arr2 : ARRAY [0..10000] OF DWORD; arr3 : ARRAY [0..10000] OF DWORD; arr4 : ARRAY [0..10000] OF DWORD; bSyncDataResult: BOOL; END_VAR
GVL_1
VAR_GLOBAL sReduState: RedundancyState; conni: REDUNDANCY_CONNECTION_INFO; sSyncInfo: SYNC_INFO; sPlcIdent: PLC_IDENT; bConnectionState: BOOL; tLast: TIME; nTimeWarp: INT; tDiff: TIME; nTimeRun: INT; tNow: TIME; sState: STRING; acopy: INT; MB2 AT %MX0.2: BOOL; tDiffMax: TIME; tNow2: TIME; tDiff2: TIME; nTimeWarp2: INT; tDiffMax2: TIME; tLast2: TIME; tNowDownloadDone: TIME; tNowCodeInitDone: TIME; nCycle: INT; atNow: ARRAY [0..9] OF TIME; nCycle2: INT; atNow2: ARRAY [0..9] OF TIME; bAreaRegisterDone: BOOL; pIB64: POINTER TO BYTE; bUpdateData: BOOL; bSwitchToStandby: BOOL; bSwitchToActive: BOOL; bSwitchToSimulation: BOOL; bSynchronize: BOOL; bSwitchToStandaloneResult: BOOL; END_VAR
GVL_Synchro
(* Global variables, registered to be synchronized in every task cycle. *) VAR_GLOBAL iSyncFirst: INT; iSyncCount: INT; iSyncLast: INT; END_VAR
POU per il controllo della sincronizzazione
PROGRAM PLC_PRG VAR a: INT; bSyncCalled: BOOL; Timestamp1: systime.SYSTIME; firstcycle: BOOL := TRUE; Timestamp2: systime.SYSTIME; b: INT; sText: STRING; bCopy: BOOL; Blink: TON; bBlink: BOOL; bAutoSync: BOOL := TRUE; // Flag to enable autosync mechanism xResSync: BOOL; END_VARIF a = 0 THEN Blink(PT := T#1S, IN := TRUE); END_IF a := a + 6; globalvar1 := globalvar1 + 1; (* Call functions of redundancy library *) GetRedundancyState(ADR(sReduState)); bConnectionState := GetConnectionState(); sPlcIdent := GetPlcIdent(); (* Call functions of redundancy connection library *) GetConnectionInfo(ADR(conni)); GetSyncInformation(ADR(sSyncInfo)); // Flag to enable autosync mechanism IF bAutoSync THEN IF sReduState.eRedundancyState = RDCY.STATE.RS_CYCLE_STANDALONE AND bConnectionState AND xResSync = FALSE AND sPlcIdent = RDCY.PLC_IDENT.PLC_ID_2 THEN // Call of Synchronize from redundant application. Note, actual synchronisation is executed from background loop with some delay xResSync := RDCY.Synchronize(); END_IF END_IF // Recover from error state (*IF sReduState.eRedundancyState = RDCY.STATE.RS_SYNCHRO_ERROR THEN bSwitchToStandaloneResult := SwitchToStandalone(); END_IF IF sReduState.eRedundancyState = RDCY.STATE.RS_CYCLE_ACTIVE THEN bSyncDataResult := RedundancySynchronizeData(); END_IF *) IF bUpdateData THEN bUpdateData := FALSE; RedundancySynchronizeData(); END_IF IF bSwitchToStandby THEN bSwitchToStandby := FALSE; SwitchToStandby(); END_IF IF bSwitchToActive THEN bSwitchToActive := FALSE; SwitchToActive(); END_IF IF bSwitchToSimulation THEN bSwitchToSimulation := FALSE; SwitchToSimulation(); END_IF IF bSynchronize THEN bSynchronize := FALSE; Synchronize(); END_IF Blink(); IF Blink.Q THEN Blink.IN := FALSE; Blink(); Blink.IN := TRUE; bBlink := NOT bBlink; END_IF %IB64; IF bCopy THEN bCopy := FALSE; acopy := a; END_IF arr2 := arr1; IF sReduState.eRedundancyState = RDCY.STATE.RS_CYCLE_ACTIVE THEN sState := 'Active'; b := b + 1; pIB64 := ADR(%IB64); pIB64^ := pIB64^ + 1; ELSIF sReduState.eRedundancyState = RDCY.STATE.RS_CYCLE_STANDBY THEN sState := 'Passive'; ELSIF sReduState.eRedundancyState = RDCY.STATE.RS_CYCLE_STANDALONE THEN sState := 'Standalone'; ELSIF sReduState.eRedundancyState = RDCY.STATE.RS_SIMULATION THEN sState := 'Simulation'; ELSIF sReduState.eRedundancyState = RDCY.STATE.RS_SYNCHRO THEN sState := 'Synchro'; ELSIF sReduState.eRedundancyState = RDCY.STATE.RS_SYNCHRO_ERROR THEN sState := 'SYNCHRO_ERROR'; ELSIF sReduState.eRedundancyState = RDCY.STATE.RS_NO_LICENSE THEN sState := 'LICENCE EXPIRED'; ELSIF sReduState.eRedundancyState = RDCY.STATE.RS_START THEN sState := 'START'; ELSE sState := 'Other'; END_IF nCycle := nCycle + 1;
PROGRAM POU VAR END_VAR tNow2 := TIME(); tDiff2 := tNow - tLast; IF tDiff2 > T#1D THEN nTimeWarp2 := nTimeWarp2 + 1; LogAdd(STD_LOGGER, 'IEC', 0, 0, 0, 'Time Warp'); END_IF IF tDiff2 > tDiffMax2 THEN tDiffMax2 := tDiff2; END_IF tLast2 := TIME(); IF nCycle2 < 10 THEN atNow2[nCycle2] := tNow2; END_IF nCycle2 := nCycle2 + 1;
FUNCTION cdCodeInit : DWORD VAR_IN_OUT EventPrm: CmpApp.EVTPARAM_CmpApp; END_VAR VAR END_VAR tNowCodeInitDone := TIME();
FUNCTION cbDownloadDone : DWORD VAR_IN_OUT EventPrm: CmpApp.EVTPARAM_CmpApp; END_VAR VAR END_VAR (* Register GVL_Synchro to be synchronized in every task cycle *) bAreaRegisterDone := AreaRegister(ADR(iSyncFirst), ADR(iSyncLast) - ADR(iSyncFirst) + sizeof(iSyncLast), AREA_TYPE.AREA_SYNCHRO); tNowDownloadDone := TIME();
Visualizzazione
