diff --git a/PLC/GVLs/GVL_CONFIG.TcGVL b/PLC/GVLs/GVL_CONFIG.TcGVL index 6f4ef4e..e9596ba 100644 --- a/PLC/GVLs/GVL_CONFIG.TcGVL +++ b/PLC/GVLs/GVL_CONFIG.TcGVL @@ -289,7 +289,18 @@ VAR_GLOBAL PERSISTENT rBalancingFactor : REAL := 20.0; // Timeout heartbeat from EMS - timEMSHeartbeatTimeout : TIME := t#5s; + timEMSHeartbeatTimeout : TIME := T#5S; + + // Flag if charging should be done with cv phase at end + xCVCharging : BOOL := FALSE; + + // Controller parameters for cv charging + rCVKp : REAL := 0.0; + // In ms + rCVTn : REAL := 0.0; + + // Minimum current for cv charging in Amps + rMinCVCurrentForFull : REAL := -5.0; // Dummy to deactivate functions {attribute 'analysis' := '-33'} diff --git a/PLC/POUs/FB_String.TcPOU b/PLC/POUs/FB_String.TcPOU index 700aef9..d0ecba8 100644 --- a/PLC/POUs/FB_String.TcPOU +++ b/PLC/POUs/FB_String.TcPOU @@ -389,7 +389,7 @@ xOff := _fbModule1.xOff AND _fbModule2.xOff AND _fbModule3.xOff; _fbInverter( sInverterIPAddr:= sInverterIP, xEnable:= _xEnableInverter AND xEmergencyStopOk, - xReleasePower := xReleaseInverterPower, + xReleasePower := xReleaseInverterPower AND _xEnableInverter, rPower:= _rPowerInverterInternal, xReset:= xConfirmAlarms, rMaxBattPower:= DINT_TO_REAL(GVL_CONFIG.diMaxStringDischargePower), diff --git a/PLC/POUs/MAIN.TcPOU b/PLC/POUs/MAIN.TcPOU index bf76f7a..9ea5586 100644 --- a/PLC/POUs/MAIN.TcPOU +++ b/PLC/POUs/MAIN.TcPOU @@ -210,6 +210,12 @@ VAR _xGetPowerMeterData : BOOL; + _fbPIControl : FB_PI; + _fbLimit : FB_Limit; + _xCVChargingLatched : BOOL; + _rCVSetpoint : REAL; + _xStringsFullCV : BOOL; + _rPowerDH : REAL; _xDHActive : BOOL; _fbTONDHCycleTime : TON := (PT := T#15M); @@ -1087,7 +1093,7 @@ _fbTowerLight( IF _xStringsErrorActive OR _fbStringReadyTimeout.Q THEN _fbStringReadyTimeout(IN := FALSE); - _xStringNotReadyInTime := TRUE; + _xStringNotReadyInTime := _fbStringReadyTimeout.Q; _xEnableString := FALSE; GVL_SCADA.stAutomaticModeHMI.diSetpointAutomatic := 0; _xCanChangeMode := TRUE; @@ -1148,11 +1154,54 @@ _fbTowerLight( _xEnableString := FALSE; GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus := E_CHARGE_STATUS.DISCHARGING; GVL_MODBUS.stModbusEMSComm.stModbusReg10.uiActiveParallelMembers := 0; + _xCVChargingLatched := FALSE; + _fbPIControl.Reset(); _iState := 35; END_IF + // Charge with constant Voltage at charging end + IF GVL_CONFIG.xCVCharging AND (_rAutoPowerRequest < 0.0) AND (_rHighestSegmentVoltage >= (GVL_CONFIG.rMaximumUnitVoltage)) THEN + _xCVChargingLatched := TRUE; + END_IF + + // Delatch if charging power requested is lower than cv power + //IF _xCVChargingLatched AND (_rAutoPowerRequest > _rPowerInverter) THEN + // _xCVChargingLatched := FALSE; + //END_IF + + IF _xCVChargingLatched THEN + // Reglerfreigabe + _rCVSetpoint := GVL_CONFIG.rMaximumUnitVoltage; + ELSE + // Nachführbetrieb + _rCVSetpoint := _rHighestSegmentVoltage; + END_IF + + _fbPIControl( + rSP:= _rCVSetpoint, + rPV:= _rHighestSegmentVoltage, + rKp:= GVL_CONFIG.rCVKp, + rTn:= GVL_CONFIG.rCVTn, + xSaturated:= _fbLimit.xClamped); + + _rPowerInverter := _rAutoPowerRequest - _fbPIControl.rMV; + + _fbLimit( + rIn := _rPowerInverter, + rMin := _rMinPower, + rMax := _rMaxPower, + rOut => _rPowerInverter); + + IF ((GVL_SCADA.stHMIInterface[0].stInverterData.rActDCCurrent > GVL_CONFIG.rMinCVCurrentForFull) AND GVL_CONFIG.axStringEnabled[0]) OR ((GVL_SCADA.stHMIInterface[1].stInverterData.rActDCCurrent > GVL_CONFIG.rMinCVCurrentForFull) AND GVL_CONFIG.axStringEnabled[1]) THEN + _xStringsFullCV := TRUE; + ELSE + _xStringsFullCV := FALSE; + END_IF + // Shutdown triggered by battery fully charged - IF GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus = E_CHARGE_STATUS.CHARGING AND ((_rMaxCurrentInverterDCVoltage >= GVL_CONFIG.rStringFullyChargedVoltage) OR _rHighestSegmentVoltage >= GVL_CONFIG.rMaximumUnitVoltage) THEN + IF GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus = E_CHARGE_STATUS.CHARGING + AND ((_rMaxCurrentInverterDCVoltage >= GVL_CONFIG.rStringFullyChargedVoltage) OR (_rHighestSegmentVoltage >= GVL_CONFIG.rMaximumUnitVoltage AND (NOT _xCVChargingLatched)) OR _xStringsFullCV) THEN +//OR (_xCVChargingLatched AND ((ABS(GVL_SCADA.stHMIInterface[0].rCurrent) < 8.0) OR (ABS(GVL_SCADA.stHMIInterface[0].rCurrent) < 8.0))) _xGetPowerMeterData := TRUE; IF (_eBMSControlMode = E_BMS_CONTROL_MODE.CYCLING) THEN GVL_SCADA.eCycleStatus := E_CYCLE_STATUS.DISCHARGE_STARTED; @@ -1176,9 +1225,10 @@ _fbTowerLight( // Change battery status GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus := E_CHARGE_STATUS.FULL; GVL_MODBUS.stModbusEMSComm.stModbusReg10.uiActiveParallelMembers := 0; + _xCVChargingLatched := FALSE; + _fbPIControl.Reset(); _iState := 35; END_IF - END_IF // Shutdown triggered by battery empty @@ -1206,6 +1256,8 @@ _fbTowerLight( // Change battery status GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus := E_CHARGE_STATUS.EMPTY; GVL_MODBUS.stModbusEMSComm.stModbusReg10.uiActiveParallelMembers := 0; + _xCVChargingLatched := FALSE; + _fbPIControl.Reset(); _iState := 35; END_IF END_IF @@ -1218,6 +1270,8 @@ _fbTowerLight( _tonBeginShutdown(In := FALSE); GVL_SCADA.stAutomaticModeHMI.diSetpointAutomatic := 0; _xCanChangeMode := TRUE; + _xCVChargingLatched := FALSE; + _fbPIControl.Reset(); _iState := 45; END_IF diff --git a/PLC/POUs/Utility/Controller/FB_Limit.TcPOU b/PLC/POUs/Utility/Controller/FB_Limit.TcPOU new file mode 100644 index 0000000..f989711 --- /dev/null +++ b/PLC/POUs/Utility/Controller/FB_Limit.TcPOU @@ -0,0 +1,30 @@ + + + + + + rMax THEN + rOut := rMax; + xClamped := TRUE; +ELSIF rIn < rMin THEN + rOut := rMin; + xClamped := TRUE; +ELSE + rOut := rIn; + xClamped := FALSE; +END_IF]]> + + + \ No newline at end of file diff --git a/PLC/POUs/Utility/Controller/FB_PI.TcPOU b/PLC/POUs/Utility/Controller/FB_PI.TcPOU new file mode 100644 index 0000000..64be941 --- /dev/null +++ b/PLC/POUs/Utility/Controller/FB_PI.TcPOU @@ -0,0 +1,68 @@ + + + + + + 0) THEN + _rIntegral := _rIntegral + (rKp * _rT / rTn) * _rError; +END_IF + +// Reset integral with deactivated integral time +IF (rTn = 0.0) AND (_rIntegral <> 0) THEN + _rIntegral := 0.0; +END_IF]]> + + + + + + + + + + + + + + \ No newline at end of file