Change E-Stop so that it can also work with one string
- Also optimized CV charging
This commit is contained in:
@@ -551,12 +551,10 @@ CASE _iState OF
|
||||
CASE eOperationMode OF
|
||||
E_STRING_OPERATING_MODE.AUTOMATIC:
|
||||
_rPowerInverterInternal := rPowerInverter;
|
||||
_xEnableInverter := TRUE;
|
||||
_iState := 21;
|
||||
|
||||
E_STRING_OPERATING_MODE.SAFETY_CHECK:
|
||||
_rPowerInverterInternal := 0.0;
|
||||
_xEnableInverter := TRUE;
|
||||
_iState := 21;
|
||||
|
||||
E_STRING_OPERATING_MODE.PRECHARGE:
|
||||
|
||||
@@ -214,12 +214,17 @@ VAR
|
||||
_fbLimit : FB_Limit;
|
||||
_xCVChargingLatched : BOOL;
|
||||
_rCVSetpoint : REAL;
|
||||
_xStringsFullCV : BOOL;
|
||||
|
||||
_rPowerDH : REAL;
|
||||
_xDHActive : BOOL;
|
||||
_fbTONDHCycleTime : TON := (PT := T#15M);
|
||||
|
||||
_xFullByVoltage : BOOL;
|
||||
_xFullByCV : BOOL;
|
||||
_fbTONCVLow : TON;
|
||||
_xCVCurrentLimitReached : BOOL;
|
||||
_fbPT1CVAntiAliasFilter : FB_PT1Filter;
|
||||
|
||||
// tower light
|
||||
_fbTowerLight : FB_TowerLight;
|
||||
END_VAR
|
||||
@@ -1116,7 +1121,7 @@ _fbTowerLight(
|
||||
_xBatteryActive := TRUE;
|
||||
|
||||
// Check if the battery should still be active
|
||||
IF (_rAutoPowerRequest = 0.0) AND ((NOT GVL_MODBUS.stModbusEMSComm.stModbusReg12.wBMSControlsRegister.stBitmap.bScheduleActive) OR (NOT _xDHActive)) THEN
|
||||
IF (_rAutoPowerRequest = 0.0) AND (NOT GVL_MODBUS.stModbusEMSComm.stModbusReg12.wBMSControlsRegister.stBitmap.bScheduleActive) AND (NOT _xDHActive) THEN
|
||||
_xNoPowerRequested := TRUE;
|
||||
ELSE
|
||||
_xNoPowerRequested := FALSE;
|
||||
@@ -1164,10 +1169,7 @@ _fbTowerLight(
|
||||
_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
|
||||
@@ -1177,31 +1179,43 @@ _fbTowerLight(
|
||||
_rCVSetpoint := _rHighestSegmentVoltage;
|
||||
END_IF
|
||||
|
||||
_fbPT1CVAntiAliasFilter(rInput := _rHighestSegmentVoltage, timT := T#200MS);
|
||||
|
||||
_fbPIControl(
|
||||
xEnable := _xCVChargingLatched,
|
||||
rSP:= _rCVSetpoint,
|
||||
rPV:= _rHighestSegmentVoltage,
|
||||
rPV:= _fbPT1CVAntiAliasFilter.rOutput,
|
||||
rKp:= GVL_CONFIG.rCVKp,
|
||||
rTn:= GVL_CONFIG.rCVTn,
|
||||
xSaturated:= _fbLimit.xClamped);
|
||||
|
||||
_rPowerInverter := _rAutoPowerRequest - _fbPIControl.rMV;
|
||||
_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;
|
||||
|
||||
// Delatch if charging power requested is lower than cv power
|
||||
IF _xCVChargingLatched AND (_rAutoPowerRequest > _rPowerInverter) THEN
|
||||
_xCVChargingLatched := FALSE;
|
||||
END_IF
|
||||
|
||||
_xFullByVoltage := (NOT GVL_CONFIG.xCVCharging)
|
||||
AND (_rPowerInverter < 0)
|
||||
AND ((_rMaxCurrentInverterDCVoltage >= GVL_CONFIG.rStringFullyChargedVoltage) OR (_rHighestSegmentVoltage >= GVL_CONFIG.rMaximumUnitVoltage));
|
||||
|
||||
_xCVCurrentLimitReached := ((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]);
|
||||
_fbTONCVLow(
|
||||
IN := (_rPowerInverter < 0) AND _xCVCurrentLimitReached AND _xCVChargingLatched,
|
||||
PT := GVL_CONFIG.timCVCurrentReached
|
||||
);
|
||||
|
||||
_xFullByCV := GVL_CONFIG.xCVCharging AND _fbTONCVLow.Q;
|
||||
|
||||
// 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 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)))
|
||||
IF GVL_MODBUS.stModbusEMSComm.stModbusReg11.eChargeStatus = E_CHARGE_STATUS.CHARGING AND (_xFullByVoltage OR _xFullByCV) THEN
|
||||
_xGetPowerMeterData := TRUE;
|
||||
IF (_eBMSControlMode = E_BMS_CONTROL_MODE.CYCLING) THEN
|
||||
GVL_SCADA.eCycleStatus := E_CYCLE_STATUS.DISCHARGE_STARTED;
|
||||
@@ -1209,6 +1223,7 @@ _fbTowerLight(
|
||||
GVL_SCADA.stAutomaticModeHMI.diSetpointAutomatic := REAL_TO_DINT(_rAutoPowerRequest);
|
||||
ELSE
|
||||
_tonBeginShutdown(In := FALSE);
|
||||
_fbTONCVLow(In := FALSE);
|
||||
|
||||
// Send message
|
||||
_fbBatteryFullMessage.Send(0);
|
||||
|
||||
@@ -8,6 +8,7 @@ VAR_INPUT
|
||||
rKp : REAL;
|
||||
rTn : REAL;
|
||||
|
||||
xEnable : BOOL;
|
||||
xSaturated : BOOL := FALSE;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
@@ -19,6 +20,9 @@ VAR
|
||||
_rIntegral : REAL := 0.0;
|
||||
_rProportinal : REAL := 0.0;
|
||||
|
||||
_rErrorSign : REAL;
|
||||
_xHoldIntegrator : BOOL;
|
||||
|
||||
_fbGetCurTaskIdx : GETCURTASKINDEX;
|
||||
_rT : REAL;
|
||||
END_VAR
|
||||
@@ -31,10 +35,18 @@ _rError := rSP - rPV;
|
||||
_rProportinal := rKp * _rError;
|
||||
|
||||
// Calculate controller output
|
||||
rMV := _rProportinal + _rIntegral;
|
||||
IF xEnable THEN
|
||||
rMV := _rProportinal + _rIntegral;
|
||||
ELSE
|
||||
rMV := 0.0;
|
||||
END_IF
|
||||
|
||||
_rErrorSign := _rError * rMV;
|
||||
|
||||
_xHoldIntegrator := xSaturated AND (_rErrorSign > 0);
|
||||
|
||||
// Stop integrator if saturated
|
||||
IF (NOT xSaturated) AND (rTn <> 0) THEN
|
||||
IF (NOT _xHoldIntegrator) AND (rTn <> 0) THEN
|
||||
_rIntegral := _rIntegral + (rKp * _rT / rTn) * _rError;
|
||||
END_IF
|
||||
|
||||
@@ -56,7 +68,7 @@ END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Get current task time
|
||||
_fbGetCurTaskIdx();
|
||||
_rT := UDINT_TO_LREAL(TwinCAT_SystemInfoVarList._TASKInfo[_fbGetCurTaskIdx.index].CycleTime) * 10E-5;]]></ST>
|
||||
_rT := LREAL_TO_REAL(UDINT_TO_LREAL(TwinCAT_SystemInfoVarList._TASKInfo[_fbGetCurTaskIdx.index].CycleTime) * 10E-5);]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Action Name="Reset" Id="{4227580c-e163-4250-9575-dd60ff3083af}">
|
||||
|
||||
43
PLC/POUs/Utility/Controller/FB_PT1Filter.TcPOU
Normal file
43
PLC/POUs/Utility/Controller/FB_PT1Filter.TcPOU
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.12">
|
||||
<POU Name="FB_PT1Filter" Id="{bdcdd199-96b1-43e5-8e4f-5515b0a2225d}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_PT1Filter
|
||||
VAR_INPUT
|
||||
rInput : REAL;
|
||||
timT : TIME := T#100MS;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
rOutput : REAL;
|
||||
END_VAR
|
||||
VAR
|
||||
_rOutputLast : REAL := 0.0;
|
||||
|
||||
_fbGetCurTaskIdx : GETCURTASKINDEX;
|
||||
_rT : REAL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Calculate output
|
||||
rOutput := _rOutputLast + (rInput - _rOutputLast) * (_rT / (TIME_TO_LREAL(timT) + _rT));
|
||||
|
||||
// Save last output
|
||||
_rOutputLast := rOutput;]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="FB_init" Id="{8cf1c8f8-42a3-4c2a-b0ef-f9c06ee7877f}">
|
||||
<Declaration><![CDATA[//FB_Init ist immer implizit verfügbar und wird primär für die Initialisierung verwendet.
|
||||
//Der Rückgabewert wird nicht ausgewertet. Für gezielte Einflussnahme können Sie
|
||||
//die Methoden explizit deklarieren und darin mit dem Standard-Initialisierungscode
|
||||
//zusätzlichen Code bereitstellen. Sie können den Rückgabewert auswerten.
|
||||
METHOD FB_Init: BOOL
|
||||
VAR_INPUT
|
||||
bInitRetains: BOOL; // TRUE: Die Retain-Variablen werden initialisiert (Reset warm / Reset kalt)
|
||||
bInCopyCode: BOOL; // TRUE: Die Instanz wird danach in den Kopiercode kopiert (Online-Change)
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Get current task time
|
||||
_fbGetCurTaskIdx();
|
||||
_rT := LREAL_TO_REAL(UDINT_TO_LREAL(TwinCAT_SystemInfoVarList._TASKInfo[_fbGetCurTaskIdx.index].CycleTime) * 10E-5);]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
Reference in New Issue
Block a user