Some fixes before the FAT

- Refactored inverter Heartbeat check
- Added SafetyComError on EtherCAT checking
- Adjusted lower pressure value for safety plc from 200 mBar to 300mBar
This commit is contained in:
Matthias Heisig
2025-06-06 19:09:12 +02:00
parent 38f44128d1
commit 58f3c751d3
12 changed files with 826 additions and 882 deletions

View File

@@ -33,10 +33,6 @@ VAR_INPUT
// Reset Safety
xResetSafety : BOOL;
// Safety communication error
{attribute 'analysis' := '-33'}
xSafetyComError AT %I* : BOOL;
// Release alarms
xReleaseErrors : BOOL;
@@ -64,6 +60,10 @@ VAR_OUTPUT
// Repair switch closed
xRepairSwitchOk AT %I* : BOOL;
// Safety communication error
{attribute 'analysis' := '-33'}
xSafetyComError AT %I* : BOOL;
// All safetyinterlocks from safety plc are ok
xSafetyIntlksOk AT %I* : BOOL;
@@ -157,9 +157,6 @@ VAR
// State for start and stop
_iState : INT := 0;
// Timer for result pulse to safety
_tonResetPulseLength : TON := (PT := T#250MS);
// Error timer for not closing dc relais
_tonErrorDCCBNotClosed : TON := (PT := T#5S);
@@ -221,7 +218,7 @@ VAR
_xErrorInternal : BOOL;
_fbSafetyResetImpulseGen : FB_Blinker := (rFrequency := 1.0);
_fbSafetyResetImpulseGen : FB_Blinker := (rFrequency := 2.0);
END_VAR
@@ -234,8 +231,7 @@ END_VAR
<ST><![CDATA[// Reset all modules in automatic mode
xAllModulesInAutoMode := TRUE;
// Reset Safety
xResetSafetyDCCB := xResetSafety;
_fbSafetyResetImpulseGen();
// ===============================
// DC current measurement
@@ -383,7 +379,6 @@ END_IF
// ===============================
// String ready validation check
// ===============================
_tonResetPulseLength();
_tonErrorDCCBNotClosed();
_tonSafetyOkTimeout();
@@ -436,8 +431,6 @@ CASE _iState OF
1: // Wait for ready in safety check mode
IF _xAllModulesReady THEN
xResetSafetyDCCB := TRUE;
_tonResetPulseLength.IN := TRUE;
_xReleaseLimitErrorsInternal := TRUE;
_iState := 10;
END_IF
@@ -453,9 +446,7 @@ CASE _iState OF
5: // Wait for all modules to be ready in normal mode
IF _xAllModulesReady AND _xBalanceOk THEN
xResetSafetyDCCB := TRUE;
_xReleaseLimitErrorsInternal := TRUE;
_tonResetPulseLength.IN := TRUE;
_iState := 10;
END_IF
@@ -485,17 +476,14 @@ CASE _iState OF
10: // Reset safety from sensors
IF _tonResetPulseLength.Q THEN
_tonResetPulseLength.IN := FALSE;
xResetSafetyDCCB := FALSE;
_tonSafetyOkTimeout.IN := TRUE;
_iState := 15;
END_IF
xResetSafety := FALSE;
_tonSafetyOkTimeout.IN := TRUE;
_iState := 15;
15: // Wait for Safety to be ok
xResetSafetyDCCB := _fbSafetyResetImpulseGen.xOut;
xResetSafety := _fbSafetyResetImpulseGen.xOut;
IF xSafetyIntlksOk THEN
xResetSafetyDCCB := FALSE;
xResetSafety := FALSE;
_tonSafetyOkTimeout.IN := FALSE;
xCloseDCCB := TRUE;
_tonErrorDCCBNotClosed.IN := TRUE;
@@ -504,14 +492,14 @@ CASE _iState OF
IF (NOT xEnable) THEN
_tonSafetyOkTimeout.IN := FALSE;
xResetSafetyDCCB := FALSE;
xResetSafety := FALSE;
_xEnable := FALSE;
_iState := 40;
END_IF
IF _tonSafetyOkTimeout.Q THEN
_tonSafetyOkTimeout.IN := FALSE;
xResetSafetyDCCB := FALSE;
xResetSafety := FALSE;
xCloseDCCB := TRUE;
xError := TRUE;
xReady := FALSE;
@@ -759,7 +747,6 @@ CASE _iState OF
_xReleaseSafetyIntlkErrors := FALSE;
// Reset timer
_tonResetPulseLength(IN := FALSE);
_tonErrorDCCBNotClosed(IN := FALSE);
//eStatus := E_COMPONENT_STATUS.ERROR;
@@ -851,7 +838,10 @@ IF _fbSafetyIntlkTimeoutAlarm.bRaised AND xConfirmAlarms THEN
END_IF
// Copy status to hmi interface
stHMIInterface.eStatus := eStatus;]]></ST>
stHMIInterface.eStatus := eStatus;
// Reset Safety
xResetSafetyDCCB := xResetSafety;]]></ST>
</Implementation>
<Method Name="FB_init" Id="{9e8494eb-1b40-4be9-91c8-810ecbdf7f0c}">
<Declaration><![CDATA[METHOD FB_init : BOOL
@@ -915,6 +905,12 @@ _fbIsolationAlarm.ipArguments.Clear().AddString(_sName);]]></ST>
<ST><![CDATA[// Reset internal error flag
_xErrorInternal := FALSE;
// ===============================
// Safety ComError Handling
// ===============================
IF xSafetyComError THEN
_xErrorInternal := TRUE;
END_IF
// ===============================
// EtherCAT connection lost error handling

View File

@@ -147,6 +147,7 @@ VAR
_xStringsOff : BOOL;
_xStringsBalancingDone : BOOL;
_xStringsInAutoMode : BOOL;
_xStringSafetyComError : BOOL;
_eStringOpMode : E_STRING_OPERATING_MODE;
@@ -260,7 +261,7 @@ END_IF
// Safety
// ===============================
xSafetyErrAck := xSafetyResterTaster;
_xShowAckEmergencyStop := NOT _xEmergencyStopOk;
_xShowAckEmergencyStop := (NOT _xEmergencyStopOk) OR _xStringSafetyComError;
IF (NOT _xEmergencyStopOk) AND (NOT _fbEStopNotOk.bRaised) THEN
_fbEStopNotOk.Raise(0);
@@ -396,8 +397,15 @@ _rSmallestSegmentVoltage := 1_000.0;
_xStringsInAutoMode := TRUE;
_uiNumberOfActiveStrings := 0;
_rStringsSumVoltage := 0;
_xStringSafetyComError := FALSE;
FOR _ui := 0 TO (GVL_CONFIG.uiNumberOfStrings-1) DO
// Check for safety com error
IF _afbStrings[_ui].xSafetyComError THEN
_xStringSafetyComError := TRUE;
END_IF
// Ignore deactivated strings
IF (NOT GVL_CONFIG.axStringEnabled[_ui]) THEN
CONTINUE;

View File

@@ -38,6 +38,9 @@ VAR
// FB for writing Modbus holding registers for inverter heartbeat
_fbWriteHeartbeatRegister : FB_MBWriteRegs;
// FB for reading Modbus holding registers for inverter heartbeat
_fbReadHeartbeatRegister : FB_MBReadRegs;
// Timer for checking if the inverter started in a reasonable amount of time
//_tonInverterStartup : TON;
@@ -226,30 +229,7 @@ IF (rPower < -rMaxBattPower) THEN
rPower := -rMaxBattPower;
END_IF
// Increment heartbeat counter
_tonHearbeatIncTimer(IN := TRUE);
IF _tonHearbeatIncTimer.Q THEN
_tonHearbeatIncTimer(IN := FALSE);
_uiPLCToInverterCounter := _uiPLCToInverterCounter + 1;
_fbWriteHeartbeatRegister.bExecute := TRUE;
END_IF
_fbWriteHeartbeatRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= CONTROLLER_HB,
cbLength:= SIZEOF(_uiPLCToInverterCounter),
pSrcAddr:= ADR(_uiPLCToInverterCounter),
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> );
// If writing modbus register is done
IF NOT _fbWriteHeartbeatRegister.bBusy THEN
// And there is no error, then continue
_fbWriteHeartbeatRegister(bExecute := FALSE);
END_IF
HandleHeartbeat();
// State machine
CASE _iState OF
@@ -362,7 +342,7 @@ CASE _iState OF
// If there was no error and the converter has no error continue
IF NOT _fbReadRegister.bError THEN
// Go back to polling state
_iState := 6;
_iState := 0;
stCurrentValues.rActACCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
stCurrentValues.rActtACPhaseACurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[1]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
stCurrentValues.rActtACPhaseBCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
@@ -379,46 +359,6 @@ CASE _iState OF
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
6: // Check heartbeat signal
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= PCS_HB,
cbLength:= SIZEOF(_uiInverterToPLCCounter),
pDestAddr:= ADR(_uiInverterToPLCCounter),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
IF NOT _fbReadRegister.bBusy THEN
IF (NOT _fbReadRegister.bError) THEN
// Check if counter has been incremented by the inverter
IF (_uiInverterToPLCCounter - _uiInverterToPLCCounterOld) > 0 THEN
_xInverterHBCounterIncremented := TRUE;
// Safe old value
_uiInverterToPLCCounterOld := _uiInverterToPLCCounter;
ELSE
_xInverterHBCounterIncremented := FALSE;
END_IF
_iState := 0;
ELSE
xError := TRUE;
_iErrorInState := _iState;
// Goto error state
_iState := 1000;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
10: // Wait for inverter to be online and in state STANDBY(8)
@@ -979,7 +919,7 @@ CASE _iState OF
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
IF NOT _fbReadRegister.bError THEN
_iState := 91;
_iState := 93;
stCurrentValues.uiStatus := _uiInverterState;
ELSE
_iErrorInState := _iState;
@@ -989,78 +929,6 @@ CASE _iState OF
_fbReadRegister(bExecute := FALSE);
END_IF
91: // Send heartbeat signal
_uiPLCToInverterCounter := _uiPLCToInverterCounter + 1;
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= CONTROLLER_HB,
cbLength:= SIZEOF(_uiPLCToInverterCounter),
pSrcAddr:= ADR(_uiPLCToInverterCounter),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> );
// If writing modbus register is done
IF NOT _fbWriteRegister.bBusy THEN
// And there is no error, then continue
IF NOT _fbWriteRegister.bError THEN
_iState := 92;
ELSE
_iErrorInState := _iState;
xError := TRUE;
// Goto error state
_iState := 1000;
END_IF
_fbWriteRegister(bExecute := FALSE);
END_IF
92: // Check heartbeat signal
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= PCS_HB,
cbLength:= SIZEOF(_uiInverterToPLCCounter),
pDestAddr:= ADR(_uiInverterToPLCCounter),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
IF NOT _fbReadRegister.bBusy THEN
IF (NOT _fbReadRegister.bError) THEN
// Check if counter has been incremented by the inverter
IF (_uiInverterToPLCCounter - _uiInverterToPLCCounterOld) > 0 THEN
_xInverterHBCounterIncremented := TRUE;
// Safe old value
_uiInverterToPLCCounterOld := _uiInverterToPLCCounter;
ELSE
_xInverterHBCounterIncremented := FALSE;
END_IF
// _iState := 65;
_iState := 93;
ELSE
xError := TRUE;
_iErrorInState := _iState;
// Goto error state
_iState := 1000;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
93: // Send current power demand
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,
@@ -1223,11 +1091,14 @@ CASE _iState OF
1000: // Write error state to log
ADSLOGDINT(msgCtrlMask:= ADSLOG_MSGTYPE_ERROR, msgFmtStr:= 'Fehler im state: %s', dintArg:= INT_TO_DINT(_iErrorInState));
_fbWriteRegister(bExecute := FALSE);
_fbReadRegister(bExecute := FALSE);
xActive := FALSE;
xError := TRUE;
_iState := 1001;
1001: // Error state, wait for reset
IF xReset AND (NOT xEnable) THEN
IF xReset AND xHeartbeatOk AND (NOT xEnable) THEN
_iState := 1010;
END_IF
@@ -1270,11 +1141,13 @@ IF _fbHeartbeatTimeout.Q THEN
xHeartbeatOk := FALSE;
END_IF
IF (NOT xHeartbeatOk) AND (_iState < 1000) THEN
_iState := 1000;
END_IF
// ===============================
// Inverter alarm handling
// ===============================
IF xError AND (NOT _fbErrorInverterAlarm.bRaised) THEN
_fbErrorInverterAlarm.Raise(0);
END_IF
@@ -1304,6 +1177,74 @@ _fbErrorInverterAlarm.CreateEx(stEventEntry := TC_EVENTS.Inverter.InverterError,
_fbErrorInverterAlarm.ipArguments.Clear().AddString(_sName);]]></ST>
</Implementation>
</Method>
<Action Name="HandleHeartbeat" Id="{323d78bf-2521-40eb-b5f1-47fb6b9e0ed1}">
<Implementation>
<ST><![CDATA[// Increment heartbeat counter and check current heartbeat
_tonHearbeatIncTimer(IN := TRUE);
IF _tonHearbeatIncTimer.Q THEN
_tonHearbeatIncTimer(IN := FALSE);
_uiPLCToInverterCounter := _uiPLCToInverterCounter + 1;
IF (NOT _fbWriteHeartbeatRegister.bBusy) THEN
_fbWriteHeartbeatRegister.bExecute := TRUE;
END_IF
IF (NOT _fbReadHeartbeatRegister.bBusy) THEN
_fbReadHeartbeatRegister.bExecute := TRUE;
END_IF
END_IF
// Write new heartbeat counter
_fbWriteHeartbeatRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= CONTROLLER_HB,
cbLength:= SIZEOF(_uiPLCToInverterCounter),
pSrcAddr:= ADR(_uiPLCToInverterCounter),
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> );
// If writing modbus register is done
IF (NOT _fbWriteHeartbeatRegister.bBusy) THEN
_fbWriteHeartbeatRegister(bExecute := FALSE);
END_IF
// Read current heartbeat counter
_fbReadHeartbeatRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= PCS_HB,
cbLength:= SIZEOF(_uiInverterToPLCCounter),
pDestAddr:= ADR(_uiInverterToPLCCounter),
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
IF (NOT _fbReadHeartbeatRegister.bBusy) THEN
_fbReadHeartbeatRegister(bExecute := FALSE);
IF (NOT _fbReadHeartbeatRegister.bError) THEN
// Check if counter has been incremented by the inverter
IF (_uiInverterToPLCCounter - _uiInverterToPLCCounterOld) > 0 THEN
_xInverterHBCounterIncremented := TRUE;
// Safe old value
_uiInverterToPLCCounterOld := _uiInverterToPLCCounter;
ELSE
_xInverterHBCounterIncremented := FALSE;
END_IF
ELSE
// only flag heartbeat as incremented of modbusregister could be read
_xInverterHBCounterIncremented := FALSE;
END_IF
END_IF]]></ST>
</Implementation>
</Action>
<Property Name="Name" Id="{ef8c6e8f-7c1b-4781-b201-87f759acb289}">
<Declaration><![CDATA[PROPERTY Name : string]]></Declaration>
<Get Name="Get" Id="{bc17161e-727d-4abd-a845-a7eacc08f995}">