Added error and waring messages and updated tower light inputs

- Added strings not ready in time error
- Added battery already full warning
- Added battery already empty warning
- Added battery in stop input to tower light
- Added warnings active to tower light
- Added BMS State Machine errors to tower light input
This commit is contained in:
Matthias Heisig
2025-09-10 12:13:40 +02:00
parent d718c813c9
commit 0d3369d54d
9 changed files with 552 additions and 413 deletions

View File

@@ -70,6 +70,15 @@ VAR
// NA Protection Alarm
_fbNAProtectionAlarm : FB_TcAlarm;
// String ready timeout alarm
_fbStringReadyTimeoutAlarm : FB_AlarmMessage;
// Battery already full warning
_fbBatteryAlreadyFullWarning : FB_AlarmMessage;
// Battery already empty warning
_fbBatteryAlreadyEmptyWarning : FB_AlarmMessage;
// First cycle tag
_xFirstCycle : BOOL := TRUE;
@@ -120,6 +129,7 @@ VAR
_xErrorActive : BOOL;
_xWarningActive : BOOL;
_xBatteryActive : BOOL;
// Battery in safety check mode
_xInSafetyCheckMode : BOOL;
@@ -149,6 +159,7 @@ VAR
// Hardware reset button rising edge trigger
_fbRTrigHardwareAck : R_TRIG;
// String not ready in time timeout
_fbStringReadyTimeout : TON;
// Sum of voltage of all active strings
@@ -176,6 +187,9 @@ VAR
_xStringsInAutoMode : BOOL;
_xStringSafetyComError : BOOL;
_xStringNotReadyInTime : BOOL;
_xErrorBMSSMActive : BOOL;
_eStringOpMode : E_STRING_OPERATING_MODE;
_rMaxCurrentInverterDCVoltage : REAL;
@@ -227,6 +241,10 @@ END_VAR
_fbEMSHeartbeatAlarm.CreateEx(stEventEntry := TC_EVENTS.BMSEvents.EMSHeartbeatTimeout, TRUE, 0);
_fbNAProtectionAlarm.CreateEx(stEventEntry := TC_EVENTS.BMSEvents.NAProtectionTripped, TRUE, 0);
_fbStringReadyTimeoutAlarm.Init(stEventType := TC_EVENTS.BMSEvents.StringReadyTimeout, TRUE);
_fbBatteryAlreadyFullWarning.Init(stEventType := TC_EVENTS.BMSEvents.BatteryAlreadyFull, FALSE);
_fbBatteryAlreadyEmptyWarning.Init(stEventType := TC_EVENTS.BMSEvents.BatteryAlreadyEmpty, FALSE);
END_IF
// Reset error flag
@@ -518,7 +536,7 @@ IF _fbTempCabinetSCSString2.xError THEN
_xErrorActive := TRUE;
END_IF
// Handle string 1 modbus error and warning
// Handle string 2 modbus error and warning
GVL_MODBUS.stBMSErrorReg.wStringErrorActive.1 := _afbStrings[1].xError;
GVL_MODBUS.stBMSErrorReg.wStringWarningActive.1 := _afbStrings[1].xWarning;
GVL_MODBUS.stBMSErrorReg.wString2ErrorActive.stBitmap.bDCSwitch := (NOT _afbStrings[1].xRepairSwitchOk);
@@ -528,9 +546,6 @@ GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.stBitmap.bTCabinetString2Module2High
GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.stBitmap.bTCabinetString2Module3High := _afbStrings[1].xTempCabinetModule3Warning;
GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.stBitmap.bTCabinetSCSString2High := _fbTempCabinetSCSString2.xWarningHigh;
// Copy general error to modbus error register
GVL_MODBUS.stBMSErrorReg.wBMSErrorActive.stBitmap.bError := _xErrorActive;
// ===============================
// Get global string status information
@@ -950,6 +965,10 @@ IF _xGetPowerMeterData THEN
END_IF
// Handle modbus global warning and error flag
GVL_MODBUS.stBMSErrorReg.wBMSErrorActive.stBitmap.bError := _xErrorActive OR _xErrorBMSSMActive;
// Call safety fb
_fbSafety(refuStringErrorsModbus := GVL_MODBUS.stBMSErrorReg.wBMSErrorActive);
@@ -971,6 +990,7 @@ END_IF
// Reset alarm confirmation
IF _xConfirmAlarms OR _rtHardwareResetButton.Q THEN
_xErrorBMSSMActive := FALSE;
GVL_MODBUS.stBMSErrorReg.wBMSErrorActive.wRegister := 0;
GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.wRegister := 0;
GVL_MODBUS.stBMSErrorReg.wString1ErrorActive.wRegister := 0;
@@ -981,10 +1001,10 @@ END_IF
_fbPowerMeter24V();
_fbTowerLight(
xAutoInStop := FALSE,
xWarningActive := FALSE,
xAutoInStop := NOT _xBatteryActive,
xWarningActive := _xWarningActive,
xWarningConfirmPending := FALSE,
xErrorActive := _xErrorActive,
xErrorActive := _xErrorActive OR _xErrorBMSSMActive,
xErrorConfirmPending := FALSE);]]></ST>
</Implementation>
<Action Name="SM_AUTO" Id="{b5166e16-4fea-442b-9560-02c156f9a9ad}">
@@ -1025,6 +1045,7 @@ _fbTowerLight(
IF _xStringsReady AND (NOT _xStringsErrorActive) THEN
_xGetPowerMeterData := TRUE;
_fbStringReadyTimeout(IN := FALSE);
GVL_MODBUS.stBMSErrorReg.wBMSErrorActive.stBitmap.bStringsNotReadyInTime := 1;
_rPowerInverter := 0.0;
// Set active parallel members (modbus)
GVL_MODBUS.stModbusEMSComm.stModbusReg10.uiActiveParallelMembers := GVL_CONFIG.uiNumberOfStrings;
@@ -1034,10 +1055,11 @@ _fbTowerLight(
IF _xStringsErrorActive OR _fbStringReadyTimeout.Q THEN
_fbStringReadyTimeout(IN := FALSE);
_xStringNotReadyInTime := TRUE;
_xEnableString := FALSE;
GVL_SCADA.stAutomaticModeHMI.diSetpointAutomatic := 0;
_xCanChangeMode := TRUE;
_iState := 45;
_iState := 1000;
END_IF
@@ -1053,6 +1075,7 @@ _fbTowerLight(
// Set inverter power to modbus requested power
_rPowerInverter := _rAutoPowerRequest;
_xReleaseInverterPower := TRUE;
_xBatteryActive := TRUE;
// Check if the battery should still be active
IF (_rAutoPowerRequest = 0.0) AND NOT GVL_MODBUS.stModbusEMSComm.stModbusReg12.wBMSControlsRegister.stBitmap.bScheduleActive THEN
@@ -1172,6 +1195,7 @@ _fbTowerLight(
IF GVL_CONFIG.xShutdownDischargeWithInverter THEN
_iState := 40;
ELSE
_xBatteryActive := FALSE;
_xReleaseInverterPower := FALSE;
_rPowerInverter := 0.0;
_xEnableString := FALSE;
@@ -1193,6 +1217,7 @@ _fbTowerLight(
IF _xStringsShutdownDischargeAllowed OR _xEMSHeartbeatNotOK THEN
_rPowerInverter := GVL_CONFIG.rAbsShutdownDischargePower;
ELSE
_xBatteryActive := FALSE;
_xReleaseInverterPower := FALSE;
_xGetPowerMeterData := TRUE;
GVL_MODBUS.stModbusEMSComm.stModbusReg10.uiActiveParallelMembers := 0;
@@ -1213,12 +1238,10 @@ _fbTowerLight(
IF (ABS(_rAutoPowerRequest) > DINT_TO_REAL(GVL_CONFIG.diMinimumAbsPowerForEnable)) AND (NOT _xStringsErrorActive) AND _xStringsAllInAutomaticMode THEN
IF _rAutoPowerRequest < 0 AND GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus <> E_CHARGE_STATUS.FULL THEN
_iState := 0;
// TODO: Meldung ausgeben, dass Batterie schon voll ist
END_IF
IF _rAutoPowerRequest > 0 AND GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus <> E_CHARGE_STATUS.EMPTY THEN
_iState := 0;
// TODO: Meldung ausgeben, dass Batterie schon leer ist.
END_IF
END_IF
@@ -1236,12 +1259,10 @@ _fbTowerLight(
_xCanChangeMode := FALSE;
IF (_rAutoPowerRequest < 0 OR GVL_MODBUS.stModbusEMSComm.stModbusReg12.wBMSControlsRegister.stBitmap.bScheduleActive) AND GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus <> E_CHARGE_STATUS.FULL THEN
_iState := 0;
// TODO: Meldung ausgeben, dass Batterie schon voll ist
END_IF
IF (_rAutoPowerRequest > 0 OR GVL_MODBUS.stModbusEMSComm.stModbusReg12.wBMSControlsRegister.stBitmap.bScheduleActive) AND GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus <> E_CHARGE_STATUS.EMPTY THEN
_iState := 0;
// TODO: Meldung ausgeben, dass Batterie schon leer ist.
END_IF
IF (_rAutoPowerRequest <> 0 OR GVL_MODBUS.stModbusEMSComm.stModbusReg12.wBMSControlsRegister.stBitmap.bScheduleActive) THEN
@@ -1263,8 +1284,11 @@ _fbTowerLight(
GVL_MODBUS.stModbusEMSComm.stModbusReg10.uiActiveParallelMembers := 0;
_xReleaseInverterPower := FALSE;
_xEnableString := FALSE;
_xBatteryActive := FALSE;
_rPowerInverter := 0.0;
GVL_MODBUS.stModbusEMSComm.stModbusReg11.eBatteryStatus := E_BATTERY_STATUS.ERROR;
_xErrorBMSSMActive := TRUE;
_xStringNotReadyInTime := FALSE;
_iState := 1010;
1010: // Wait for reset from error state
@@ -1285,6 +1309,32 @@ _fbTowerLight(
END_IF
END_CASE
// String not ready in time alarm
_fbStringReadyTimeoutAlarm(xActive := _xStringNotReadyInTime , xAcknowledge := _xConfirmAlarms);
IF GVL_MODBUS.stBMSErrorReg.wBMSErrorActive.stBitmap.bStringsNotReadyInTime AND _fbStringReadyTimeoutAlarm.ClearedAndConfirmed THEN
GVL_MODBUS.stBMSErrorReg.wBMSErrorActive.stBitmap.bStringsNotReadyInTime := 0;
END_IF
// Battery already full warning
IF (_rAutoPowerRequest < 0) AND GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus = E_CHARGE_STATUS.FULL THEN
GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.stBitmap.bBatteryAlreadyFull := 1;
_fbBatteryAlreadyFullWarning(xActive := TRUE);
_xWarningActive := TRUE;
ELSE
GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.stBitmap.bBatteryAlreadyFull := 0;
_fbBatteryAlreadyFullWarning(xActive := FALSE);
END_IF
// Battery already empty
IF (_rAutoPowerRequest > 0) AND GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus = E_CHARGE_STATUS.EMPTY THEN
GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.stBitmap.bBatteryAlreadyEmpty := 1;
_fbBatteryAlreadyEmptyWarning(xActive := TRUE);
_xWarningActive := TRUE;
ELSE
GVL_MODBUS.stBMSErrorReg.wBMSWarningActive.stBitmap.bBatteryAlreadyEmpty := 0;
_fbBatteryAlreadyEmptyWarning(xActive := FALSE);
END_IF
// Calculate string power balancing
IF _rStringsSumVoltage <> 0 AND (_uiNumberOfActiveStrings <> 0) THEN
FOR _ui := 0 TO (GVL_CONFIG.uiNumberOfStrings-1) DO