Files
BasicComponents/PLC/POUs/Unittests/ValveTests/FB_Valve_Test.TcPOU
2025-11-13 09:19:39 +01:00

427 lines
14 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_Valve_Test" Id="{1304864d-3fed-4e82-bcdb-9dc7e4b2a441}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Valve_Test EXTENDS TcUnit.FB_TestSuite
VAR
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Automatic Mode
SwitchToAutomaticMode();
OpenValveInAutomaticMode();
// Manual Mode
SwitchToManualMode();
OpenValveInManualMode();
// Test interlocks
TestProcessInterlocks();
TestProcessINTLKsInAutomaticMode();
TestProcessINTLKsInManualMode();
// Check feedback signals
CheckOpenCloseFeedbacks();
]]></ST>
</Implementation>
<Method Name="CheckOpenCloseFeedbacks" Id="{a28ac9cc-3e5a-4aec-ae25-5e2418416c2e}">
<Declaration><![CDATA[{warning disable C0394}
METHOD CheckOpenCloseFeedbacks
VAR
// valve instance
_fbValve : FB_Valve('');
// valve config
_stHMIValve : ST_HMI_VALVE_DATA;
_stValveConfig : ST_ValveConfig;
// valve feedback
_xOpenFeedback : BOOL;
_xCloseFeedback : BOOL;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('CheckOpenCloseFeedbacks');
// set timeout to zero and open+close feedback present
_stValveConfig.timTimeoutClose := T#0S;
_stValveConfig.timTimeoutOpen := T#0S;
_stValveConfig.xHasOpenFeedback := TRUE;
_stValveConfig.xHasClosedFeedback := TRUE;
// Test feedbacks in manual mode
_xOpenFeedback := FALSE;
_xCloseFeedback := FALSE;
_fbValve.xReleaseManualMode := TRUE;
_fbValve.ReqManualMode();
_fbValve(xOpenFeedback := _xOpenFeedback, xCloseFeedback := _xCloseFeedback, stHMIInterface := _stHMIValve, stValveConfig := _stValveConfig, xInUnitTestMode := TRUE);
// We should now be in manual mode
AssertTrue(Condition := _fbValve.IsInManualMode, Message := 'Valve did not changed to manual mode');
// Test not closed and not opened
AssertFalse(Condition := _fbValve.IsClosed OR _fbValve.IsOpen, Message := 'Valve should not signal open or closed with no feedback signals');
// Test closed
_xOpenFeedback := FALSE;
_xCloseFeedback := TRUE;
_fbValve(xOpenFeedback := _xOpenFeedback, xCloseFeedback := _xCloseFeedback,stHMIInterface := _stHMIValve, stValveConfig := _stValveConfig, xInUnitTestMode := TRUE);
AssertTrue(Condition := _fbValve.IsClosed, Message := 'Valve should be closed');
AssertFalse(Condition := _fbValve.IsOpen, Message := 'Valve should not be open');
// Test opened
_xOpenFeedback := TRUE;
_xCloseFeedback := FALSE;
_stHMIValve.stOpenButton.xRequest := TRUE;
_fbValve(stHMIInterface := _stHMIValve);
_fbValve(xOpenFeedback := _xOpenFeedback, xCloseFeedback := _xCloseFeedback, stHMIInterface := _stHMIValve, stValveConfig := _stValveConfig, xInUnitTestMode := TRUE);
AssertTrue(Condition := _fbValve.IsOpen, Message := 'Valve should be open');
AssertFalse(Condition := _fbValve.IsClosed, Message := 'Valve should not be closed');
// Test open and close
_xOpenFeedback := TRUE;
_xCloseFeedback := TRUE;
_fbValve(xOpenFeedback := _xOpenFeedback, xCloseFeedback := _xCloseFeedback, stHMIInterface := _stHMIValve, stValveConfig := _stValveConfig, xInUnitTestMode := TRUE);
AssertFalse(Condition := _fbValve.IsClosed OR _fbValve.IsOpen, Message := 'Valve should not signal open or closed with both feedback signals high');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="OpenValveInAutomaticMode" Id="{0b9852fb-7e89-42e5-977d-75ac8ce8f431}">
<Declaration><![CDATA[{warning disable C0394}
METHOD OpenValveInAutomaticMode
VAR
// valve instance
_fbValve : FB_Valve('');
// valve hmi data
_stHMIValve : ST_HMI_VALVE_DATA;
// valve state
_xResult : BOOL;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('OpenValveInAutomaticMode');
// Set in automatic mode
_fbValve.ReqAutomaticMode();
// Open valve
_fbValve(xAutomaticOpen := TRUE, stHMIInterface := _stHMIValve);
// Needs one cycle to write outputs
_fbValve(stHMIInterface := _stHMIValve, xInUnitTestMode := TRUE);
// evaluate valve state
_xResult := _fbValve.IsOpen AND NOT _fbValve.IsClosed;
AssertTrue(_xResult, 'Valve did not open in Automatic Mode');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="OpenValveInManualMode" Id="{ebd3a3ca-f259-4efb-b134-f4d858027ff8}">
<Declaration><![CDATA[{warning disable C0394}
METHOD OpenValveInManualMode
VAR
// valve instance
_fbValve : FB_Valve('');
// valve hmi data
_stHMIValve : ST_HMI_VALVE_DATA;
// valve state
_xResult : BOOL;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('OpenValveInManualMode');
// Needs one cycle to write outputs
_fbValve.xReleaseManualMode := TRUE;
// Set in manual mode
_fbValve.ReqManualMode();
// Open valve
_stHMIValve.stOpenButton.xRequest := TRUE;
_fbValve(stHMIInterface := _stHMIValve);
_fbValve(stHMIInterface := _stHMIValve, xInUnitTestMode := TRUE);
// evaluate valve state
_xResult := _fbValve.IsOpen AND NOT _fbValve.IsClosed;
AssertTrue(_xResult, 'Valve did not open in Manual Mode');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="SwitchToAutomaticMode" Id="{f0347789-26a5-4296-ac7a-3320d7d68b7f}">
<Declaration><![CDATA[{warning disable C0394}
METHOD SwitchToAutomaticMode
VAR
// valve instance
_fbValve : FB_Valve('');
// valve hmi data
_stHMIValve : ST_HMI_VALVE_DATA;
// valve state
_xResult : BOOL;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('SwitchToAutomaticMode');
// request switch to automatic modes
_fbValve.ReqAutomaticMode();
// call valve and read values
_fbValve(stHMIInterface := _stHMIValve, xInUnitTestMode := TRUE);
// set result
_xResult := _fbValve.IsInAutomaticMode;
// assert result
AssertTrue(_xResult, 'Valve did not change into Automatic Mode');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="SwitchToManualMode" Id="{f3a6a0eb-d468-45b4-ae0e-31d573348f7d}">
<Declaration><![CDATA[{warning disable C0394}
METHOD SwitchToManualMode
VAR
// valve instance
_fbValve : FB_Valve('');
// valve state
_xResult : BOOL;
// valve hmi data
_stHMIValve : ST_HMI_VALVE_DATA;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('SwitchToManualMode');
// Test switch without xReleaseManualMode
_fbValve.xReleaseManualMode := FALSE;
_fbValve.ReqManualMode();
_fbValve(stHMIInterface := _stHMIValve, xInUnitTestMode := TRUE);
_xResult := NOT _fbValve.IsInManualMode;
AssertTrue(_xResult, 'Valve changed to Manual Mode but this mode was not released');
// Test with xReleaseManualMode
_fbValve.xReleaseManualMode := TRUE;
_fbValve.ReqManualMode();
_fbValve(stHMIInterface := _stHMIValve);
_xResult := _fbValve.IsInManualMode;
AssertTrue( _xResult, 'Valve did not changed to Manual Mode');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="TestProcessInterlocks" Id="{a963e3c3-4c6c-44cd-913b-cd94b66ce40c}">
<Declaration><![CDATA[{warning disable C0394}
{attribute 'analysis' := '-81'}
METHOD TestProcessInterlocks
VAR
// valve instance
_fbValve : FB_Valve('');
// valve hmi data
_stHMIValve : ST_HMI_VALVE_DATA;
// valve state
_xResult : BOOL;
// current interlock
_usiCounter : USINT;
// Init all entries to TRUE
_wInterlocks : T_INTERLOCK := 2#1111_1111_1111_1111;//[GVL_VALVE.MAX_INTERLOCKS(TRUE)];
_wInterlocksUsed : T_INTERLOCK := 2#1111_1111_1111_1111;
// interlock test result
_axInterlockTestResultFalse : ARRAY[0..GVL_CONFIGS.MAX_INTERLOCKS-1] OF BOOL;
_axInterlockTestResultTrue : ARRAY[0..GVL_CONFIGS.MAX_INTERLOCKS-1] OF BOOL;
// interlock comulated result
_xInterlocksFalseOK : BOOL;
_xInterlocksTrueOK : BOOL;
END_VAR
VAR CONSTANT
// loop iterations for interlock test
usiEndValue : USINT := GVL_CONFIGS.MAX_INTERLOCKS-1;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[// Test interlocks as reutrn value
TEST('TestProcessInterlocks');
// call valve with interlocks and evaluate result
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve, xInUnitTestMode := TRUE);
_xResult := _fbValve.ProcessInterlocksOK;
AssertTrue(_xResult, 'Interlocks not Ok but should be');
// Test each interlock individually
// Save the result in the two following variables
_xInterlocksFalseOK := TRUE;
_xInterlocksTrueOK := TRUE;
FOR _usiCounter := 0 TO usiEndValue DO
// Test one interlock for false and then disable it
_wInterlocks := SHL(_wInterlocks, 1);
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Save result in an array for later debugging if necessary
_axInterlockTestResultFalse[_usiCounter] := _fbValve.ProcessInterlocksOK;
// Save global result
IF _fbValve.ProcessInterlocksOK THEN
_xInterlocksFalseOK := FALSE;
END_IF
// Disable this interlock after testing it
_wInterlocksUsed := SHL(_wInterlocksUsed, 1);
// Test if, after disabling the interlock, the interlocks are ok again
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Save result in an array for later debugging if necessary
_axInterlockTestResultTrue[_usiCounter] := _fbValve.ProcessInterlocksOK;
// Save global result
IF NOT _fbValve.ProcessInterlocksOK THEN
_xInterlocksTrueOK := FALSE;
END_IF
END_FOR
// Test False interlocks result
AssertTrue(_xInterlocksFalseOK, 'Interlock should not be ok but are');
// Test False interlocks result
AssertTrue(_xInterlocksTrueOK, 'Interlock should be ok but are not');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="TestProcessINTLKsInAutomaticMode" Id="{d6681863-baa6-4f1c-bb6d-7d6ecd0c4518}">
<Declaration><![CDATA[{warning disable C0394}
METHOD TestProcessINTLKsInAutomaticMode
VAR
// valve instance
_fbValve : FB_Valve('');
// valve hmi data
_stHMIValve : ST_HMI_VALVE_DATA;
// valve interlocks
_wInterlocks : T_INTERLOCK;
_wInterlocksUsed : T_INTERLOCK;
// valve config
_stValveConfig : ST_ValveConfig;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('TestProcessINTLKsInAutomaticMode');
_wInterlocks.0 := 1;
_wInterlocksUsed.0 := 1;
// Switch to automatic mode
_fbValve.ReqAutomaticMode();
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve, xInUnitTestMode := TRUE);
// Open valve in automatic mode
_fbValve(xAutomaticOpen := TRUE, stHMIInterface := _stHMIValve);
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Test if valve is open, when not we have an intermediate error
// which should have been found by another test
IF _fbValve.IsOpen THEN
// Activate an interlock
_wInterlocks.0 := 0;
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Valve should now be closed
AssertFalse(Condition := _fbValve.xOpenValve, Message := 'Valve should not be open with active Interlock');
AssertTrue(Condition := _fbValve.xCloseValve, Message := 'Close output not active with active Interlock');
// Test the same with open valve when interlock active
_stValveConfig.xOpenWhenInterlocksActive := TRUE;
_fbValve(stValveConfig := _stValveConfig, wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Valve should now be open
AssertTrue(Condition := _fbValve.xOpenValve, Message := 'Valve should be open with active Interlock and inverted config');
AssertFalse(Condition := _fbValve.xCloseValve, Message := 'Close output active with active Interlock and inverted config');
ELSE
AssertTrue(Condition := _fbValve.IsOpen, Message := 'Valve did not open before the test');
END_IF
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="TestProcessINTLKsInManualMode" Id="{24ef6949-9116-427c-aa82-83ed6d197c5c}">
<Declaration><![CDATA[{warning disable C0394}
METHOD TestProcessINTLKsInManualMode
VAR
// valve instance
_fbValve : FB_Valve('');
// valve hmi data
_stHMIValve : ST_HMI_VALVE_DATA;
// valve interlocks
_wInterlocks : T_INTERLOCK;
_wInterlocksUsed : T_INTERLOCK;
// valve config
_stValveConfig : ST_ValveConfig;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('TestProcessINTLKsInManualMode');
_wInterlocks.0 := 1;
_wInterlocksUsed.0 := 1;
// Switch to manual mode
_fbValve.xReleaseManualMode := TRUE;
_fbValve.ReqManualMode();
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve, xInUnitTestMode := TRUE);
// Open valve in manual mode
_stHMIValve.stOpenButton.xRequest := TRUE;
_fbValve(stHMIInterface := _stHMIValve);
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Test if valve is open, when not we have an intermediate error
// which should have been found by another test
IF _fbValve.IsOpen THEN
// Activate an interlock
_wInterlocks.0 := 0;
_fbValve(wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Valve should now be closed
AssertFalse(Condition := _fbValve.xOpenValve, Message := 'Valve should not be open with active Interlock');
AssertTrue(Condition := _fbValve.xCloseValve, Message := 'Close output not active with active Interlock');
// Test the same with open valve when interlock active
_stValveConfig.xOpenWhenInterlocksActive := TRUE;
_fbValve(stValveConfig := _stValveConfig, wProcessINTLK := _wInterlocks, wProcessINTLKUsed := _wInterlocksUsed, stHMIInterface := _stHMIValve);
// Valve should now be open
AssertTrue(Condition := _fbValve.xOpenValve, Message := 'Valve should be open with active Interlock and inverted config');
AssertFalse(Condition := _fbValve.xCloseValve, Message := 'Close output active with active Interlock and inverted config');
AssertTrue(Condition := _stHMIValve.stOpenButton.eFeedback = E_HMI_BUTTON_FEEDBACK.ACTIVE, Message := 'Open button should be set active with active Interlock and inverted config');
ELSE
AssertTrue(Condition := _fbValve.IsOpen, Message := 'Valve did not open before the test');
END_IF
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>