Implemented a better balancing algorith for string balancing
* Added error logging to inverter fb * Changed HMI actual power feedback from dc to ac power * Small config adjustments
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.11">
|
||||
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.12">
|
||||
<GVL Name="GVL_CONFIG" Id="{0773bf51-0237-454d-a970-cfd896054edb}">
|
||||
<Declaration><![CDATA[{attribute 'qualified_only'}
|
||||
VAR_GLOBAL CONSTANT
|
||||
@@ -187,10 +187,10 @@ VAR_GLOBAL PERSISTENT
|
||||
// ===========================
|
||||
|
||||
// Pump posolyt on power in %
|
||||
rPumpPosolytOnPower : REAL := 65.0;
|
||||
rPumpPosolytOnPower : REAL := 70.0;
|
||||
|
||||
// Pump negolyt on power in %
|
||||
rPumpNegolytOnPower : REAL := 65.0;
|
||||
rPumpNegolytOnPower : REAL := 70.0;
|
||||
|
||||
// Pump posolyt discharge segment without inverter power in %
|
||||
rPumpPosolytDisChrgPower : REAL := 45.0;
|
||||
@@ -259,7 +259,10 @@ VAR_GLOBAL PERSISTENT
|
||||
timStringReadyTimeout : TIME := T#3M;
|
||||
|
||||
// Timeout for isolation error
|
||||
timIsoErrorTimeout : TIME := T#20s;
|
||||
timIsoErrorTimeout : TIME := T#20S;
|
||||
|
||||
// Balancing factor
|
||||
rBalancingFactor : REAL := 20.0;
|
||||
|
||||
// Dummy to deactivate functions
|
||||
{attribute 'analysis' := '-33'}
|
||||
|
||||
30
PLC/PLC.tmc
30
PLC/PLC.tmc
File diff suppressed because one or more lines are too long
@@ -131,6 +131,7 @@ VAR
|
||||
|
||||
// Sum of voltage of all active strings
|
||||
_rStringsSumVoltage : REAL;
|
||||
_rDeltaUm : REAL;
|
||||
_arPowerString : ARRAY[0..(GVL_CONFIG.uiNumberOfStrings-1)] OF REAL;
|
||||
|
||||
_ui : UINT := 0;
|
||||
@@ -607,7 +608,7 @@ GVL_SCADA.xCanChangeControlMode := _xCanChangeMode;
|
||||
GVL_SCADA.eCurrentControlMode := _eBMSControlMode;
|
||||
|
||||
// Calculate current battery dc power
|
||||
GVL_SCADA.diCurrentBatteryPower := REAL_TO_DINT(_afbStrings[0].stInverterData.rActDCPower + _afbStrings[1].stInverterData.rActDCPower);
|
||||
GVL_SCADA.diCurrentBatteryPower := REAL_TO_DINT(_afbStrings[0].stInverterData.rActACPower + _afbStrings[1].stInverterData.rActACPower);
|
||||
|
||||
// Read power values if commanded
|
||||
_fbPowerMeterPower(
|
||||
@@ -927,14 +928,17 @@ _fbPowerMeter24V();]]></ST>
|
||||
END_CASE
|
||||
|
||||
// Calculate string power balancing
|
||||
IF _rStringsSumVoltage <> 0 THEN
|
||||
IF _rStringsSumVoltage <> 0 AND (GVL_CONFIG.uiNumberOfStrings <> 0) THEN
|
||||
FOR _ui := 0 TO (GVL_CONFIG.uiNumberOfStrings-1) DO
|
||||
// Calculate delta u to middle voltage
|
||||
_rDeltaUm := (_afbStrings[_ui].rCurrentVoltage * GVL_CONFIG.uiNumberOfStrings - _rStringsSumVoltage) / _rStringsSumVoltage;
|
||||
|
||||
// Discharging
|
||||
IF _rPowerInverter > 0 THEN
|
||||
_arPowerString[_ui] := _rPowerInverter * (_afbStrings[_ui].rCurrentVoltage / _rStringsSumVoltage);
|
||||
_arPowerString[_ui] := (_rPowerInverter / GVL_CONFIG.uiNumberOfStrings) * ( 1 + (_rDeltaUm * GVL_CONFIG.rBalancingFactor));
|
||||
// Charging
|
||||
ELSIF _rPowerInverter < 0 THEN
|
||||
_arPowerString[_ui] := _rPowerInverter * (1.0 - (_afbStrings[_ui].rCurrentVoltage / _rStringsSumVoltage));
|
||||
_arPowerString[_ui] := (_rPowerInverter / GVL_CONFIG.uiNumberOfStrings) * ( 1 - (_rDeltaUm * GVL_CONFIG.rBalancingFactor));
|
||||
// Nothing
|
||||
ELSE
|
||||
_arPowerString[_ui] := 0.0;
|
||||
|
||||
@@ -260,6 +260,7 @@ CASE _iState OF
|
||||
IF NOT _fbReadRegister.bError THEN
|
||||
_iState := 2;
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
_fbReadRegister(bExecute := FALSE);
|
||||
@@ -276,7 +277,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
3: // Read current DC values
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -301,6 +301,7 @@ CASE _iState OF
|
||||
stCurrentValues.rActDCVoltage := LREAL_TO_REAL(WORD_TO_UINT(_awCurrentDCValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[3])));
|
||||
stCurrentValues.rActDCPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[4]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[5])));
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Read error register
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -309,7 +310,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
4: // Read current ac values
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -341,6 +341,7 @@ CASE _iState OF
|
||||
stCurrentValues.rActReactivePower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[18]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[19])));
|
||||
stCurrentValues.rActPowerFactor := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[20]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[21])));
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Read error register
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -350,7 +351,6 @@ CASE _iState OF
|
||||
|
||||
5: // Send heartbeat signal
|
||||
_uiPLCToInverterCounter := _uiPLCToInverterCounter + 1;
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -372,6 +372,7 @@ CASE _iState OF
|
||||
_iState := 6;
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -410,6 +411,7 @@ CASE _iState OF
|
||||
_iState := 0;
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -471,7 +473,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
20: // Read inverter max power scaling
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -500,6 +501,7 @@ CASE _iState OF
|
||||
END_IF
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -508,7 +510,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
25: // Read inverter Max power limit scaling
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -536,6 +537,7 @@ CASE _iState OF
|
||||
END_IF
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -544,7 +546,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
26: // Read inverter scaling factor for reactive power
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -572,6 +573,7 @@ CASE _iState OF
|
||||
END_IF
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -580,7 +582,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
30: // Read inverter max power
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -608,6 +609,7 @@ CASE _iState OF
|
||||
_iWMaxLimPct := LREAL_TO_INT((_rPowerInternal*100)/(_rWMax * EXPT(10,_iWMaxLimPctSF)));
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -616,7 +618,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
40: // Set power limit
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -644,6 +645,7 @@ CASE _iState OF
|
||||
ELSE
|
||||
_uiSetPowerLimitErrorCounter := _uiSetPowerLimitErrorCounter + 1;
|
||||
IF _uiSetPowerLimitErrorCounter > 5 THEN
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
ELSE
|
||||
@@ -661,7 +663,6 @@ CASE _iState OF
|
||||
END_IF
|
||||
|
||||
42: // Set max reactive power in percent
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -683,6 +684,7 @@ CASE _iState OF
|
||||
_iState := 42;
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -691,7 +693,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
43: // Enable reactive power percent limiting
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -713,6 +714,7 @@ CASE _iState OF
|
||||
_iState := 50;
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -721,7 +723,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
50: // Enable Power limiting (THROTTLED)
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -745,6 +746,7 @@ CASE _iState OF
|
||||
xActive := TRUE;
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -753,7 +755,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
51: // Go to started
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -776,6 +777,7 @@ CASE _iState OF
|
||||
_iState := 60;
|
||||
ELSE
|
||||
_uiPCSSetOperation := 1;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -784,7 +786,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
60: // Switch to THROTTLED mode
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -805,6 +806,7 @@ CASE _iState OF
|
||||
IF NOT _fbWriteRegister.bError THEN
|
||||
_iState := 65;
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -840,7 +842,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
70: // Enabled, check for error
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -870,6 +871,8 @@ CASE _iState OF
|
||||
xError := TRUE;
|
||||
xActive := FALSE;
|
||||
_uiPCSSetOperation := 3;
|
||||
_iErrorInState := _iState;
|
||||
ADSLOGDINT(msgCtrlMask:= ADSLOG_MSGTYPE_ERROR, msgFmtStr:= 'Fehler im state: %s', dintArg:= INT_TO_DINT(_iErrorInState));
|
||||
// Read error register
|
||||
_iState := 200;
|
||||
END_IF
|
||||
@@ -878,7 +881,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
80: // Read current DC values
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -903,6 +905,7 @@ CASE _iState OF
|
||||
stCurrentValues.rActDCVoltage := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[3])));
|
||||
stCurrentValues.rActDCPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[4]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[5])));
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Read error register
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -911,7 +914,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
85: // Read current ac values
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -943,6 +945,7 @@ CASE _iState OF
|
||||
stCurrentValues.rActReactivePower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[18]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[19])));
|
||||
stCurrentValues.rActPowerFactor := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[20]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[21])));
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Read error register
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -972,6 +975,7 @@ CASE _iState OF
|
||||
_iState := 91;
|
||||
stCurrentValues.uiStatus := _uiInverterState;
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Read error register
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -981,7 +985,6 @@ CASE _iState OF
|
||||
|
||||
91: // Send heartbeat signal
|
||||
_uiPLCToInverterCounter := _uiPLCToInverterCounter + 1;
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -1002,6 +1005,7 @@ CASE _iState OF
|
||||
IF NOT _fbWriteRegister.bError THEN
|
||||
_iState := 92;
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
xError := TRUE;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
@@ -1042,6 +1046,7 @@ CASE _iState OF
|
||||
_iState := 93;
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -1050,7 +1055,6 @@ CASE _iState OF
|
||||
END_IF
|
||||
|
||||
93: // Send current power demand
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -1078,6 +1082,7 @@ CASE _iState OF
|
||||
ELSE
|
||||
_uiSetPowerLimitErrorCounter := _uiSetPowerLimitErrorCounter + 1;
|
||||
IF _uiSetPowerLimitErrorCounter > 5 THEN
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
ELSE
|
||||
@@ -1089,7 +1094,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
200: // Shutdown send zero power command
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -1111,6 +1115,7 @@ CASE _iState OF
|
||||
_iState := 201;
|
||||
_uiPCSSetOperation := 3;
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -1118,7 +1123,6 @@ CASE _iState OF
|
||||
END_IF
|
||||
|
||||
201: // Shutdown sequence
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -1139,6 +1143,7 @@ CASE _iState OF
|
||||
IF NOT _fbWriteRegister.bError THEN
|
||||
_iState := 210;
|
||||
ELSE
|
||||
_iErrorInState := _iState;
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
@@ -1184,7 +1189,6 @@ CASE _iState OF
|
||||
|
||||
|
||||
990: // Read error register
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
@@ -1204,13 +1208,17 @@ CASE _iState OF
|
||||
IF NOT _fbReadRegister.bBusy THEN
|
||||
// If there was no error and the converter has no error continue
|
||||
IF NOT _fbReadRegister.bError THEN
|
||||
_iErrorInState := _iState;
|
||||
_iState := 1000;
|
||||
END_IF
|
||||
_fbReadRegister(bExecute := FALSE);
|
||||
END_IF
|
||||
|
||||
1000: // Write error state to log
|
||||
ADSLOGDINT(msgCtrlMask:= ADSLOG_MSGTYPE_ERROR, msgFmtStr:= 'Fehler im state: %s', dintArg:= INT_TO_DINT(_iErrorInState));
|
||||
_iState := 1001;
|
||||
|
||||
1000: // Error state, wait for reset
|
||||
1001: // Error state, wait for reset
|
||||
IF xReset AND (NOT xEnable) THEN
|
||||
_iState := 1010;
|
||||
END_IF
|
||||
|
||||
@@ -269,7 +269,7 @@
|
||||
</System>
|
||||
<Plc>
|
||||
<Project GUID="{9AE64910-5EB2-4866-93FD-EFE059C38C36}" Name="PLC" PrjFilePath="PLC\PLC.plcproj" TmcFilePath="PLC\PLC.tmc" ReloadTmc="true" AmsPort="851" FileArchiveSettings="#x000e" CopyTmcToTarget="true" CopyTpyToTarget="false" SymbolicMapping="true">
|
||||
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" TmcHash="{7ED08416-1955-C55E-9601-98E642FFD609}" TmcPath="PLC\PLC.tmc">
|
||||
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" TmcHash="{09733D5D-F6BF-9F96-D45C-805CEB906D89}" TmcPath="PLC\PLC.tmc">
|
||||
<Name>PLC Instance</Name>
|
||||
<CLSID ClassFactory="TcPlc30">{08500001-0000-0000-F000-000000000064}</CLSID>
|
||||
<Vars VarGrpType="2" AreaNo="1">
|
||||
|
||||
Reference in New Issue
Block a user