Changed Kaco communication statemachine
- Added small delay after each modbus/tcp read - Only write requested state when requested state has changed
This commit is contained in:
18
PLC/POUs/Sunspec/Kaco/E_KACO_PCU_REQUESTED_STATE.TcDUT
Normal file
18
PLC/POUs/Sunspec/Kaco/E_KACO_PCU_REQUESTED_STATE.TcDUT
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.12">
|
||||||
|
<DUT Name="E_KACO_PCU_REQUESTED_STATE" Id="{d26b8bd2-4451-4a56-a3ba-471d8a90e01d}">
|
||||||
|
<Declaration><![CDATA[{attribute 'qualified_only'}
|
||||||
|
{attribute 'strict'}
|
||||||
|
{attribute 'to_string'}
|
||||||
|
TYPE E_KACO_PCU_REQUESTED_STATE :
|
||||||
|
(
|
||||||
|
UNDEFINED := 0,
|
||||||
|
OFF := 1,
|
||||||
|
STANDBY := 8,
|
||||||
|
GRID_PRE_CONNECTED := 10,
|
||||||
|
GRID_CONNECTED := 11
|
||||||
|
);
|
||||||
|
END_TYPE
|
||||||
|
]]></Declaration>
|
||||||
|
</DUT>
|
||||||
|
</TcPlcObject>
|
||||||
@@ -49,7 +49,8 @@ VAR
|
|||||||
_rPowerInternal : REAL := 0;
|
_rPowerInternal : REAL := 0;
|
||||||
|
|
||||||
// Enum for requested state
|
// Enum for requested state
|
||||||
_eRequestedState : (OFF := 1, STANDBY := 8, GRID_PRE_CONNECTED := 10, GRID_CONNECTED := 11) := OFF;
|
_eRequestedState : E_KACO_PCU_REQUESTED_STATE := E_KACO_PCU_REQUESTED_STATE.OFF;
|
||||||
|
_eLastRequestedState : E_KACO_PCU_REQUESTED_STATE := E_KACO_PCU_REQUESTED_STATE.UNDEFINED;
|
||||||
|
|
||||||
// Watchdog timeout in seconds
|
// Watchdog timeout in seconds
|
||||||
_uiWatchdogTimeoutSeconds : UINT := 10;
|
_uiWatchdogTimeoutSeconds : UINT := 10;
|
||||||
@@ -85,20 +86,13 @@ VAR
|
|||||||
_fbReadACValues : FB_MBReadRegs;
|
_fbReadACValues : FB_MBReadRegs;
|
||||||
|
|
||||||
// Time for polling for current dc values and check for inverter error
|
// Time for polling for current dc values and check for inverter error
|
||||||
_timPollingDelay : TIME := T#500MS;
|
_timPollingDelay : TIME := T#200MS;
|
||||||
|
|
||||||
// Time for setting the current power
|
|
||||||
_timSetPowerDelay : TIME := T#250MS;
|
|
||||||
|
|
||||||
// Timer for polling of current values
|
// Timer for polling of current values
|
||||||
_tonPollingTimer : TON;
|
_tonPollingTimer : TON;
|
||||||
_tTimeoutPolling : TIME := T#5S;
|
_tTimeoutPolling : TIME := T#5S;
|
||||||
|
|
||||||
// Timer for setting the inverter power
|
// watchdog write timeout
|
||||||
_tonSetPowerTimer : TON;
|
|
||||||
|
|
||||||
// Timer for watchdog
|
|
||||||
_tonWatchdogResetTimer : TON := (PT := T#1S);
|
|
||||||
_tTimeoutWriteWatchdogRegister : TIME := T#5S;
|
_tTimeoutWriteWatchdogRegister : TIME := T#5S;
|
||||||
|
|
||||||
// Inverter alarm
|
// Inverter alarm
|
||||||
@@ -199,10 +193,12 @@ VAR CONSTANT
|
|||||||
// 41120 is Voltage and 41121 is amp
|
// 41120 is Voltage and 41121 is amp
|
||||||
BATTERY_LIMIT_SF_START : WORD := 41120;
|
BATTERY_LIMIT_SF_START : WORD := 41120;
|
||||||
BATTERY_SET_LIMITS_START : WORD := 41122;
|
BATTERY_SET_LIMITS_START : WORD := 41122;
|
||||||
|
(*
|
||||||
DIS_MIN_V : WORD := 41122;
|
DIS_MIN_V : WORD := 41122;
|
||||||
DIS_MAX_A : WORD := 41123;
|
DIS_MAX_A : WORD := 41123;
|
||||||
CHA_MAX_V : WORD := 41125;
|
CHA_MAX_V : WORD := 41125;
|
||||||
CHA_MAX_A : WORD := 41126;
|
CHA_MAX_A : WORD := 41126;
|
||||||
|
*)
|
||||||
EN_LIMIT : WORD := 41129;
|
EN_LIMIT : WORD := 41129;
|
||||||
|
|
||||||
// Power registers (Model 64201)
|
// Power registers (Model 64201)
|
||||||
@@ -248,7 +244,6 @@ IF (rPower < -rMaxBattPower) THEN
|
|||||||
_rPowerInternal := -rMaxBattPower;
|
_rPowerInternal := -rMaxBattPower;
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
HandleHeartbeat();
|
|
||||||
HandleCyclicData();
|
HandleCyclicData();
|
||||||
|
|
||||||
CASE _iState OF
|
CASE _iState OF
|
||||||
@@ -256,7 +251,7 @@ CASE _iState OF
|
|||||||
_fbTONSetBatteryLimits(IN := TRUE);
|
_fbTONSetBatteryLimits(IN := TRUE);
|
||||||
IF _fbTONSetBatteryLimits.Q THEN
|
IF _fbTONSetBatteryLimits.Q THEN
|
||||||
_fbTONSetBatteryLimits(IN := FALSE);
|
_fbTONSetBatteryLimits(IN := FALSE);
|
||||||
_eRequestedState := OFF;
|
_eRequestedState := E_KACO_PCU_REQUESTED_STATE.OFF;
|
||||||
_iStateStartup := 0;
|
_iStateStartup := 0;
|
||||||
_iState := 10;
|
_iState := 10;
|
||||||
END_IF
|
END_IF
|
||||||
@@ -348,7 +343,7 @@ CASE _iState OF
|
|||||||
40: // Idle state, wait for enable
|
40: // Idle state, wait for enable
|
||||||
// If enable and INTLK Ok
|
// If enable and INTLK Ok
|
||||||
IF xEnable THEN
|
IF xEnable THEN
|
||||||
_eRequestedState := GRID_CONNECTED;
|
_eRequestedState := E_KACO_PCU_REQUESTED_STATE.GRID_CONNECTED;
|
||||||
IF xReleasePower THEN
|
IF xReleasePower THEN
|
||||||
// Calculate power to write to register
|
// Calculate power to write to register
|
||||||
// (could not find where the scaling for wset can be read but its -2!)
|
// (could not find where the scaling for wset can be read but its -2!)
|
||||||
@@ -360,14 +355,14 @@ CASE _iState OF
|
|||||||
_iWSetPct := 0;
|
_iWSetPct := 0;
|
||||||
END_IF
|
END_IF
|
||||||
ELSE
|
ELSE
|
||||||
_eRequestedState := OFF;
|
_eRequestedState := E_KACO_PCU_REQUESTED_STATE.OFF;
|
||||||
_iWSetPct := 0;
|
_iWSetPct := 0;
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
// Comm error or Watchdog error occured
|
// Comm error or Watchdog error occured
|
||||||
IF _xErrorCyclicData OR (NOT xHeartbeatOk) THEN
|
IF _xErrorCyclicData OR (NOT xHeartbeatOk) THEN
|
||||||
_iWSetPct := 0;
|
_iWSetPct := 0;
|
||||||
_eRequestedState := OFF;
|
_eRequestedState := E_KACO_PCU_REQUESTED_STATE.OFF;
|
||||||
_iState := 1000;
|
_iState := 1000;
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
@@ -384,7 +379,7 @@ CASE _iState OF
|
|||||||
|
|
||||||
1001: // Error state, wait for reset
|
1001: // Error state, wait for reset
|
||||||
IF xReset AND (NOT xEnable) AND (NOT _xErrorInverter) AND (NOT _xErrorCyclicData) AND xHeartbeatOk THEN
|
IF xReset AND (NOT xEnable) AND (NOT _xErrorInverter) AND (NOT _xErrorCyclicData) AND xHeartbeatOk THEN
|
||||||
_eRequestedState := OFF;
|
_eRequestedState := E_KACO_PCU_REQUESTED_STATE.OFF;
|
||||||
xError := FALSE;
|
xError := FALSE;
|
||||||
_xFaultInverter := FALSE;
|
_xFaultInverter := FALSE;
|
||||||
_xErrorCyclicDataLedge := FALSE;
|
_xErrorCyclicDataLedge := FALSE;
|
||||||
@@ -463,14 +458,16 @@ _fbCyclicDataAlarm.ipArguments.Clear().AddString(_sName);]]></ST>
|
|||||||
_iErrorIDRACV := 0;
|
_iErrorIDRACV := 0;
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
// Fetch cyclic data with polling timer
|
|
||||||
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
|
||||||
|
|
||||||
CASE _iStateCyclicData OF
|
CASE _iStateCyclicData OF
|
||||||
0: // init state
|
0: // init state
|
||||||
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||||
IF _tonPollingTimer.Q THEN
|
IF _tonPollingTimer.Q THEN
|
||||||
_tonPollingTimer(IN := FALSE);
|
_tonPollingTimer(IN := FALSE);
|
||||||
_iStateCyclicData := 10;
|
IF _eRequestedState <> _eLastRequestedState THEN
|
||||||
|
_iStateCyclicData := 10;
|
||||||
|
ELSE
|
||||||
|
_iStateCyclicData := 20;
|
||||||
|
END_IF
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
10: // Write requested state
|
10: // Write requested state
|
||||||
@@ -488,16 +485,24 @@ CASE _iStateCyclicData OF
|
|||||||
|
|
||||||
IF (NOT _fbWriteRequestedState.bBusy) THEN
|
IF (NOT _fbWriteRequestedState.bBusy) THEN
|
||||||
_fbWriteRequestedState(bExecute := FALSE);
|
_fbWriteRequestedState(bExecute := FALSE);
|
||||||
_iStateCyclicData := 20;
|
_iStateCyclicData := 11;
|
||||||
IF _fbWriteRequestedState.bError THEN
|
IF _fbWriteRequestedState.bError THEN
|
||||||
_iCurrentErrorCountWRS := _iCurrentErrorCountWRS + 1;
|
_iCurrentErrorCountWRS := _iCurrentErrorCountWRS + 1;
|
||||||
_iErrorCountWRS := _iErrorCountWRS + 1;
|
_iErrorCountWRS := _iErrorCountWRS + 1;
|
||||||
_iErrorIDWRS := _fbWriteRequestedState.nErrId;
|
_iErrorIDWRS := _fbWriteRequestedState.nErrId;
|
||||||
ELSE
|
ELSE
|
||||||
_iCurrentErrorCountWRS := 0;
|
_iCurrentErrorCountWRS := 0;
|
||||||
|
_eLastRequestedState := _eRequestedState;
|
||||||
END_IF
|
END_IF
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
|
11: // wait for next state
|
||||||
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||||
|
IF _tonPollingTimer.Q THEN
|
||||||
|
_tonPollingTimer(IN := FALSE);
|
||||||
|
_iStateCyclicData := 20;
|
||||||
|
END_IF
|
||||||
|
|
||||||
20: // Write current power command
|
20: // Write current power command
|
||||||
_fbWritePowerCommand(
|
_fbWritePowerCommand(
|
||||||
sIPAddr:= sInverterIPAddr,
|
sIPAddr:= sInverterIPAddr,
|
||||||
@@ -515,7 +520,7 @@ CASE _iStateCyclicData OF
|
|||||||
|
|
||||||
IF (NOT _fbWritePowerCommand.bBusy) THEN
|
IF (NOT _fbWritePowerCommand.bBusy) THEN
|
||||||
_fbWritePowerCommand(bExecute := FALSE);
|
_fbWritePowerCommand(bExecute := FALSE);
|
||||||
_iStateCyclicData := 30;
|
_iStateCyclicData := 21;
|
||||||
IF _fbWritePowerCommand.bError THEN
|
IF _fbWritePowerCommand.bError THEN
|
||||||
_iCurrentErrorCountWPC := _iCurrentErrorCountWPC + 1;
|
_iCurrentErrorCountWPC := _iCurrentErrorCountWPC + 1;
|
||||||
_iErrorCountWPC := _iErrorCountWPC + 1;
|
_iErrorCountWPC := _iErrorCountWPC + 1;
|
||||||
@@ -525,6 +530,13 @@ CASE _iStateCyclicData OF
|
|||||||
END_IF
|
END_IF
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
|
21: // wait for next state
|
||||||
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||||
|
IF _tonPollingTimer.Q THEN
|
||||||
|
_tonPollingTimer(IN := FALSE);
|
||||||
|
_iStateCyclicData := 30;
|
||||||
|
END_IF
|
||||||
|
|
||||||
30: // Read current state
|
30: // Read current state
|
||||||
_fbReadCurrentState(
|
_fbReadCurrentState(
|
||||||
sIPAddr:= sInverterIPAddr,
|
sIPAddr:= sInverterIPAddr,
|
||||||
@@ -543,7 +555,7 @@ CASE _iStateCyclicData OF
|
|||||||
|
|
||||||
IF (NOT _fbReadCurrentState.bBusy) THEN
|
IF (NOT _fbReadCurrentState.bBusy) THEN
|
||||||
_fbReadCurrentState(bExecute := FALSE);
|
_fbReadCurrentState(bExecute := FALSE);
|
||||||
_iStateCyclicData := 40;
|
_iStateCyclicData := 31;
|
||||||
IF _fbReadCurrentState.bError THEN
|
IF _fbReadCurrentState.bError THEN
|
||||||
_iCurrentErrorCountRCS := _iCurrentErrorCountRCS + 1;
|
_iCurrentErrorCountRCS := _iCurrentErrorCountRCS + 1;
|
||||||
_iErrorCountRCS := _iErrorCountRCS + 1;
|
_iErrorCountRCS := _iErrorCountRCS + 1;
|
||||||
@@ -553,6 +565,13 @@ CASE _iStateCyclicData OF
|
|||||||
END_IF
|
END_IF
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
|
31: // wait for next state
|
||||||
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||||
|
IF _tonPollingTimer.Q THEN
|
||||||
|
_tonPollingTimer(IN := FALSE);
|
||||||
|
_iStateCyclicData := 40;
|
||||||
|
END_IF
|
||||||
|
|
||||||
40: // Read current pcu status
|
40: // Read current pcu status
|
||||||
_fbReadPCUState(
|
_fbReadPCUState(
|
||||||
sIPAddr:= sInverterIPAddr,
|
sIPAddr:= sInverterIPAddr,
|
||||||
@@ -571,7 +590,7 @@ CASE _iStateCyclicData OF
|
|||||||
|
|
||||||
IF (NOT _fbReadPCUState.bBusy) THEN
|
IF (NOT _fbReadPCUState.bBusy) THEN
|
||||||
_fbReadPCUState(bExecute := FALSE);
|
_fbReadPCUState(bExecute := FALSE);
|
||||||
_iStateCyclicData := 50;
|
_iStateCyclicData := 41;
|
||||||
IF _fbReadPCUState.bError THEN
|
IF _fbReadPCUState.bError THEN
|
||||||
_iCurrentErrorCountRPCUS := _iCurrentErrorCountRPCUS + 1;
|
_iCurrentErrorCountRPCUS := _iCurrentErrorCountRPCUS + 1;
|
||||||
_iErrorCountRPCUS := _iErrorCountRPCUS + 1;
|
_iErrorCountRPCUS := _iErrorCountRPCUS + 1;
|
||||||
@@ -584,6 +603,13 @@ CASE _iStateCyclicData OF
|
|||||||
END_IF
|
END_IF
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
|
41: // wait for next state
|
||||||
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||||
|
IF _tonPollingTimer.Q THEN
|
||||||
|
_tonPollingTimer(IN := FALSE);
|
||||||
|
_iStateCyclicData := 50;
|
||||||
|
END_IF
|
||||||
|
|
||||||
50: // Read current dc values
|
50: // Read current dc values
|
||||||
_fbReadDCValues(
|
_fbReadDCValues(
|
||||||
sIPAddr:= sInverterIPAddr,
|
sIPAddr:= sInverterIPAddr,
|
||||||
@@ -603,7 +629,7 @@ CASE _iStateCyclicData OF
|
|||||||
// Check if reading modbus register is done
|
// Check if reading modbus register is done
|
||||||
IF (NOT _fbReadDCValues.bBusy) THEN
|
IF (NOT _fbReadDCValues.bBusy) THEN
|
||||||
_fbReadDCValues(bExecute := FALSE);
|
_fbReadDCValues(bExecute := FALSE);
|
||||||
_iStateCyclicData := 60;
|
_iStateCyclicData := 51;
|
||||||
// If there was no error and the converter has no error continue
|
// If there was no error and the converter has no error continue
|
||||||
IF (NOT _fbReadDCValues.bError) THEN
|
IF (NOT _fbReadDCValues.bError) THEN
|
||||||
stCurrentValues.rActDCCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[1])));
|
stCurrentValues.rActDCCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[1])));
|
||||||
@@ -620,6 +646,13 @@ CASE _iStateCyclicData OF
|
|||||||
END_IF
|
END_IF
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
|
51: // wait for next state
|
||||||
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||||
|
IF _tonPollingTimer.Q THEN
|
||||||
|
_tonPollingTimer(IN := FALSE);
|
||||||
|
_iStateCyclicData := 60;
|
||||||
|
END_IF
|
||||||
|
|
||||||
60: // Read current ac values
|
60: // Read current ac values
|
||||||
_fbReadACValues(
|
_fbReadACValues(
|
||||||
sIPAddr:= sInverterIPAddr,
|
sIPAddr:= sInverterIPAddr,
|
||||||
@@ -639,7 +672,7 @@ CASE _iStateCyclicData OF
|
|||||||
// Check if reading mudbus register is done
|
// Check if reading mudbus register is done
|
||||||
IF (NOT _fbReadACValues.bBusy) THEN
|
IF (NOT _fbReadACValues.bBusy) THEN
|
||||||
_fbReadACValues(bExecute := FALSE);
|
_fbReadACValues(bExecute := FALSE);
|
||||||
_iStateCyclicData := 0;
|
_iStateCyclicData := 61;
|
||||||
// If there was no error and the converter has no error continue
|
// If there was no error and the converter has no error continue
|
||||||
IF (NOT _fbReadACValues.bError) THEN
|
IF (NOT _fbReadACValues.bError) THEN
|
||||||
stCurrentValues.rActACCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
stCurrentValues.rActACCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
||||||
@@ -667,8 +700,49 @@ CASE _iStateCyclicData OF
|
|||||||
_iErrorIDRACV := _fbReadACValues.nErrId;
|
_iErrorIDRACV := _fbReadACValues.nErrId;
|
||||||
END_IF
|
END_IF
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
|
61: // wait for next state
|
||||||
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||||
|
IF _tonPollingTimer.Q THEN
|
||||||
|
_tonPollingTimer(IN := FALSE);
|
||||||
|
_iStateCyclicData := 70;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
70:
|
||||||
|
// Timeout should be less than timer interval
|
||||||
|
_fbWriteHearbeatRegister(
|
||||||
|
sIPAddr:= sInverterIPAddr,
|
||||||
|
nTCPPort:= 502,
|
||||||
|
nUnitID:= 16#01,
|
||||||
|
nMBAddr:= WATCHDOG_REGISTER,
|
||||||
|
nValue:= _uiWatchdogTimeoutSeconds,
|
||||||
|
bExecute:= TRUE,
|
||||||
|
tTimeout:= _tTimeoutWriteWatchdogRegister,
|
||||||
|
bBusy=> ,
|
||||||
|
bError=> ,
|
||||||
|
nErrId=> );
|
||||||
|
|
||||||
|
// Because there is no heartbeat register to read,
|
||||||
|
// we will use a successfull write as a valid heartbeat signal
|
||||||
|
IF NOT _fbWriteHearbeatRegister.bBusy THEN
|
||||||
|
_fbWriteHearbeatRegister(bExecute := FALSE);
|
||||||
|
_iStateCyclicData := 0;
|
||||||
|
IF _fbWriteHearbeatRegister.bError THEN
|
||||||
|
_iCurrentErrorCountHB := _iCurrentErrorCountHB + 1;
|
||||||
|
_iErrorCountHB := _iErrorCountHB + 1;
|
||||||
|
_iErrorIDHB := _fbWriteHearbeatRegister.nErrId;
|
||||||
|
IF _iCurrentErrorCountHB >= GVL_CONFIG.udiMaxConsecutiveInvError THEN
|
||||||
|
xHeartbeatOk := FALSE;
|
||||||
|
xError := TRUE;
|
||||||
|
END_IF
|
||||||
|
ELSE
|
||||||
|
_iCurrentErrorCountHB := 0;
|
||||||
|
xHeartbeatOk := TRUE;
|
||||||
|
END_IF
|
||||||
|
END_IF
|
||||||
END_CASE
|
END_CASE
|
||||||
|
|
||||||
|
|
||||||
// evaluate inverter state
|
// evaluate inverter state
|
||||||
IF _eCurrentState = E_KACO_CURRENT_STATE.GRID_CONNECTED OR _eCurrentState = E_KACO_CURRENT_STATE.THROTTLED THEN
|
IF _eCurrentState = E_KACO_CURRENT_STATE.GRID_CONNECTED OR _eCurrentState = E_KACO_CURRENT_STATE.THROTTLED THEN
|
||||||
xActive := TRUE;
|
xActive := TRUE;
|
||||||
@@ -710,7 +784,7 @@ IF _xErrorCyclicData THEN
|
|||||||
_xErrorCyclicDataLedge := TRUE;
|
_xErrorCyclicDataLedge := TRUE;
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
// handle alarm
|
// handle cyclic data alarm
|
||||||
IF _xErrorCyclicData AND NOT _fbCyclicDataAlarm.bRaised THEN
|
IF _xErrorCyclicData AND NOT _fbCyclicDataAlarm.bRaised THEN
|
||||||
_fbCyclicDataAlarm.Raise();
|
_fbCyclicDataAlarm.Raise();
|
||||||
END_IF
|
END_IF
|
||||||
@@ -721,42 +795,6 @@ END_IF
|
|||||||
|
|
||||||
IF _fbCyclicDataAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND xReset THEN
|
IF _fbCyclicDataAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND xReset THEN
|
||||||
_fbCyclicDataAlarm.Confirm(0);
|
_fbCyclicDataAlarm.Confirm(0);
|
||||||
END_IF]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
</Action>
|
|
||||||
<Action Name="HandleHeartbeat" Id="{eeb5f65a-fd91-4c22-ab2e-3080c24e87fb}">
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[// Self resetting watchdog timer
|
|
||||||
_tonWatchdogResetTimer(IN := TRUE);
|
|
||||||
|
|
||||||
// Timeout should be less than timer interval
|
|
||||||
_fbWriteHearbeatRegister(
|
|
||||||
sIPAddr:= sInverterIPAddr,
|
|
||||||
nTCPPort:= 502,
|
|
||||||
nUnitID:= 16#01,
|
|
||||||
nMBAddr:= WATCHDOG_REGISTER,
|
|
||||||
nValue:= _uiWatchdogTimeoutSeconds,
|
|
||||||
bExecute:= _tonWatchdogResetTimer.Q AND (NOT _fbWriteHearbeatRegister.bBusy),
|
|
||||||
tTimeout:= _tTimeoutWriteWatchdogRegister,
|
|
||||||
bBusy=> ,
|
|
||||||
bError=> ,
|
|
||||||
nErrId=> );
|
|
||||||
|
|
||||||
// Because there is no heartbeat register to read,
|
|
||||||
// we will use a successfull write as a valid heartbeat signal
|
|
||||||
IF NOT _fbWriteHearbeatRegister.bBusy THEN
|
|
||||||
IF _fbWriteHearbeatRegister.bError THEN
|
|
||||||
_iCurrentErrorCountHB := _iCurrentErrorCountHB + 1;
|
|
||||||
_iErrorCountHB := _iErrorCountHB + 1;
|
|
||||||
_iErrorIDHB := _fbWriteHearbeatRegister.nErrId;
|
|
||||||
IF _iCurrentErrorCountHB >= GVL_CONFIG.udiMaxConsecutiveInvError THEN
|
|
||||||
xHeartbeatOk := FALSE;
|
|
||||||
xError := TRUE;
|
|
||||||
END_IF
|
|
||||||
ELSE
|
|
||||||
_iCurrentErrorCountHB := 0;
|
|
||||||
xHeartbeatOk := TRUE;
|
|
||||||
END_IF
|
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
// set fault flag when error active
|
// set fault flag when error active
|
||||||
@@ -764,7 +802,7 @@ IF NOT xHeartbeatOk THEN
|
|||||||
_xHeartBeatNOK := TRUE;
|
_xHeartBeatNOK := TRUE;
|
||||||
END_IF
|
END_IF
|
||||||
|
|
||||||
// handle alarm
|
// handle heartbeat alarm
|
||||||
IF NOT xHeartbeatOk AND NOT _fbHeartBeatAlarm.bRaised THEN
|
IF NOT xHeartbeatOk AND NOT _fbHeartBeatAlarm.bRaised THEN
|
||||||
_fbHeartBeatAlarm.Raise();
|
_fbHeartBeatAlarm.Raise();
|
||||||
END_IF
|
END_IF
|
||||||
@@ -775,11 +813,6 @@ END_IF
|
|||||||
|
|
||||||
IF _fbHeartBeatAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND xReset THEN
|
IF _fbHeartBeatAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND xReset THEN
|
||||||
_fbHeartBeatAlarm.Confirm(0);
|
_fbHeartBeatAlarm.Confirm(0);
|
||||||
END_IF
|
|
||||||
|
|
||||||
// Reset timer
|
|
||||||
IF _tonWatchdogResetTimer.Q THEN
|
|
||||||
_tonWatchdogResetTimer(IN := FALSE);
|
|
||||||
END_IF]]></ST>
|
END_IF]]></ST>
|
||||||
</Implementation>
|
</Implementation>
|
||||||
</Action>
|
</Action>
|
||||||
|
|||||||
Reference in New Issue
Block a user