Projektdateien hinzufügen.

This commit is contained in:
Matthias Heisig
2024-01-04 15:15:26 +01:00
parent 4c6f8dc5bd
commit faa33db290
94 changed files with 15104 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="E_BATTERY_STATUS" Id="{99b02815-2b47-4159-a889-c86170baa34d}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_BATTERY_STATUS :
(
ERROR := 1,
OFF := 2,
READY := 3,
ACTIVE := 4,
MAINTENANCE := 5,
TESTING := 6
);
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="E_CHARGE_STATUS" Id="{7a281462-bf73-4949-96d8-aca55bee6c60}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_CHARGE_STATUS :
(
UNDEFINED := 1,
EMPTY := 2,
CHARGING := 3,
DISCHARGING := 4,
FULL := 5
);
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="E_REACTIVE_POWER_TYPE" Id="{e2c788a7-c536-4b02-910e-6cbe600afdab}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_REACTIVE_POWER_TYPE :
(
INDUCTIVE := 1,
CAPACITIVE := 2,
NONE := 3
);
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="ST_EMS_MODBUS_INTERFACE" Id="{c26c9ee9-feee-46cf-86e6-45d1a1e6819c}">
<Declaration><![CDATA[TYPE ST_EMS_MODBUS_INTERFACE :
STRUCT
// Size = 16 * 2 byte = 32 byte
// Addr: 10.000
sManufacturer : STRING(32); // 1 char = 1 byte
// Addr: 10.016
sModelname : STRING(32);
// Addr: 10.032
sSerialnumber : STRING(32);
// Addr: 10.048
sBMSVersion : STRING(64);
// Addr: 10.080
uiTotalParallelMembers : UINT; //uint 16bit = 1 Word
// Addr: 10.081
uiActiveParallelMembers : UINT;
// Addr: 11.000
eBatteryStatus : E_BATTERY_STATUS;
// Addr: 11.001
eChargeStatus : E_CHARGE_STATUS;
// Addr: 11.002
// Unit: Ah
udiChargeCapacity : UDINT; // 32bit
// Addr: 11.004
// Unit: Wh
udiEnergyCapacity : UDINT;
// Addr: 11.006
// Unit: W
udiMaxChargingActivePower : UDINT;
// Addr: 11.008
// Unit: W
udiMaxDischargingActivePower : UDINT;
// Addr: 11.010
// Unit: var
udiMaxAvailableInductiveReactivePower : UDINT;
// Addr: 11.012
// Unit: var
udiMaxAvailableCapacitiveReactivePower : UDINT;
// Addr: 11.014
// Unit: %
uiSelfDischargeRate : UINT; // 16 bit
// Addr: 11.015
// Unit: %
uiMaxAllowedSOC : UINT;
// Addr: 11.016
// Unit: %
uiMinAllowedSOC : UINT;
// Addr: 11.017
// Unit: %
uiCurrentSOC : UINT;
// Addr: 11.018
// Unit: %
uiCurrentDOD : UINT;
// Addr: 11.019
// Unit: Wh
udiChargedEnergy : UDINT;
// Addr: 11.021
// Unit: Wh
udiAvailableEnergy : UDINT;
// Addr: 11.023
// Unit: %
uiCurrentSOH : UINT;
// Addr: 11.024
// Unit: A
diTotalACCurrentPhase1 : DINT;
// Addr: 11.025
// Unit: A
diTotalACCurrentPhase2 : DINT;
// Addr: 11.026
// Unit: A
diTotalACCurrentPhase3 : DINT;
// Addr: 11.027
// Unit: W
diSetpointActivePowerMirror : DINT;
// Addr: 11.028
rSetpointCosPhiMirror : REAL; // 32 bit
// Addr: 11.030
// Unit: W
diCurrentActivePower : DINT;
// Addr: 11.031
// Unit: var
diCurrentReactivePower : DINT;
// Addr: 11.032
udiLifeMessage : UDINT;
// Addr: 11.033
lwWarningBitmap : LWORD;
// Addr: 11.035
lwErrorBitmap : LWORD;
// Addr: 12.000
// Unit: W
diSetpointActivePower : DINT;
// Addr: 12.001
rSetpointCosPhi : REAL;
// Addr: 12.003
eReactivePowerType : E_REACTIVE_POWER_TYPE;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="ST_MODULE_HMI_INTERFACE" Id="{11e89a54-55b7-4731-b5d2-c1f68fd12879}">
<Declaration><![CDATA[TYPE ST_MODULE_HMI_INTERFACE :
STRUCT
stHMIInterfaceUnit1 : ST_UNIT_HMI_INTERFACE;
stHMIInterfaceUnit2 : ST_UNIT_HMI_INTERFACE;
stHMIInterfaceUnit3 : ST_UNIT_HMI_INTERFACE;
stHMIInterfaceUnit4 : ST_UNIT_HMI_INTERFACE;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="ST_STRING_HMI_INTERFACE" Id="{b74e184a-a1d0-4499-8ac0-7e2226af9a4f}">
<Declaration><![CDATA[TYPE ST_STRING_HMI_INTERFACE :
STRUCT
stHMIInterfaceModule1 : ST_MODULE_HMI_INTERFACE;
stHMIInterfaceModule2 : ST_MODULE_HMI_INTERFACE;
stHMIInterfaceModule3 : ST_MODULE_HMI_INTERFACE;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="ST_UNIT_CONFIG" Id="{75a00288-1f08-4f47-846c-fa7c44b2279c}">
<Declaration><![CDATA[TYPE ST_UNIT_CONFIG :
STRUCT
// Pump posolyt
// ===================================
stConfigPosolytPump : ST_MOTOR_ANALOG_CONFIG;
// Pump negolyt
// ===================================
stConfigNegolytPump : ST_MOTOR_ANALOG_CONFIG;
// Valves posolyt
// ===================================
stConfigPosolytValve : ST_ValveConfig;
// Valves negolyt
// ===================================
stConfigNegolytValve : ST_ValveConfig;
// Pressure sensor posolyt segment inlet
//====================================
stConfigPosolytPressureSegmentInlet : ST_ANALOG_IO_CONFIG;
stEWLPosolytPressureSegmentInlet : ST_ANALOG_EW_LEVELS;
stEWDPosolytPressureSegmentInlet : ST_ANALOG_EW_DELAYS;
// Pressure sensor negolyt segment inlet
//====================================
stConfigNegolytPressureSegmentInlet : ST_ANALOG_IO_CONFIG;
stEWLNegolytPressureSegmentInlet : ST_ANALOG_EW_LEVELS;
stEWDNegolytPressureSegmentInlet : ST_ANALOG_EW_DELAYS;
// Pressure sensor posolyt tank inlet
//====================================
stConfigPosolytPressureTankInlet : ST_ANALOG_IO_CONFIG;
stEWLPosolytPressureTankInlet : ST_ANALOG_EW_LEVELS;
stEWDPosolytPressureTankInlet : ST_ANALOG_EW_DELAYS;
// Pressure sensor posolyt tank inlet
//====================================
stConfigNegolytPressureTankInlet : ST_ANALOG_IO_CONFIG;
stEWLNegolytPressureTankInlet : ST_ANALOG_EW_LEVELS;
stEWDNegolytPressureTankInlet : ST_ANALOG_EW_DELAYS;
// Temperature sensor posolyt tank inlet
//====================================
stConfigPosolytTempTankInlet : ST_ANALOG_IO_CONFIG;
stEWLPosolytTempTankInlet : ST_ANALOG_EW_LEVELS;
stEWDPosolytTempTankInlet : ST_ANALOG_EW_DELAYS;
// Temperature sensor negolyt tank inlet
//====================================
stConfigNegolytTempTankInlet : ST_ANALOG_IO_CONFIG;
stEWLNegolytTempTankInlet : ST_ANALOG_EW_LEVELS;
stEWDNegolytTempTankInlet : ST_ANALOG_EW_DELAYS;
// Voltage segment
//====================================
stConfigVoltageSegment : ST_ANALOG_IO_CONFIG;
stEWLVoltageSegment : ST_ANALOG_EW_LEVELS;
stEWDVoltageSegment : ST_ANALOG_EW_DELAYS;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="ST_UNIT_HMI_INTERFACE" Id="{a46d51f7-c17c-44e4-be59-edb877b3b5dc}">
<Declaration><![CDATA[TYPE ST_UNIT_HMI_INTERFACE :
STRUCT
// Pump posolyt
// ===================================
stPosolytPump : ST_HMI_ANALOG_MOTOR_DATA;
// Pump negolyt
// ===================================
stNegolytPump : ST_HMI_ANALOG_MOTOR_DATA;
// Valve posolyt
// ===================================
stPosolytValve : ST_HMI_VALVE_DATA;
// Valve negolyt
// ===================================
stNegolytValve : ST_HMI_VALVE_DATA;
// Drucksensoren Posolyt
//====================================
stPosolytPressureSegmentInlet : ST_HMI_ANALOG_VALUE;
// Drucksensoren Negolyt
//====================================
stNegolytPressureSegmentInlet : ST_HMI_ANALOG_VALUE;
// Temperature sensor posolyt tank inlet
//====================================
stPosolytTempTankInlet : ST_HMI_ANALOG_VALUE;
// Temperature sensor negolyt tank inlet
//====================================
stNegolytTempTankInlet : ST_HMI_ANALOG_VALUE;
// Voltage sensors
// ===================================
stVoltageSegment : ST_HMI_ANALOG_VALUE;
// Aknowledge all alarms button
// ===================================
stButtonAckAlarms : ST_HMI_CONTROL_BUTTON;
END_STRUCT
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

158
PLC/GVLs/GVL_CONFIG.TcGVL Normal file
View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<GVL Name="GVL_CONFIG" Id="{0773bf51-0237-454d-a970-cfd896054edb}">
<Declaration><![CDATA[{attribute 'qualified_only'}
VAR_GLOBAL
// ===========================
// Unit hardware config
// ===========================
stUnitConfig : ST_UNIT_CONFIG :=
(
// Pump poslyt segment inlet
stConfigPosolytPump :=
(
rTargetMin := 0.0,
rTargetMax := 100.0,
timRampUpTime := T#5S,
timRampDownTime := T#5S,
stAnalogInputConfig := (iAIMax := 32767, iAIMin := 0, rPVMax := 100, rPVMin := 0, sUnit := '%'),
stAnalogOutputConfig := (iAIMax := 32767, iAIMin := 0, rPVMax := 100, rPVMin := 0),
xHasAnalogFeedback := TRUE,
xHasMCBFeedback := TRUE,
xHasRepairSwitchFeedback := FALSE
),
// Pump negolyt segment inlet
stConfigNegolytPump :=
(
rTargetMin := 0.0,
rTargetMax := 100.0,
timRampUpTime := T#5S,
timRampDownTime := T#5S,
stAnalogInputConfig := (iAIMax := 32767, iAIMin := 0, rPVMax := 100, rPVMin := 0, sUnit := '%'),
stAnalogOutputConfig := (iAIMax := 32767, iAIMin := 0, rPVMax := 100, rPVMin := 0),
xHasAnalogFeedback := TRUE,
xHasMCBFeedback := TRUE,
xHasRepairSwitchFeedback := FALSE
),
// Valve posolyt tank outlet
stConfigPosolytValve := (timTimeoutOpen := T#10S, timTimeoutClose := T#10S, xHasOpenFeedback := TRUE, xHasClosedFeedback := TRUE),
// Valve negolyt tank outlet
stConfigNegolytValve := (timTimeoutOpen := T#10S, timTimeoutClose := T#10S, xHasOpenFeedback := TRUE, xHasClosedFeedback := TRUE),
// Pressure posolyt segment inlet
stConfigPosolytPressureSegmentInlet := (iAIMax := 32767, iAIMin := 0, rPVMax := 1500, rPVMin := -1000, sUnit := 'mbar'),
stEWLPosolytPressureSegmentInlet := (rErrorMin := -500, rWarningMin := -400, rWarningMax := 600, rErrorMax := 700),
stEWDPosolytPressureSegmentInlet :=
(
timHardwareSignalLevelOn := T#0S,
timHardwareSignalLevelOff := T#5S,
timErrorLowOn := T#1S,
timErrorLowOff := T#5S,
timWarningLowOn := T#1S,
timWarningLowOff := T#5S,
timWarningHighOn := T#1S,
timWarningHighOff := T#5S,
timErrorHighOn := T#1S,
timErrorHighOff := T#5S
),
// Pressure negolyt segment inlet
stConfigNegolytPressureSegmentInlet := (iAIMax := 32767, iAIMin := 0, rPVMax := 1500, rPVMin := -1000, sUnit := 'mbar'),
stEWLNegolytPressureSegmentInlet := (rErrorMin := -500, rWarningMin := -400, rWarningMax := 600, rErrorMax := 700),
stEWDNegolytPressureSegmentInlet :=
(
timHardwareSignalLevelOn := T#0S,
timHardwareSignalLevelOff := T#5S,
timErrorLowOn := T#1S,
timErrorLowOff := T#5S,
timWarningLowOn := T#1S,
timWarningLowOff := T#5S,
timWarningHighOn := T#1S,
timWarningHighOff := T#5S,
timErrorHighOn := T#1S,
timErrorHighOff := T#5S
),
// Temperature sensor posolyt tank inlet
stConfigPosolytTempTankInlet := (iAIMax := 32767, iAIMin := -32768, rPVMax := 3276.7, rPVMin := -3276.8, sUnit := '°C'),
stEWLPosolytTempTankInlet := (rErrorMin := -10, rWarningMin := -5, rWarningMax := 45, rErrorMax := 60),
stEWDPosolytTempTankInlet :=
(
timHardwareSignalLevelOn := T#0S,
timHardwareSignalLevelOff := T#5S,
timErrorLowOn := T#5S,
timErrorLowOff := T#5S,
timWarningLowOn := T#5S,
timWarningLowOff := T#5S,
timWarningHighOn := T#5S,
timWarningHighOff := T#5S,
timErrorHighOn := T#5S,
timErrorHighOff := T#5S
),
// Temperature sensor negolyt tank inlet
stConfigNegolytTempTankInlet := (iAIMax := 32767, iAIMin := -32768, rPVMax := 3276.7, rPVMin := -3276.8, sUnit := '°C'),
stEWLNegolytTempTankInlet := (rErrorMin := -10, rWarningMin := -5, rWarningMax := 45, rErrorMax := 60),
stEWDNegolytTempTankInlet :=
(
timHardwareSignalLevelOn := T#0S,
timHardwareSignalLevelOff := T#5S,
timErrorLowOn := T#5S,
timErrorLowOff := T#5S,
timWarningLowOn := T#5S,
timWarningLowOff := T#5S,
timWarningHighOn := T#5S,
timWarningHighOff := T#5S,
timErrorHighOn := T#5S,
timErrorHighOff := T#5S
),
// Voltage sensor segment
// EL3214-0090 CoE Verzeichnis
// Index 0x80n0:02 "Presentation" = Signed(0) -> Resolution 1/10°C
// Index 0x80n0:19 "RTD Element" = PT100(0)
stConfigVoltageSegment := (iAIMax := 32767, iAIMin := 0, rPVMax := 150, rPVMin := 0, sUnit := 'V'),
stEWLVoltageSegment := (rErrorMin := 50, rWarningMin := 55, rWarningMax := 75, rErrorMax := 80),
stEWDVoltageSegment :=
(
timHardwareSignalLevelOn := T#0S,
timHardwareSignalLevelOff := T#5S,
timErrorLowOn := T#2S,
timErrorLowOff := T#5S,
timWarningLowOn := T#2S,
timWarningLowOff := T#5S,
timWarningHighOn := T#2S,
timWarningHighOff := T#5S,
timErrorHighOn := T#2S,
timErrorHighOff := T#5S
)
);
// ===========================
// General settings
// ===========================
// Pump on power
rPumpPosolytOnPower : REAL := 70.0;
rPumpNegolytOnPower : REAL := 70.0;
// Unit voltage pumps shutoff threshold
rPumpshutoffThreshold : REAL := 25.0;
// Minimum unit voltage for startup
rMinimumUnitVoltage : REAL := 49.0;
// Maximum absolute voltage difference
// between units in the same module
rMaxAbsDiffVoltageUnitsOnModule : REAL := 5.0;
// Maximum absolute voltage difference
// between Modules
rMaxAbsDiffVoltageModulesInString : REAL := 10.0;
END_VAR]]></Declaration>
</GVL>
</TcPlcObject>

21
PLC/GVLs/GVL_MODBUS.TcGVL Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<GVL Name="GVL_MODBUS" Id="{913a9222-1338-4c08-b758-91c1bd26dcd9}">
<Declaration><![CDATA[{attribute 'qualified_only'}
VAR_GLOBAL
// Modbus interface to customer EMS
stModbusEMSComm : ST_EMS_MODBUS_INTERFACE := (
sManufacturer := 'cmblu energy ag',
sModelname := 'all liquid',
sSerialnumber := '202312151643',
sBMSVersion := '0.8.0',
uiTotalParallelMembers := 2);
// Modbus default config
mb_Input_Coils : ARRAY [0..255] OF BOOL;
mb_Output_Coils : ARRAY [0..255] OF BOOL;
mb_Input_Registers : ARRAY [0..255] OF WORD;
mb_Output_Registers : ARRAY [0..255] OF WORD;
END_VAR]]></Declaration>
</GVL>
</TcPlcObject>

9
PLC/GVLs/GVL_SCADA.TcGVL Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<GVL Name="GVL_SCADA" Id="{8186ff04-764f-4b24-8a6b-d0a44d528e6f}">
<Declaration><![CDATA[{attribute 'qualified_only'}
VAR_GLOBAL
stHMIInterfaces : ARRAY [0..3] OF ST_UNIT_HMI_INTERFACE;
END_VAR]]></Declaration>
</GVL>
</TcPlcObject>

150
PLC/PLC.plcproj Normal file
View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FileVersion>1.0.0.0</FileVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{9ae64910-5eb2-4866-93fd-efe059c38c36}</ProjectGuid>
<SubObjectsSortedByName>True</SubObjectsSortedByName>
<DownloadApplicationInfo>true</DownloadApplicationInfo>
<WriteProductVersion>true</WriteProductVersion>
<GenerateTpy>false</GenerateTpy>
<Name>PLC</Name>
<ProgramVersion>3.1.4024.0</ProgramVersion>
<Application>{afd0b275-de2f-4006-ab0f-6826ccfce7be}</Application>
<TypeSystem>{18a2eab9-0077-4cea-9d3b-9a168bdf0814}</TypeSystem>
<Implicit_Task_Info>{6e35f35d-280b-4da2-9c5b-fc35ab6da425}</Implicit_Task_Info>
<Implicit_KindOfTask>{580e4ecb-3f35-4f4d-bc2a-d29ea11be950}</Implicit_KindOfTask>
<Implicit_Jitter_Distribution>{8bf9a0d5-d7ca-4ab3-b8e1-6723c8a1acbc}</Implicit_Jitter_Distribution>
<LibraryReferences>{106b5199-0018-4919-a06c-2ea0dd3e1070}</LibraryReferences>
</PropertyGroup>
<ItemGroup>
<Compile Include="DUTs\E_BATTERY_STATUS.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="DUTs\E_CHARGE_STATUS.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="DUTs\E_REACTIVE_POWER_TYPE.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="DUTs\ST_EMS_MODBUS_INTERFACE.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="DUTs\ST_MODULE_HMI_INTERFACE.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="DUTs\ST_STRING_HMI_INTERFACE.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="DUTs\ST_UNIT_HMI_INTERFACE.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="DUTs\ST_UNIT_CONFIG.TcDUT">
<SubType>Code</SubType>
</Compile>
<Compile Include="GVLs\GVL_CONFIG.TcGVL">
<SubType>Code</SubType>
<LinkAlways>true</LinkAlways>
</Compile>
<Compile Include="GVLs\GVL_MODBUS.TcGVL">
<SubType>Code</SubType>
<LinkAlways>true</LinkAlways>
</Compile>
<Compile Include="GVLs\GVL_SCADA.TcGVL">
<SubType>Code</SubType>
<LinkAlways>true</LinkAlways>
</Compile>
<Compile Include="PlcTask.TcTTO">
<SubType>Code</SubType>
</Compile>
<Compile Include="POUs\FB_Module.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="POUs\FB_String.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="POUs\FB_Unit.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="POUs\MAIN.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="POUs\Sunspec\FB_PowerSupplySunspec.TcPOU">
<SubType>Code</SubType>
</Compile>
<Compile Include="POUs\Sunspec\U_SUNSPEC_ERROR.TcDUT">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="DUTs" />
<Folder Include="GVLs" />
<Folder Include="POUs\Sunspec" />
<Folder Include="VISUs" />
<Folder Include="POUs" />
</ItemGroup>
<ItemGroup>
<PlaceholderReference Include="BaseLib">
<DefaultResolution>BaseLib, * (cmblu)</DefaultResolution>
<Namespace>BaseLib</Namespace>
</PlaceholderReference>
<PlaceholderReference Include="Tc2_ModbusSrv">
<DefaultResolution>Tc2_ModbusSrv, * (Beckhoff Automation GmbH)</DefaultResolution>
<Namespace>Tc2_ModbusSrv</Namespace>
</PlaceholderReference>
<PlaceholderReference Include="Tc2_Standard">
<DefaultResolution>Tc2_Standard, * (Beckhoff Automation GmbH)</DefaultResolution>
<Namespace>Tc2_Standard</Namespace>
</PlaceholderReference>
<PlaceholderReference Include="Tc2_System">
<DefaultResolution>Tc2_System, * (Beckhoff Automation GmbH)</DefaultResolution>
<Namespace>Tc2_System</Namespace>
</PlaceholderReference>
<PlaceholderReference Include="Tc3_EventLogger">
<DefaultResolution>Tc3_EventLogger, * (Beckhoff Automation GmbH)</DefaultResolution>
</PlaceholderReference>
<PlaceholderReference Include="Tc3_Module">
<DefaultResolution>Tc3_Module, * (Beckhoff Automation GmbH)</DefaultResolution>
<Namespace>Tc3_Module</Namespace>
</PlaceholderReference>
</ItemGroup>
<ItemGroup>
<None Include="PLC.tmc">
<SubType>Content</SubType>
</None>
</ItemGroup>
<ProjectExtensions>
<PlcProjectOptions>
<XmlArchive>
<Data>
<o xml:space="preserve" t="OptionKey">
<v n="Name">"&lt;ProjectRoot&gt;"</v>
<d n="SubKeys" t="Hashtable" ckt="String" cvt="OptionKey">
<v>{40450F57-0AA3-4216-96F3-5444ECB29763}</v>
<o>
<v n="Name">"{40450F57-0AA3-4216-96F3-5444ECB29763}"</v>
<d n="SubKeys" t="Hashtable" />
<d n="Values" t="Hashtable" ckt="String" cvt="String">
<v>ActiveVisuProfile</v>
<v>IR0whWr8bwfwBwAAiD2qpQAAAABVAgAA37x72QAAAAABAAAAAAAAAAEaUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwACTHsAZgA5ADUAYgBiADQAMgA2AC0ANQA1ADIANAAtADQAYgA0ADUALQA5ADQAMAAwAC0AZgBiADAAZgAyAGUANwA3AGUANQAxAGIAfQADCE4AYQBtAGUABDBUAHcAaQBuAEMAQQBUACAAMwAuADEAIABCAHUAaQBsAGQAIAA0ADAAMgA0AC4ANwAFFlAAcgBvAGYAaQBsAGUARABhAHQAYQAGTHsAMQA2AGUANQA1AGIANgAwAC0ANwAwADQAMwAtADQAYQA2ADMALQBiADYANQBiAC0ANgAxADQANwAxADMAOAA3ADgAZAA0ADIAfQAHEkwAaQBiAHIAYQByAGkAZQBzAAhMewAzAGIAZgBkADUANAA1ADkALQBiADAANwBmAC0ANABkADYAZQAtAGEAZQAxAGEALQBhADgAMwAzADUANgBhADUANQAxADQAMgB9AAlMewA5AGMAOQA1ADgAOQA2ADgALQAyAGMAOAA1AC0ANAAxAGIAYgAtADgAOAA3ADEALQA4ADkANQBmAGYAMQBmAGUAZABlADEAYQB9AAoOVgBlAHIAcwBpAG8AbgALBmkAbgB0AAwKVQBzAGEAZwBlAA0KVABpAHQAbABlAA4aVgBpAHMAdQBFAGwAZQBtAE0AZQB0AGUAcgAPDkMAbwBtAHAAYQBuAHkAEAxTAHkAcwB0AGUAbQARElYAaQBzAHUARQBsAGUAbQBzABIwVgBpAHMAdQBFAGwAZQBtAHMAUwBwAGUAYwBpAGEAbABDAG8AbgB0AHIAbwBsAHMAEyhWAGkAcwB1AEUAbABlAG0AcwBXAGkAbgBDAG8AbgB0AHIAbwBsAHMAFCRWAGkAcwB1AEUAbABlAG0AVABlAHgAdABFAGQAaQB0AG8AcgAVIlYAaQBzAHUATgBhAHQAaQB2AGUAQwBvAG4AdAByAG8AbAAWFHYAaQBzAHUAaQBuAHAAdQB0AHMAFwxzAHkAcwB0AGUAbQAYGFYAaQBzAHUARQBsAGUAbQBCAGEAcwBlABkmRABlAHYAUABsAGEAYwBlAGgAbwBsAGQAZQByAHMAVQBzAGUAZAAaCGIAbwBvAGwAGyJQAGwAdQBnAGkAbgBDAG8AbgBzAHQAcgBhAGkAbgB0AHMAHEx7ADQAMwBkADUAMgBiAGMAZQAtADkANAAyAGMALQA0ADQAZAA3AC0AOQBlADkANAAtADEAYgBmAGQAZgAzADEAMABlADYAMwBjAH0AHRxBAHQATABlAGEAcwB0AFYAZQByAHMAaQBvAG4AHhRQAGwAdQBnAGkAbgBHAHUAaQBkAB8WUwB5AHMAdABlAG0ALgBHAHUAaQBkACBIYQBmAGMAZAA1ADQANAA2AC0ANAA5ADEANAAtADQAZgBlADcALQBiAGIANwA4AC0AOQBiAGYAZgBlAGIANwAwAGYAZAAxADcAIRRVAHAAZABhAHQAZQBJAG4AZgBvACJMewBiADAAMwAzADYANgBhADgALQBiADUAYwAwAC0ANABiADkAYQAtAGEAMAAwAGUALQBlAGIAOAA2ADAAMQAxADEAMAA0AGMAMwB9ACMOVQBwAGQAYQB0AGUAcwAkTHsAMQA4ADYAOABmAGYAYwA5AC0AZQA0AGYAYwAtADQANQAzADIALQBhAGMAMAA2AC0AMQBlADMAOQBiAGIANQA1ADcAYgA2ADkAfQAlTHsAYQA1AGIAZAA0ADgAYwAzAC0AMABkADEANwAtADQAMQBiADUALQBiADEANgA0AC0ANQBmAGMANgBhAGQAMgBiADkANgBiADcAfQAmFk8AYgBqAGUAYwB0AHMAVAB5AHAAZQAnVFUAcABkAGEAdABlAEwAYQBuAGcAdQBhAGcAZQBNAG8AZABlAGwARgBvAHIAQwBvAG4AdgBlAHIAdABpAGIAbABlAEwAaQBiAHIAYQByAGkAZQBzACgQTABpAGIAVABpAHQAbABlACkUTABpAGIAQwBvAG0AcABhAG4AeQAqHlUAcABkAGEAdABlAFAAcgBvAHYAaQBkAGUAcgBzACs4UwB5AHMAdABlAG0ALgBDAG8AbABsAGUAYwB0AGkAbwBuAHMALgBIAGEAcwBoAHQAYQBiAGwAZQAsEnYAaQBzAHUAZQBsAGUAbQBzAC1INgBjAGIAMQBjAGQAZQAxAC0AZAA1AGQAYwAtADQAYQAzAGIALQA5ADAANQA0AC0AMgAxAGYAYQA3ADUANgBhADMAZgBhADQALihJAG4AdABlAHIAZgBhAGMAZQBWAGUAcgBzAGkAbwBuAEkAbgBmAG8AL0x7AGMANgAxADEAZQA0ADAAMAAtADcAZgBiADkALQA0AGMAMwA1AC0AYgA5AGEAYwAtADQAZQAzADEANABiADUAOQA5ADYANAAzAH0AMBhNAGEAagBvAHIAVgBlAHIAcwBpAG8AbgAxGE0AaQBuAG8AcgBWAGUAcgBzAGkAbwBuADIMTABlAGcAYQBjAHkAMzBMAGEAbgBnAHUAYQBnAGUATQBvAGQAZQBsAFYAZQByAHMAaQBvAG4ASQBuAGYAbwA0MEwAbwBhAGQATABpAGIAcgBhAHIAaQBlAHMASQBuAHQAbwBQAHIAbwBqAGUAYwB0ADUaQwBvAG0AcABhAHQAaQBiAGkAbABpAHQAeQDQAAIaA9ADAS0E0AUGGgfQBwgaAUUHCQjQAAkaBEUKCwQDAAAABQAAAA0AAAAAAAAA0AwLrQIAAADQDQEtDtAPAS0Q0AAJGgRFCgsEAwAAAAUAAAANAAAAKAAAANAMC60BAAAA0A0BLRHQDwEtENAACRoERQoLBAMAAAAFAAAADQAAAAAAAADQDAutAgAAANANAS0S0A8BLRDQAAkaBEUKCwQDAAAABQAAAA0AAAAUAAAA0AwLrQIAAADQDQEtE9APAS0Q0AAJGgRFCgsEAwAAAAUAAAANAAAAAAAAANAMC60CAAAA0A0BLRTQDwEtENAACRoERQoLBAMAAAAFAAAADQAAAAAAAADQDAutAgAAANANAS0V0A8BLRDQAAkaBEUKCwQDAAAABQAAAA0AAAAAAAAA0AwLrQIAAADQDQEtFtAPAS0X0AAJGgRFCgsEAwAAAAUAAAANAAAAKAAAANAMC60EAAAA0A0BLRjQDwEtENAZGq0BRRscAdAAHBoCRR0LBAMAAAAFAAAADQAAAAAAAADQHh8tINAhIhoCRSMkAtAAJRoFRQoLBAMAAAADAAAAAAAAAAoAAADQJgutAAAAANADAS0n0CgBLRHQKQEtENAAJRoFRQoLBAMAAAADAAAAAAAAAAoAAADQJgutAQAAANADAS0n0CgBLRHQKQEtEJoqKwFFAAEC0AABLSzQAAEtF9AAHy0t0C4vGgPQMAutAQAAANAxC60XAAAA0DIarQDQMy8aA9AwC60CAAAA0DELrQMAAADQMhqtANA0Gq0A0DUarQA=</v>
</d>
</o>
<v>{192FAD59-8248-4824-A8DE-9177C94C195A}</v>
<o>
<v n="Name">"{192FAD59-8248-4824-A8DE-9177C94C195A}"</v>
<d n="SubKeys" t="Hashtable" />
<d n="Values" t="Hashtable" />
</o>
</d>
<d n="Values" t="Hashtable" />
</o>
</Data>
<TypeList>
<Type n="Hashtable">System.Collections.Hashtable</Type>
<Type n="OptionKey">{54dd0eac-a6d8-46f2-8c27-2f43c7e49861}</Type>
<Type n="String">System.String</Type>
</TypeList>
</XmlArchive>
</PlcProjectOptions>
</ProjectExtensions>
</Project>

523
PLC/PLC.tmc Normal file

File diff suppressed because one or more lines are too long

155
PLC/POUs/FB_Module.TcPOU Normal file
View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<POU Name="FB_Module" Id="{87be924f-018d-4c09-997b-f0c0054414cc}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Module
VAR_INPUT
// Emergency stop ok
xEmergencyStopOk : BOOL;
// HMI Interface
stHMIInterface : REFERENCE TO ST_MODULE_HMI_INTERFACE;
// Release alarms
xReleaseErrors : BOOL;
// Release analog io limit errors
xReleaseLimitErrors : BOOL;
// Input to confirm all errors
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
// One unit has an error
xError : BOOL;
// One unit has a warning
xWarning : BOOL;
END_VAR
VAR
_fbUnit1 : FB_Unit(CONCAT(_sName, ' Unit 1'));
_fbUnit2 : FB_Unit(CONCAT(_sName, ' Unit 2'));
_fbUnit3 : FB_Unit(CONCAT(_sName, ' Unit 3'));
_fbUnit4 : FB_Unit(CONCAT(_sName, ' Unit 4'));
// Module name
_sName : STRING;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Reset error and warning flag
xError := FALSE;
xWarning := FALSE;
// ===============================
// Unit 1
// ===============================
_fbUnit1(
stUnitConfig:= GVL_CONFIG.stUnitConfig,
stHMIInterface:= stHMIInterface.stHMIInterfaceUnit1,
xEmergencyStopOk:= xEmergencyStopOk,
rSetpointPosolytPumpInlet:= GVL_CONFIG.rPumpPosolytOnPower,
rSetpointNegolytPumpInlet:= GVL_CONFIG.rPumpNegolytOnPower,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xConfirmAlarms:= xConfirmAlarms,
_xWarningConfirmPending=> );
IF _fbUnit1.xWarning THEN
xWarning := TRUE;
END_IF
IF _fbUnit1.xError THEN
xError := TRUE;
END_IF
// ===============================
// Unit 2
// ===============================
_fbUnit2(
stUnitConfig:= GVL_CONFIG.stUnitConfig,
stHMIInterface:= stHMIInterface.stHMIInterfaceUnit2,
xEmergencyStopOk:= xEmergencyStopOk,
rSetpointPosolytPumpInlet:= GVL_CONFIG.rPumpPosolytOnPower,
rSetpointNegolytPumpInlet:= GVL_CONFIG.rPumpNegolytOnPower,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xConfirmAlarms:= xConfirmAlarms,
_xWarningConfirmPending=> );
IF _fbUnit2.xWarning THEN
xWarning := TRUE;
END_IF
IF _fbUnit2.xError THEN
xError := TRUE;
END_IF
// ===============================
// Unit 3
// ===============================
_fbUnit3(
stUnitConfig:= GVL_CONFIG.stUnitConfig,
stHMIInterface:= stHMIInterface.stHMIInterfaceUnit3,
xEmergencyStopOk:= xEmergencyStopOk,
rSetpointPosolytPumpInlet:= GVL_CONFIG.rPumpPosolytOnPower,
rSetpointNegolytPumpInlet:= GVL_CONFIG.rPumpNegolytOnPower,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xConfirmAlarms:= xConfirmAlarms,
_xWarningConfirmPending=> );
IF _fbUnit3.xWarning THEN
xWarning := TRUE;
END_IF
IF _fbUnit3.xError THEN
xError := TRUE;
END_IF
// ===============================
// Unit 4
// ===============================
_fbUnit4(
stUnitConfig:= GVL_CONFIG.stUnitConfig,
stHMIInterface:= stHMIInterface.stHMIInterfaceUnit4,
xEmergencyStopOk:= xEmergencyStopOk,
rSetpointPosolytPumpInlet:= GVL_CONFIG.rPumpPosolytOnPower,
rSetpointNegolytPumpInlet:= GVL_CONFIG.rPumpNegolytOnPower,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xConfirmAlarms:= xConfirmAlarms,
_xWarningConfirmPending=> );
IF _fbUnit4.xWarning THEN
xWarning := TRUE;
END_IF
IF _fbUnit4.xError THEN
xError := TRUE;
END_IF]]></ST>
</Implementation>
<Method Name="FB_init" Id="{369c1d27-76e4-45f8-9dbe-03524d3389df}">
<Declaration><![CDATA[METHOD FB_init : BOOL
VAR_INPUT
bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
sName : STRING;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_sName := sName;]]></ST>
</Implementation>
</Method>
<LineIds Name="FB_Module">
<LineId Id="248" Count="92" />
<LineId Id="188" Count="0" />
</LineIds>
<LineIds Name="FB_Module.FB_init">
<LineId Id="7" Count="0" />
</LineIds>
</POU>
</TcPlcObject>

124
PLC/POUs/FB_String.TcPOU Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<POU Name="FB_String" Id="{46501225-f446-4674-bfed-3be64273e576}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_String
VAR_INPUT
// Module 1 HMI interface
stHMIInterface : ST_STRING_HMI_INTERFACE;
// Emergency stop ok
xEmergencyStopOk : BOOL;
// Release alarms
xReleaseErrors : BOOL;
// Release analog io limit errors
xReleaseLimitErrors : BOOL;
// Input to confirm all errors
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
xError : BOOL;
xWarning : BOOL;
END_VAR
VAR
_fbModule1 : FB_Module(CONCAT(_sName, 'Module 1'));
_fbModule2 : FB_Module(CONCAT(_sName, 'Module 2'));
_fbModule3 : FB_Module(CONCAT(_sName, 'Module 3'));
// String name
_sName : STRING;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// ===============================
// Module 1
// ===============================
_fbModule1(
xEmergencyStopOk:= xEmergencyStopOk,
stHMIInterface:= stHMIInterface.stHMIInterfaceModule1,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xConfirmAlarms:= xConfirmAlarms);
IF _fbModule1.xWarning THEN
xWarning := TRUE;
END_IF
IF _fbModule1.xError THEN
xError := TRUE;
END_IF
// ===============================
// Module 2
// ===============================
_fbModule2(
xEmergencyStopOk:= xEmergencyStopOk,
stHMIInterface:= stHMIInterface.stHMIInterfaceModule2,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xConfirmAlarms:= xConfirmAlarms);
IF _fbModule2.xWarning THEN
xWarning := TRUE;
END_IF
IF _fbModule2.xError THEN
xError := TRUE;
END_IF
// ===============================
// Module 3
// ===============================
_fbModule3(
xEmergencyStopOk:= xEmergencyStopOk,
stHMIInterface:= stHMIInterface.stHMIInterfaceModule3,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xConfirmAlarms:= xConfirmAlarms);
IF _fbModule3.xWarning THEN
xWarning := TRUE;
END_IF
IF _fbModule3.xError THEN
xError := TRUE;
END_IF]]></ST>
</Implementation>
<Method Name="FB_init" Id="{9e8494eb-1b40-4be9-91c8-810ecbdf7f0c}">
<Declaration><![CDATA[METHOD FB_init : BOOL
VAR_INPUT
bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
sName : STRING;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_sName := sName;]]></ST>
</Implementation>
</Method>
<LineIds Name="FB_String">
<LineId Id="69" Count="0" />
<LineId Id="67" Count="1" />
<LineId Id="47" Count="1" />
<LineId Id="50" Count="3" />
<LineId Id="58" Count="0" />
<LineId Id="62" Count="0" />
<LineId Id="64" Count="0" />
<LineId Id="66" Count="0" />
<LineId Id="63" Count="0" />
<LineId Id="59" Count="2" />
<LineId Id="71" Count="17" />
<LineId Id="70" Count="0" />
<LineId Id="90" Count="17" />
<LineId Id="89" Count="0" />
</LineIds>
<LineIds Name="FB_String.FB_init">
<LineId Id="7" Count="0" />
</LineIds>
</POU>
</TcPlcObject>

535
PLC/POUs/FB_Unit.TcPOU Normal file
View File

@@ -0,0 +1,535 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<POU Name="FB_Unit" Id="{e9bb815b-eb46-4920-800d-910484e58b22}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Unit
VAR_INPUT
// Unit configuration
stUnitConfig : REFERENCE TO ST_UNIT_CONFIG;
// HMI interface
stHMIInterface : REFERENCE TO ST_UNIT_HMI_INTERFACE;
// Start unit
xEnable : BOOL;
// Emergency stop ok
xEmergencyStopOk : BOOL;
// Setpoint posolyt pump inlet
rSetpointPosolytPumpInlet : REAL;
// Setpoint negolyt pump inlet
rSetpointNegolytPumpInlet : REAL;
// Release alarms
xReleaseErrors : BOOL;
// Release analog io limit errors
xReleaseLimitErrors : BOOL;
// Input to confirm all errors
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
// Unit ready
xReady : BOOL;
// Error active
xError : BOOL;
// Warning active
xWarning : BOOL;
// Warning confirmation still pending
_xWarningConfirmPending : BOOL;
END_VAR
VAR
// Check unit condition after some time during startup
_timUnitStartupWaitTime : TIME := T#20S;
// Valves posolyt
_fbPosolytValveTankOutlet : FB_Valve('Posolyt tank outlet');
// Valves negolyt
_fbNegolytValveTankOutlet : FB_Valve('Negolyt tank outlet');
// Pumps posolyt
_fbPosolytPumpInlet : FB_MotorAnalog('Posolyt segment inlet');
// Pumps negolyt
_fbNegolytPumpInlet : FB_MotorAnalog('Negolyt segment inlet');
// Pressure sensors posolyt
_fbPressurePosolytSegmentInlet : FB_AnalogInput('P1_P');
_fbPressurePosolytTankInlet : FB_AnalogInput('P3_P');
_fbPressurePosolytTankOutlet : FB_AnalogInput('P4_P');
// Pressure sensors negolyt
_fbPressureNegolytSegmentInlet : FB_AnalogInput('P1_N');
_fbPressureNegolytTankInlet : FB_AnalogInput('P3_N');
_fbPressureNegolytTankOutlet : FB_AnalogInput('P4_N');
// Unit voltage
_fbVoltageSegment : FB_AnalogInput('Voltage');
// Valve posolyt tank outlet interlocks
_stPosolytValveTankOutletPIntlk : T_INTERLOCK;
_stPosolytValveTankOutletPIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0000;
_stPosolytValveTankOutletSIntlk : T_INTERLOCK;
_stPosolytValveTankOutletSIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0011;
// Valve negolyt tank outlet interlocks
_stNegolytValveTankOutletPIntlk : T_INTERLOCK;
_stNegolytValveTankOutletPIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0000;
_stNegolytValveTankOutletSIntlk : T_INTERLOCK;
_stNegolytValveTankOutletSIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0011;
// Pump posolyt inlet interlocks
_stPosolytPumpInletPIntlk : T_INTERLOCK;
_stPosolytPumpInletPIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0001;
_stPosolytPumpInletSIntlk : T_INTERLOCK;
_stPosolytPumpInletSIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0011;
// Pump negolyt inlet interlocks
_stNegolytPumpInletPIntlk : T_INTERLOCK;
_stNegolytPumpInletPIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0001;
_stNegolytPumpInletSIntlk : T_INTERLOCK;
_stNegolytPumpInletSIntlkUsed : T_INTERLOCK := 2#0000_0000_0000_0011;
// Error active
_xErrorActive : BOOL;
// Warning active
_xWarningActive : BOOL;
// Current state
_iState: INT;
// All components in automatic mode
_xAllComponentsInAutomatic : BOOL;
// Not all components in automatic mode alarm
_fbNotAllAutomaticAlarm : FB_TcAlarm;
// Unit name
_sName : STRING;
// Unit startup check timer
_tonStartupCheck : TON;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Reset error active
_xErrorActive := FALSE;
// Reset warning active
_xWarningActive := FALSE;
// ===============================
// Valve posolyt tank outlet
// ===============================
// Safety Interlocks
stHMIInterface.stPosolytValve.stInterlock.asSafetyINTLKName[0] := 'Emergency stop ok';
_stPosolytValveTankOutletSIntlk.0 := xEmergencyStopOk;
// Valve fb
_fbPosolytValveTankOutlet(
xReleaseManualMode:= TRUE,
wProcessINTLK:= _stPosolytValveTankOutletPIntlk,
wProcessINTLKUsed:= _stPosolytValveTankOutletPIntlkUsed,
wSafetyINTLK:= _stPosolytValveTankOutletSIntlk,
wSafetyINTLKUsed:= _stPosolytValveTankOutletSIntlkUsed,
xConfirmAlarms:= xConfirmAlarms,
xReleaseErrors:= xReleaseErrors,
stValveConfig:= stUnitConfig.stConfigPosolytValve,
stHMIInterface:= stHMIInterface.stPosolytValve);
// Set error active if fb has error
IF _fbPosolytValveTankOutlet.xError THEN
_xErrorActive := TRUE;
END_IF
// ===============================
// Valve negolyt tank outlet
// ===============================
// Safety Interlocks
stHMIInterface.stNegolytValve.stInterlock.asSafetyINTLKName[0] := 'Emergency stop ok';
_stNegolytValveTankOutletSIntlk.0 := xEmergencyStopOk;
// Valve fb
_fbNegolytValveTankOutlet(
xReleaseManualMode:= TRUE,
wProcessINTLK:= _stNegolytValveTankOutletPIntlk,
wProcessINTLKUsed:= _stNegolytValveTankOutletPIntlkUsed,
wSafetyINTLK:= _stNegolytValveTankOutletSIntlk,
wSafetyINTLKUsed:= _stNegolytValveTankOutletSIntlkUsed,
xConfirmAlarms:= xConfirmAlarms,
xReleaseErrors:= xReleaseErrors,
stValveConfig:= stUnitConfig.stConfigNegolytValve,
stHMIInterface:= stHMIInterface.stNegolytValve);
// Set error active if fb has error
IF _fbNegolytValveTankOutlet.xError THEN
_xErrorActive := TRUE;
END_IF
// ===============================
// Pump posolyt segment inlet
// ===============================
// Safety Interlocks
stHMIInterface.stPosolytPump.stInterlock.asSafetyINTLKName[0] := 'Emergency stop ok';
_stPosolytPumpInletSIntlk.0 := xEmergencyStopOk;
// Process interlocks
stHMIInterface.stPosolytPump.stInterlock.asProcessINTLKName[0] := 'At least one valve is open';
_stPosolytPumpInletPIntlk.0 := _fbPosolytValveTankOutlet.IsOpen;
// Valve fb
_fbPosolytPumpInlet(
xReleaseManualMode:= TRUE,
wProcessINTLK:= _stPosolytPumpInletPIntlk,
wProcessINTLKUsed:= _stPosolytPumpInletPIntlkUsed,
wSafetyINTLK:= _stPosolytPumpInletSIntlk,
wSafetyINTLKUsed:= _stPosolytPumpInletSIntlkUsed,
xReleaseErrors:= xReleaseErrors,
xConfirmAlarms:= xConfirmAlarms,
rSPautomatic:= rSetpointPosolytPumpInlet,
xReleaseAnalogInLimitErrors:= xReleaseLimitErrors,
stMotorAnalogConfig:= stUnitConfig.stConfigPosolytPump,
stHMIInterface:= stHMIInterface.stPosolytPump,
xWarning=> );
// Set error active if fb has error
IF _fbPosolytPumpInlet.xError THEN
_xErrorActive := TRUE;
END_IF
// Set warning if fb has warning
IF _fbPosolytPumpInlet.xWarning THEN
_xWarningActive := TRUE;
END_IF
// ===============================
// Pump negolyt segment inlet
// ===============================
// Safety Interlocks
stHMIInterface.stNegolytPump.stInterlock.asSafetyINTLKName[0] := 'Emergency stop ok';
_stNegolytPumpInletSIntlk.0 := xEmergencyStopOk;
// Process interlocks
stHMIInterface.stNegolytPump.stInterlock.asProcessINTLKName[0] := 'At least one valve is open';
_stNegolytPumpInletPIntlk.0 := _fbNegolytValveTankOutlet.IsOpen;
// Valve fb
_fbNegolytPumpInlet(
xReleaseManualMode:= TRUE,
wProcessINTLK:= _stNegolytPumpInletPIntlk,
wProcessINTLKUsed:= _stNegolytPumpInletPIntlkUsed,
wSafetyINTLK:= _stNegolytPumpInletSIntlk,
wSafetyINTLKUsed:= _stNegolytPumpInletSIntlkUsed,
xReleaseErrors:= xReleaseErrors,
xConfirmAlarms:= xConfirmAlarms,
rSPautomatic:= rSetpointNegolytPumpInlet,
xReleaseAnalogInLimitErrors:= xReleaseLimitErrors,
stMotorAnalogConfig:= stUnitConfig.stConfigNegolytPump,
stHMIInterface:= stHMIInterface.stNegolytPump,
xWarning=> );
// Set error active if fb has error
IF _fbNegolytPumpInlet.xError THEN
_xErrorActive := TRUE;
END_IF
// Set warning if fb has warning
IF _fbNegolytPumpInlet.xWarning THEN
_xWarningActive := TRUE;
END_IF
// ===============================
// Pressure sensors posolyt segment inlet
// ===============================
_fbPressurePosolytSegmentInlet(
stScalingConfig:= stUnitConfig.stConfigPosolytPressureSegmentInlet,
stEWConfig:= stUnitConfig.stEWLPosolytPressureSegmentInlet,
stEWDelayConfig:= stUnitConfig.stEWDPosolytPressureSegmentInlet,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xReleaseHardwareErrors:= xReleaseErrors,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface => stHMIInterface.stPosolytPressureSegmentInlet);
// Set error active if fb has error
IF _fbPressurePosolytSegmentInlet.xError THEN
_xErrorActive := TRUE;
END_IF
// Set warning if fb has warning
IF _fbPressurePosolytSegmentInlet.xWarning THEN
_xWarningActive := TRUE;
END_IF
// ===============================
// Pressure sensors negolyt segment inlet
// ===============================
_fbPressureNegolytSegmentInlet(
stScalingConfig:= stUnitConfig.stConfigNegolytPressureSegmentInlet,
stEWConfig:= stUnitConfig.stEWLNegolytPressureSegmentInlet,
stEWDelayConfig:= stUnitConfig.stEWDNegolytPressureSegmentInlet,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xReleaseHardwareErrors:= xReleaseErrors,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface => stHMIInterface.stNegolytPressureSegmentInlet);
// Set error active if fb has error
IF _fbPressureNegolytSegmentInlet.xError THEN
_xErrorActive := TRUE;
END_IF
// Set warning if fb has warning
IF _fbPressureNegolytSegmentInlet.xWarning THEN
_xWarningActive := TRUE;
END_IF
// ===============================
// Voltage segment
// ===============================
_fbVoltageSegment(
stScalingConfig:= ,
stEWConfig:= ,
stEWDelayConfig:= ,
xReleaseErrors:= xReleaseErrors,
xReleaseLimitErrors:= xReleaseLimitErrors,
xReleaseHardwareErrors:= xReleaseErrors,
xConfirmAlarms:= xConfirmAlarms,
stHMIInterface=> stHMIInterface.stVoltageSegment);
// Set error active if fb has error
IF _fbVoltageSegment.xError THEN
_xErrorActive := TRUE;
END_IF
// Set warning if fb has warning
IF _fbVoltageSegment.xWarning THEN
_xWarningActive := TRUE;
END_IF
// ===============================
// Check if all components are in automatic
// ===============================
_xAllComponentsInAutomatic := _fbPosolytValveTankOutlet.IsInAutomaticMode
AND _fbNegolytValveTankOutlet.IsInAutomaticMode
AND _fbPosolytPumpInlet.IsInAutomaticMode
AND _fbNegolytPumpInlet.IsInAutomaticMode;
// Raise warning
IF NOT _fbNotAllAutomaticAlarm.bRaised AND (NOT _xAllComponentsInAutomatic) THEN
_fbNotAllAutomaticAlarm.Raise(0);
END_IF
// Clear warning and reset
IF _fbNotAllAutomaticAlarm.bRaised AND _xAllComponentsInAutomatic THEN
_fbNotAllAutomaticAlarm.Clear(0, TRUE);
END_IF
// ===============================
// Run state machine for startup and shutdown
// ===============================
CASE _iState OF
0: // Off
IF xEnable AND _xAllComponentsInAutomatic AND (NOT _xErrorActive) THEN
_iState := 10;
END_IF
10: // Open all valves
_fbPosolytValveTankOutlet.ReqAutomaticOpen();
_fbNegolytValveTankOutlet.ReqAutomaticOpen();
_iState := 15;
15: // Wait for all valves to be open
IF _fbPosolytValveTankOutlet.IsOpen AND _fbNegolytValveTankOutlet.IsOpen THEN
IF NOT _fbPosolytValveTankOutlet.xError AND _fbNegolytValveTankOutlet.xError THEN
_iState := 20;
END_IF
END_IF
// If enable signal is lost, or there is an error, goto shutdown
IF (NOT xEnable) OR _xErrorActive THEN
_iState := 40;
END_IF
20: // Start pumps
_fbPosolytPumpInlet.ReqAutomaticStart();
_fbNegolytPumpInlet.ReqAutomaticStart();
_iState := 25;
25: // Wait for all pumps to run
IF _fbPosolytPumpInlet.xInTarget AND _fbNegolytPumpInlet.xInTarget THEN
_iState := 30;
END_IF
// If enable signal is lost, goto shutdown
IF (NOT xEnable) OR _xErrorActive THEN
_iState := 40;
END_IF
30: // Wait some time
_tonStartupCheck(In := TRUE, PT := _timUnitStartupWaitTime);
// After some time, check if all values are ok
IF _tonStartupCheck.Q THEN
// Check for minimum unit voltage
IF _fbVoltageSegment.rScaledValue >= GVL_CONFIG.rMinimumUnitVoltage AND
NOT _xErrorActive AND
NOT _xWarningActive THEN
xReady := TRUE;
_iState := 35;
ELSE
_iState := 40;
END_IF
END_IF
// If enable signal is lost, goto shutdown
IF (NOT xEnable) OR _xErrorActive THEN
_iState := 40;
END_IF
35: // Unit in enabled state
IF (NOT xEnable) OR _xErrorActive THEN
_iState := 40;
END_IF
40: // Close all valves
_fbNegolytValveTankOutlet.ReqAutomaticClose();
_fbPosolytValveTankOutlet.ReqAutomaticClose();
_iState := 45;
45: // Wait for valves to be closed
IF _fbNegolytValveTankOutlet.IsClosed AND _fbPosolytValveTankOutlet.IsClosed THEN
_iState := 50;
END_IF
// When there is an error trying to close the valves,
// dont try to discharge the segment
IF _fbNegolytValveTankOutlet.xError OR _fbPosolytValveTankOutlet.xError THEN
_iState := 60;
END_IF
// Check for restart condition
IF xEnable AND (NOT _xErrorActive) THEN
_iState := 0;
END_IF
50: // Wait for unit voltage to drop below a certain threshold
IF (_fbVoltageSegment.rScaledValue <= GVL_CONFIG.rPumpshutoffThreshold) THEN
_iState := 60;
END_IF
// Check for restart condition
IF xEnable AND (NOT _xErrorActive) THEN
_iState := 0;
END_IF
60: // Disable pumps
_fbPosolytPumpInlet.ReqAutomaticStop();
_fbNegolytPumpInlet.ReqAutomaticStop();
_iState := 65;
65: // Wait for pumps to be stopped
IF _fbPosolytPumpInlet.IsStopped AND _fbNegolytPumpInlet.IsStopped THEN
IF _xErrorActive THEN
_iState := 1000;
ELSE
_iState := 0;
END_IF
END_IF
// Check for restart condition
IF xEnable AND (NOT _xErrorActive) THEN
_iState := 0;
END_IF
1000: // Alarm active
// Only allow reset when enable is deactivated to avoid an
// automatic restart of the unit
IF (NOT _xErrorActive) AND (NOT xEnable) THEN
_iState := 0;
END_IF
END_CASE
// ===============================
// Output error and warning flags
// ===============================
xError := _xErrorActive;
xWarning := _xWarningActive;]]></ST>
</Implementation>
<Method Name="FB_init" Id="{08f1cd44-6483-4d20-ab45-d1938e8ec885}">
<Declaration><![CDATA[METHOD FB_init : BOOL
VAR_INPUT
bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
sName : STRING;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_sName := sName;
_fbNotAllAutomaticAlarm.CreateEx(TC_EVENTS.General.NotAllCompInAutomatic, bWithConfirmation := FALSE, 0);
_fbNotAllAutomaticAlarm.ipArguments.Clear().AddString(_sName);]]></ST>
</Implementation>
</Method>
<LineIds Name="FB_Unit">
<LineId Id="4232" Count="29" />
<LineId Id="4584" Count="0" />
<LineId Id="4263" Count="102" />
<LineId Id="4619" Count="0" />
<LineId Id="4367" Count="46" />
<LineId Id="4621" Count="22" />
<LineId Id="4620" Count="0" />
<LineId Id="4644" Count="1" />
<LineId Id="4414" Count="0" />
<LineId Id="4647" Count="0" />
<LineId Id="4646" Count="0" />
<LineId Id="4416" Count="17" />
<LineId Id="4444" Count="26" />
<LineId Id="4476" Count="33" />
<LineId Id="4511" Count="17" />
<LineId Id="4653" Count="0" />
<LineId Id="4655" Count="2" />
<LineId Id="4654" Count="0" />
<LineId Id="4529" Count="4" />
<LineId Id="4658" Count="0" />
<LineId Id="4660" Count="2" />
<LineId Id="4659" Count="0" />
<LineId Id="4569" Count="0" />
<LineId Id="4535" Count="12" />
<LineId Id="4663" Count="0" />
<LineId Id="4665" Count="2" />
<LineId Id="4664" Count="0" />
<LineId Id="4548" Count="6" />
<LineId Id="4556" Count="6" />
<LineId Id="2754" Count="0" />
</LineIds>
<LineIds Name="FB_Unit.FB_init">
<LineId Id="11" Count="1" />
<LineId Id="7" Count="1" />
</LineIds>
</POU>
</TcPlcObject>

28
PLC/POUs/MAIN.TcPOU Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<POU Name="MAIN" Id="{bbd7302c-91ce-4697-9f4b-743f57ca5819}" SpecialFunc="None">
<Declaration><![CDATA[PROGRAM MAIN
VAR
_xEmergencyStopOk AT %I* : BOOL;
_xReleaseErrors : BOOL;
_xReleaseLimitsErrors : BOOL;
_xConfirmAlarms : BOOL;
_fbString : FB_String('String 1');
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_fbString(
stHMIInterface:= ,
xEmergencyStopOk:= _xEmergencyStopOk,
xReleaseErrors:= _xReleaseErrors,
xReleaseLimitErrors:= _xReleaseLimitsErrors,
xConfirmAlarms:= _xConfirmAlarms,
xError=> ,
xWarning=> );]]></ST>
</Implementation>
<LineIds Name="MAIN">
<LineId Id="7" Count="6" />
<LineId Id="2" Count="0" />
</LineIds>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,628 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<POU Name="FB_PowerSupplySunspec" Id="{a826dd09-442c-45c5-8ae3-9b71f293003c}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_PowerSupplySunspec
VAR_INPUT
sInverterIPAddr : STRING;
xEnable : BOOL;
rPower : REAL;
xReset : BOOL;
rMaxBattPower : REAL := 24_000; // 24kW
END_VAR
VAR_OUTPUT
xCloseDCRelais AT %Q*: BOOL;
rActDCCurrent : REAL;
rActDCVoltage : REAL;
xError : BOOL;
xActive : BOOL;
END_VAR
VAR
// Current state
_iState : INT := 0;
// FB for reading Modbus holding registers
_fbReadRegister : FB_MBReadRegs;
// FB for writing Modbus holding registers
_fbWriteRegister : FB_MBWriteRegs;
// Timer for checking if the inverter started in a reasonable amount of time
_tonInverterStartup : TON;
// converter max power scaling factor
_iWMaxSF : INT;
// Unscaled converter max power
_iWMax : UINT;
// Scaled converter max power
_rWMax : REAL;
// Unscaled limit for converter power
_iWMaxLimPct : INT;
// Scaling factor for power limiting
_iWMaxLimPctSF : INT;
// Unscaled maximum power from type label
_iWRTGSF : INT;
// Scaling for maximum power from type label
_rWRTGScaling : REAL;
// Current state of the inverters internal statemachine
_uiInverterState : UINT;
// Last written power to the inverter
_rOldPower : REAL;
// Value to enable or dissable the Power limiting feature
_uiMaxLimEn : UINT;
// Value for commanding the target state of the inverter
_uiPCSSetOperation : UINT;
// Holds the state number in which an error occured
_iErrorInState : INT;
// Time for polling for current dc values and check for inverter error
_timPollingDelay : TIME := T#250MS;
// Timer for polling of current values
_tonPollingTimer : TON;
// Current DC values (DCA, DCA_SF, DCV, DCV_SF) in word array for efficient modbus reading
_awCurrentDCValues : ARRAY[0..3] OF WORD;
// Inverter error bits
_dwErrorBits : DWORD;
// Inverter reset errors command
_uiResetInverter : UINT := 1;
END_VAR
VAR CONSTANT
// Inverter statemachine status register
// Size 1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
STATUS_REGISTER : WORD := 40108;
// Throttled power register
// Size 1, int16 (Range = -32767 .. 32767, Not implemented 0x8000)
W_MAX_LIM_PCT_REGISTER : WORD := 40187;
// Throttled power register scaling factor
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
W_MAX_LIM_PCT_SF_REGISTER : WORD := 40205;
// Control register to enable and dissable if the power throttleing should be active
// Size1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
W_MAX_LIM_EN_REGISTER : WORD := 40191;
// Register to reset latched alarms in the inverter
// Size 1, uint16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
PCS_ALARM_RESET_REGISTER : WORD := 40230;
// Control register to set the target state of the inverters state machine
// Size 1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
PCS_SET_OPERATION_REGISTER : WORD := 40231;
// Maximum inverter output power
// Size 1, uint16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
W_MAX_REGISTER : WORD := 40152;
// Maximum inverter output power scaling factor
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
W_MAX_SF_REGISTER : WORD := 40172;
// Maximum inverter output power from type label
// Size 1, uint16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
W_RTG_REGISTER : WORD := 40125;
// Maximum inverter output power from type label scaling factor
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
W_RTG_SF_REGISTER : WORD := 40126;
// Start of register with the current dc values
// Size 4
DC_VALUES_START_REGISTER : WORD := 40097;
// Error bits register
// Size 2
EVT_1_REGISTER : WORD := 40110;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Clamp rPower to maximum allowed power
IF (rPower > rMaxBattPower) THEN
rPower := rMaxBattPower;
END_IF
IF (rPower < -rMaxBattPower) THEN
rPower := -rMaxBattPower;
END_IF
// State machine
CASE _iState OF
0: // Off
// If enable and INTLK Ok
IF xEnable THEN
_iState := 10;
xCloseDCRelais := TRUE;
END_IF
10: // Wait for inverter to be online and in state STANDBY(8)
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= STATUS_REGISTER,
cbLength:= SIZEOF(_uiInverterState),
pDestAddr:= ADR(_uiInverterState),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error and the state is STANDBY(8) then continue
IF NOT _fbReadRegister.bError AND _uiInverterState = 8 THEN
_iState := 20;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
20: // Read inverter max power scaling
_iErrorInState := _iState;
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= W_MAX_SF_REGISTER,
cbLength:= SIZEOF(_iWMaxSF),
pDestAddr:= ADR(_iWMaxSF),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error then continue
IF NOT _fbReadRegister.bError THEN
_iState := 25;
// Check for valid value
IF (_iWMaxSF < -10) OR (_iWMaxSF > 10) OR (_iWMaxSF = 16#8000) THEN
// Goto error state
_iState := 1000;
END_IF
ELSE
xError := TRUE;
// Goto error state
_iState := 1000;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
25: // Read inverter Max power limit scaling
_iErrorInState := _iState;
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= W_MAX_LIM_PCT_SF_REGISTER,
cbLength:= SIZEOF(_iWMaxLimPctSF),
pDestAddr:= ADR(_iWMaxLimPctSF),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error then continue
IF NOT _fbReadRegister.bError THEN
_iState := 30;
// Check for valid value
IF (_iWMaxLimPctSF < -10) OR (_iWMaxLimPctSF > 10) OR (_iWMaxLimPctSF = 16#8000) THEN
// Goto error state
_iState := 1000;
END_IF
ELSE
xError := TRUE;
// Goto error state
_iState := 1000;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
30: // Read inverter max power
_iErrorInState := _iState;
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= W_MAX_REGISTER,
cbLength:= SIZEOF(_iWMax),
pDestAddr:= ADR(_iWMax),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error then continue
IF NOT _fbReadRegister.bError THEN
_iState := 40;
// Reading a register with scaling factor = value * 10^SF
_rWMax := _iWMax * EXPT(10,_iWMaxSF);
// Calculate power to write to register
_iWMaxLimPct := LREAL_TO_INT(rPower * EXPT(10,_iWMaxLimPctSF) / _rWMax);
ELSE
xError := TRUE;
// Goto error state
_iState := 1000;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
40: // Set power limit
_iErrorInState := _iState;
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= W_MAX_LIM_PCT_REGISTER,
cbLength:= SIZEOF(_iWMaxLimPct),
pSrcAddr:= ADR(_iWMaxLimPct),
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 := 50;
_rOldPower := rPower;
_uiMaxLimEn := 1;
ELSE
xError := TRUE;
// Goto error state
_iState := 1000;
END_IF
_fbWriteRegister(bExecute := FALSE);
END_IF
50: // Enable Power limiting (THROTTLED)
_iErrorInState := _iState;
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= W_MAX_LIM_EN_REGISTER,
cbLength:= SIZEOF(_uiMaxLimEn),
pSrcAddr:= ADR(_uiMaxLimEn),
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 := 60;
_uiPCSSetOperation := 1;
ELSE
xError := TRUE;
// Goto error state
_iState := 1000;
END_IF
_fbWriteRegister(bExecute := FALSE);
END_IF
60: // Switch to THROTTLED mode
_iErrorInState := _iState;
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= PCS_SET_OPERATION_REGISTER,
cbLength:= SIZEOF(_uiPCSSetOperation),
pSrcAddr:= ADR(_uiPCSSetOperation),
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 := 65;
ELSE
// Goto error state
_iState := 1000;
END_IF
_fbWriteRegister(bExecute := FALSE);
END_IF
65: // Wait for error polling timer
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
IF _tonPollingTimer.Q THEN
_tonPollingTimer(IN := FALSE);
_iState := 70;
ELSIF ABS(rPower - _rOldPower) > 0.1 THEN
_tonPollingTimer(IN := FALSE);
// If power has ben changed, goto set power limit mode
_iState := 40;
END_IF
// check if inverter should shut down
IF NOT xEnable THEN
_uiPCSSetOperation := 3;
// Goto shutdown sequence
_iState := 200;
END_IF
70: // Enabled, check for error
_iErrorInState := _iState;
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= STATUS_REGISTER,
cbLength:= SIZEOF(_uiInverterState),
pDestAddr:= ADR(_uiInverterState),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error and the converter has no error continue
IF NOT _fbReadRegister.bError AND (_uiInverterState <> 7) THEN
_iState := 80;
IF (_uiInverterState = 4) OR (_uiInverterState = 5) THEN
xActive := TRUE;
ELSE
xActive := FALSE;
END_IF
ELSE
xError := TRUE;
// Read error register
_iState := 990;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
80: // Read current DC values
_iErrorInState := _iState;
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 4,
nMBAddr:= DC_VALUES_START_REGISTER,
cbLength:= SIZEOF(_awCurrentDCValues),
pDestAddr:= ADR(_awCurrentDCValues),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error and the converter has no error continue
IF NOT _fbReadRegister.bError THEN
_iState := 65;
rActDCCurrent := WORD_TO_UINT(_awCurrentDCValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[1]));
rActDCVoltage := WORD_TO_UINT(_awCurrentDCValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[3]));
ELSE
// Read error register
_iState := 1000;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
200: // Shutdown sequence
_iErrorInState := _iState;
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= PCS_SET_OPERATION_REGISTER,
cbLength:= SIZEOF(_uiPCSSetOperation),
pSrcAddr:= ADR(_uiPCSSetOperation),
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 := 210;
rActDCCurrent := 0.0;
rActDCVoltage := 0.0;
ELSE
// Goto error state
_iState := 1000;
END_IF
_fbWriteRegister(bExecute := FALSE);
END_IF
210: // Wait for poll timer to
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
IF _tonPollingTimer.Q THEN
_tonPollingTimer(IN := FALSE);
_iState := 220;
END_IF
220: // Poll and wait for standby state
_iErrorInState := _iState;
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= STATUS_REGISTER,
cbLength:= SIZEOF(_uiInverterState),
pDestAddr:= ADR(_uiInverterState),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error and the converter has no error continue
IF NOT _fbReadRegister.bError THEN
_iState := 0;
xActive := FALSE;
xCloseDCRelais := FALSE;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
990: // Read error register
_iErrorInState := _iState;
_fbReadRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 2,
nMBAddr:= EVT_1_REGISTER,
cbLength:= SIZEOF(_dwErrorBits),
pDestAddr:= ADR(_dwErrorBits),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF NOT _fbReadRegister.bBusy THEN
// If there was no error and the converter has no error continue
IF NOT _fbReadRegister.bError THEN
_iState := 1000;
END_IF
_fbReadRegister(bExecute := FALSE);
END_IF
1000: // Error state, wait for reset
IF xReset AND (NOT xEnable) THEN
_iState := 1010;
END_IF
1010: // Try to clear all latched events
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#FF, // 16#FF for Modbus TCP
nQuantity:= 1,
nMBAddr:= PCS_ALARM_RESET_REGISTER,
cbLength:= SIZEOF(_uiResetInverter),
pSrcAddr:= ADR(_uiResetInverter),
bExecute:= TRUE,
tTimeout:= T#5S,
bBusy=> ,
bError=> ,
nErrId=> );
IF NOT _fbWriteRegister.bBusy THEN
_iState := 0;
_fbWriteRegister(bExecute := FALSE);
END_IF
END_CASE]]></ST>
</Implementation>
<LineIds Name="FB_PowerSupplySunspec">
<LineId Id="774" Count="70" />
<LineId Id="1171" Count="0" />
<LineId Id="845" Count="33" />
<LineId Id="1172" Count="0" />
<LineId Id="879" Count="33" />
<LineId Id="1173" Count="0" />
<LineId Id="913" Count="29" />
<LineId Id="1174" Count="0" />
<LineId Id="943" Count="28" />
<LineId Id="1175" Count="0" />
<LineId Id="972" Count="46" />
<LineId Id="1127" Count="0" />
<LineId Id="1019" Count="25" />
<LineId Id="1097" Count="1" />
<LineId Id="1100" Count="1" />
<LineId Id="1099" Count="0" />
<LineId Id="1045" Count="0" />
<LineId Id="1176" Count="0" />
<LineId Id="1046" Count="6" />
<LineId Id="1063" Count="20" />
<LineId Id="1090" Count="0" />
<LineId Id="1092" Count="0" />
<LineId Id="1084" Count="4" />
<LineId Id="1062" Count="0" />
<LineId Id="1093" Count="1" />
<LineId Id="1102" Count="19" />
<LineId Id="1166" Count="1" />
<LineId Id="1122" Count="4" />
<LineId Id="1054" Count="0" />
<LineId Id="1295" Count="4" />
<LineId Id="1128" Count="0" />
<LineId Id="1300" Count="1" />
<LineId Id="1129" Count="0" />
<LineId Id="1132" Count="20" />
<LineId Id="1163" Count="0" />
<LineId Id="1294" Count="0" />
<LineId Id="1161" Count="1" />
<LineId Id="1130" Count="1" />
<LineId Id="1055" Count="0" />
<LineId Id="1177" Count="20" />
<LineId Id="1199" Count="1" />
<LineId Id="1169" Count="0" />
<LineId Id="1265" Count="2" />
<LineId Id="1269" Count="3" />
<LineId Id="1274" Count="11" />
<LineId Id="1273" Count="0" />
<LineId Id="1289" Count="1" />
<LineId Id="1293" Count="0" />
<LineId Id="1291" Count="1" />
<LineId Id="1056" Count="0" />
<LineId Id="12" Count="0" />
</LineIds>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
<DUT Name="U_SUNSPEC_ERROR" Id="{4000836c-9d7f-470c-9b50-f6d22b3eac05}">
<Declaration><![CDATA[TYPE U_SUNSPEC_ERROR :
UNION
xGroundFault : BOOL;
xDCOverVoltage : BOOL;
xACDisconnected : BOOL;
xDCDisconnected : BOOL;
xGridDisconnected : BOOL;
xCabinetOpen : BOOL;
xManualShutdown : BOOL;
xOverTemp : BOOL;
xOverFrequency : BOOL;
xUnderFrequency : BOOL;
xACOverVoltage : BOOL;
xACUnderVoltage : BOOL;
xBlownStringFuse : BOOL;
xUnderTemp : BOOL;
xMemoryLoss : BOOL;
xHWTestFailure : BOOL;
xOtherAlarm : BOOL;
xOtherWarning : BOOL;
END_UNION
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

17
PLC/PlcTask.TcTTO Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<Task Name="PlcTask" Id="{13b7271a-7fe7-45e4-a613-10870835774e}">
<!--CycleTime in micro seconds.-->
<CycleTime>10000</CycleTime>
<Priority>20</Priority>
<PouCall>
<Name>MAIN</Name>
</PouCall>
<TaskFBGuid>{ffdacf88-4402-4cda-9656-2a188e28ec71}</TaskFBGuid>
<Fb_init>{0eaf59ea-61db-47c0-9b16-500c1d3c6c82}</Fb_init>
<Fb_exit>{f41aba84-dc9f-4b62-bb12-30d3e8314fa6}</Fb_exit>
<CycleUpdate>{347af9e1-a730-412d-bdd1-dba423bbf20a}</CycleUpdate>
<PostCycleUpdate>{10f1bd59-1481-4492-b627-08c962a0f93d}</PostCycleUpdate>
<ObjectProperties />
</Task>
</TcPlcObject>

Binary file not shown.