Files
2026-03-19 19:40:01 +01:00

196 lines
5.4 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_Tank" Id="{d029e65c-5c27-470b-8bee-fea9f0455669}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Tank
VAR_INPUT
xOpenPumpValve : BOOL;
xReleaseErrors : BOOL;
xReleaseManualMode : BOOL;
xConfirmAlarms : BOOL;
END_VAR
VAR_OUTPUT
xOverfull : BOOL;
xFull : BOOL;
xEmpty : BOOL;
xError : BOOL;
END_VAR
VAR_IN_OUT
stIO : ST_Tank_IO;
stHMIInterface : ST_HMI_Tank;
END_VAR
VAR
_fbWaterValve : FB_Valve('Water valve');
_fbFillingValve : FB_Valve('Filling valve');
_fbDrainValve : FB_Valve('Drain Valve');
_fbPumpValve : FB_Valve('Pump Valve');
_stValveConfig : ST_ValveConfig;
_wFillingValveSafetyIntlkUsed : T_INTERLOCK;
_wFillingValveSafetyIntlk : T_INTERLOCK;
_xStartEmptyTank : BOOL;
_xStartFillTankWater : BOOL;
_iState : INT;
_xFirstCycle : BOOL := TRUE;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[IF _xFirstCycle THEN
_xFirstCycle := FALSE;
stHMIInterface.stFillingValve.stInterlock.asSafetyINTLKName[0] := 'Tank overfull';
_wFillingValveSafetyIntlkUsed.0 := 1;
END_IF
M_HandleHMIInput();
// Overfull is NC so true if ok
_wFillingValveSafetyIntlk.0 := stIO.i_xOverfull;
_fbFillingValve(
xReleaseErrors:= xReleaseErrors,
stValveConfig:= _stValveConfig,
xReleaseManualMode:= xReleaseManualMode,
wSafetyINTLK:= _wFillingValveSafetyIntlk,
wSafetyINTLKUsed:= _wFillingValveSafetyIntlkUsed,
xConfirmAlarms:= xConfirmAlarms,
stIO := stIO.stValveFilling,
stHMIInterface:= stHMIInterface.stFillingValve);
_fbWaterValve(
xReleaseErrors:= xReleaseErrors,
stValveConfig:= _stValveConfig,
xReleaseManualMode:= xReleaseManualMode,
xConfirmAlarms:= xConfirmAlarms,
stIO := stIO.stValveWater,
stHMIInterface:= stHMIInterface.stDrainValve);
_fbDrainValve(
xReleaseErrors:= xReleaseErrors,
stValveConfig:= _stValveConfig,
xReleaseManualMode:= xReleaseManualMode,
xConfirmAlarms:= xConfirmAlarms,
stIO := stIO.stValveDrain,
stHMIInterface:= stHMIInterface.stDrainValve);
_fbPumpValve(
xAutomaticOpen := xOpenPumpValve,
xReleaseErrors:= xReleaseErrors,
stValveConfig:= _stValveConfig,
xReleaseManualMode:= xReleaseManualMode,
xConfirmAlarms:= xConfirmAlarms,
stIO := stIO.stValvePump,
stHMIInterface:= stHMIInterface.stPumpValve);
CASE _iState OF
// Idle
0:
IF _xStartEmptyTank THEN
_xStartEmptyTank := FALSE;
_iState := 10;
END_IF
IF _xStartFillTankWater THEN
_xStartFillTankWater := FALSE;
_iState := 20;
END_IF
// Empty tank
10:
_fbDrainValve.xAutomaticOpen := TRUE;
IF (NOT stIO.i_xEmpty) THEN
_fbDrainValve.xAutomaticOpen := FALSE;
_iState := 0;
END_IF
// Fill tank with water
20:
_fbWaterValve.xAutomaticOpen := TRUE;
IF xFull THEN
_fbWaterValve.xAutomaticOpen := FALSE;
_iState := 0;
END_IF
END_CASE
M_HandleHMIOutput();
// Copy to output buffer
xOverfull := (NOT stIO.i_xOverfull);
xFull := stIO.i_xFull;
xEmpty := (NOT stIO.i_xEmpty);]]></ST>
</Implementation>
<Method Name="FB_Init" Id="{9c6d1842-9c2e-4437-b40f-941f77668ffe}">
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
//The return value is not evaluated. For a specific influence, you can also declare the
//methods explicitly and provide additional code there with the standard initialization
//code. You can evaluate the return value.
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_stValveConfig.xHasOpenFeedback := FALSE;
_stValveConfig.xHasClosedFeedback := FALSE;]]></ST>
</Implementation>
</Method>
<Method Name="M_HandleHMIInput" Id="{ff85cf86-15cf-4e14-ac8d-98aa206cdc7d}">
<Declaration><![CDATA[METHOD PRIVATE M_HandleHMIInput : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[{warning disable C0371}
// Start emptying tank
IF stHMIInterface.stEmptyButton.xRequest THEN
stHMIInterface.stEmptyButton.xRequest := FALSE;
IF stHMIInterface.stEmptyButton.xRelease THEN
_xStartEmptyTank := TRUE;
END_IF
END_IF
// Start filling tank with water
IF stHMIInterface.stFillButton.xRequest THEN
stHMIInterface.stFillButton.xRequest := FALSE;
IF stHMIInterface.stFillButton.xRelease THEN
_xStartFillTankWater := TRUE;
END_IF
END_IF]]></ST>
</Implementation>
</Method>
<Method Name="M_HandleHMIOutput" Id="{8939e00b-3459-4b5e-a4b3-7b489eec260a}">
<Declaration><![CDATA[METHOD PRIVATE M_HandleHMIOutput : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[{warning disable C0371}
// Overfull sensor is NC
stHMIInterface.xOverfull := (NOT stIO.i_xOverfull);
stHMIInterface.xFull := stIO.i_xFull;
stHMIInterface.xEmpty := (NOT stIO.i_xEmpty);
stHMIInterface.stFillButton.xRelease := stIO.i_xOverfull AND (NOT stIO.i_xFull);
stHMIInterface.stEmptyButton.xRelease := stIO.i_xEmpty;
IF _fbWaterValve.IsOpen THEN
stHMIInterface.stFillButton.eFeedback := 1;
ELSE
stHMIInterface.stFillButton.eFeedback := 0;
END_IF
IF _fbDrainValve.IsOpen THEN
stHMIInterface.stEmptyButton.eFeedback := 1;
ELSE
stHMIInterface.stEmptyButton.eFeedback := 0;
END_IF]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>