Changed from ISA88 to PackML

- Added PackML Base FB's
- Added Unit Tests for PackML Base State Machine
- Added Robot job numbers according to new interface
- Added PLC job number for robot to call according to new interface
- Change Robot to PackML interface
This commit is contained in:
2026-01-23 22:55:49 +01:00
parent 2d11c43579
commit 3946e45c65
26 changed files with 1615 additions and 421 deletions

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="E_Isa88_Cmd" Id="{697f242d-4f68-49dd-b08e-e24e192406b6}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
{attribute 'to_string'}
TYPE E_Isa88_Cmd :
(
RESET := 0,
START,
PAUSE,
RESUME,
STOP,
HOLD,
RESTART,
ABORT
);
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="E_Isa88_State" Id="{67b9298d-6884-4e53-b893-d852614b96d4}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
{attribute 'to_string'}
TYPE E_Isa88_State :
(
IDLE := 0,
RUNNING,
COMPLETE,
PAUSING,
PAUSED,
HOLDING,
HELD,
RESTARTING,
STOPPING,
STOPPED,
ABORTING,
ABORTED
);
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -1,177 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_Isa88_SM" Id="{29def7dc-7eb7-4788-94bf-20badd909417}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_Isa88_SM IMPLEMENTS I_Isa88_SM
VAR_INPUT
xExecute : BOOL;
eCMD : E_Isa88_Cmd;
END_VAR
VAR_OUTPUT
eCurrentState : E_Isa88_State;
eCurrentCMD : E_Isa88_Cmd;
END_VAR
VAR
_eState : E_Isa88_State;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[CASE _eState OF
E_Isa88_State.IDLE:
M_StateIdle();
E_Isa88_State.RUNNING:
M_StateRunning();
E_Isa88_State.COMPLETE:
M_StateComplete();
E_Isa88_State.PAUSING:
IF M_StatePausing() THEN
_eState := E_Isa88_State.PAUSED;
END_IF
E_Isa88_State.PAUSED:
M_StatePaused();
E_Isa88_State.HOLDING:
IF M_StateHolding() THEN
_eState := E_Isa88_State.HELD;
END_IF
E_Isa88_State.HELD:
M_StateHeld();
E_Isa88_State.RESTARTING:
IF M_StateRestarting() THEN
_eState := E_Isa88_State.RUNNING;
END_IF
E_Isa88_State.STOPPING:
IF M_StateStopping() THEN
_eState := E_Isa88_State.STOPPED;
END_IF
E_Isa88_State.STOPPED:
M_StateStopped();
E_Isa88_State.ABORTING:
IF M_StateAborting() THEN
_eState := E_Isa88_State.ABORTED;
END_IF
E_Isa88_State.ABORTED:
M_StateAborted();
ELSE
;
END_CASE]]></ST>
</Implementation>
<Method Name="M_StateAborted" Id="{7d3ae447-cd1c-41c4-ac16-4adbba3ca9d2}">
<Declaration><![CDATA[METHOD M_StateAborted
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateAborting" Id="{65c188ca-e49a-469e-8acf-15108e45afc4}">
<Declaration><![CDATA[METHOD M_StateAborting : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateComplete" Id="{c6f588b5-faa7-4cdb-8ef7-15b60b1b3437}">
<Declaration><![CDATA[METHOD M_StateComplete
VAR_INPUT
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateHeld" Id="{d3017117-19ee-4be8-a004-3bf1cb3e986c}">
<Declaration><![CDATA[METHOD M_StateHeld
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateHolding" Id="{aa747568-2f98-4853-8a09-082a8e71cb49}">
<Declaration><![CDATA[METHOD M_StateHolding : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateIdle" Id="{a1e6fb67-08b4-4452-a103-1e87b93b70df}">
<Declaration><![CDATA[METHOD M_StateIdle
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StatePaused" Id="{e2e36464-c119-471f-8bba-3290f653d282}">
<Declaration><![CDATA[METHOD M_StatePaused
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StatePausing" Id="{02b59ba7-54b7-4ccd-88ad-9fc49284626e}">
<Declaration><![CDATA[METHOD M_StatePausing : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateRestarting" Id="{b6ffa7ab-5439-47ef-8993-798aa3ec7e01}">
<Declaration><![CDATA[METHOD M_StateRestarting : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateRunning" Id="{e61c2773-08f6-421e-88fd-c87d0d7d7581}">
<Declaration><![CDATA[METHOD M_StateRunning
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateStopped" Id="{0455a3a5-4745-4cf5-8c40-69d001c1d9aa}">
<Declaration><![CDATA[METHOD M_StateStopped
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_StateStopping" Id="{e88bc558-0424-4a5f-99cd-f9d787839b47}">
<Declaration><![CDATA[METHOD M_StateStopping : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<Itf Name="I_Isa88_SM" Id="{40882424-4ec1-4664-8b86-b7a6af5bbb74}">
<Declaration><![CDATA[INTERFACE I_Isa88_SM
]]></Declaration>
<Method Name="M_StateAborted" Id="{e67083c3-128e-45d9-b1cc-0a35d94ac3bc}">
<Declaration><![CDATA[METHOD M_StateAborted
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateAborting" Id="{d3e0a947-0574-444f-878b-6e216d4fca0c}">
<Declaration><![CDATA[METHOD M_StateAborting : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateComplete" Id="{bef858dc-1667-4bca-9f0f-99332f97e6e2}">
<Declaration><![CDATA[METHOD M_StateComplete
VAR_INPUT
END_VAR]]></Declaration>
</Method>
<Method Name="M_StateHeld" Id="{44494e88-dd2e-4465-9ead-95d76f1444b6}">
<Declaration><![CDATA[METHOD M_StateHeld
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateHolding" Id="{2b2a3d8f-01ad-4938-b464-ceb50de62ddf}">
<Declaration><![CDATA[METHOD M_StateHolding : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateIdle" Id="{4ceced48-4f87-482f-a69a-e97b69ac8963}">
<Declaration><![CDATA[METHOD M_StateIdle
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StatePaused" Id="{fc81aaa6-18b7-4113-914d-8d5cd632e976}">
<Declaration><![CDATA[METHOD M_StatePaused
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StatePausing" Id="{48a7510c-d8b6-42c2-a5e4-f4ebcb66eb3b}">
<Declaration><![CDATA[METHOD M_StatePausing : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateRestarting" Id="{12cefe9f-48b4-4752-b95c-8ffb5612b7c4}">
<Declaration><![CDATA[METHOD M_StateRestarting : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateRunning" Id="{90fa6b25-1c31-4d7c-a91d-56a908196ed4}">
<Declaration><![CDATA[METHOD M_StateRunning
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateStopped" Id="{62d558ef-79a2-484a-a156-d8057fe6d97a}">
<Declaration><![CDATA[METHOD M_StateStopped
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_StateStopping" Id="{7ecd335a-ebd9-4170-b5b7-2f9add02b49d}">
<Declaration><![CDATA[METHOD M_StateStopping : BOOL
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
</Itf>
</TcPlcObject>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="E_PackMLCmd" Id="{3ba7a228-f199-4355-be17-fd46fc967487}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
{attribute 'to_string'}
TYPE E_PackMLCmd :
(
UNDEFINED := 0,
RESET := 1,
START := 2,
STOP := 3,
HOLD := 4,
UNHOLD := 5,
SUSPEND := 6,
UNSUSPEND := 7,
ABORT := 8,
CLEAR := 9,
COMPLETE := 10
) DINT;
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="E_PackMLState" Id="{563a2f85-ab5d-400a-a6dd-3d1839155f82}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
{attribute 'to_string'}
TYPE E_PackMLState :
(
UNDEFINED := 0,
CLEARING := 1,
STOPPED := 2,
STARTING := 3,
IDLE := 4,
SUSPENDED := 5,
EXECUTE := 6,
STOPPING := 7,
ABORTING := 8,
ABORTED := 9,
HOLDING := 10,
HELD := 11,
UNHOLDING := 12,
SUSPENDING := 13,
UNSUSPENDING := 14,
RESETTING := 15,
COMPLETING := 16,
COMPLETE := 17
) DINT := STOPPED;
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<DUT Name="E_PackMLUnitMode" Id="{56f8b8e3-48e3-4607-ac73-c965d4d0058d}">
<Declaration><![CDATA[{attribute 'qualified_only'}
{attribute 'strict'}
{attribute 'to_string'}
TYPE E_PackMLUnitMode :
(
INVALID := 0,
PRODUCTION := 1,
MAINTENANCE := 2,
MANUAL := 3,
CHANGE_OVER := 4,
CLEAN := 5,
SET_UP := 6,
EMPTY_OUT := 7
) DINT := PRODUCTION;
END_TYPE
]]></Declaration>
</DUT>
</TcPlcObject>

View File

@@ -0,0 +1,225 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_PackMLGeneric" Id="{f562a10e-01bc-407d-9fc0-2837d13c10b1}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_PackMLGeneric IMPLEMENTS I_UnitState
VAR_INPUT
// Mode from superior unit
eModeCmd : E_PackMLUnitMode;
// Command for new state from superior unit
eCmd : E_PackMLCmd;
END_VAR
VAR_OUTPUT
// Current mode of unit
eMode : E_PackMLUnitMode;
// Current state of unit
eState : E_PackMLState;
// xInvalidModeCmd : BOOL;
END_VAR
VAR
// State machine handler
_fbStateMachine : FB_PackMLStateMachine;
// Internal unit state
_eState : E_PackMLState;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_fbStateMachine(
eMode:= eMode,
eCmd:= eCmd,
eState=> _eState,
xError=> );
// Call state method according to current state
CASE _eState OF
E_PackMLState.CLEARING:
M_Clearing();
E_PackMLState.STOPPED:
M_Stopped();
E_PackMLState.STARTING:
M_Starting();
E_PackMLState.IDLE:
M_Idle();
E_PackMLState.SUSPENDED:
M_Suspended();
E_PackMLState.EXECUTE:
M_Execute();
E_PackMLState.STOPPING:
M_Stopping();
E_PackMLState.ABORTING:
M_Aborting();
E_PackMLState.ABORTED:
M_Aborted();
E_PackMLState.HOLDING:
M_Holding();
E_PackMLState.HELD:
M_Held();
E_PackMLState.UNHOLDING:
M_Unholding();
E_PackMLState.SUSPENDING:
M_Suspending();
E_PackMLState.UNSUSPENDING:
M_Unsuspending();
E_PackMLState.RESETTING:
M_Resetting();
E_PackMLState.COMPLETING:
M_Completing();
E_PackMLState.COMPLETE:
M_Complete();
ELSE
;
END_CASE
// Copy internal flags to output
eState := _eState;]]></ST>
</Implementation>
<Method Name="M_Aborted" Id="{db1a684f-e4e1-4d89-a3aa-9b9dfde0508c}">
<Declaration><![CDATA[METHOD M_Aborted
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Aborting" Id="{928ad614-a3a7-4c6c-b1bc-55ae54e4c95f}">
<Declaration><![CDATA[METHOD M_Aborting
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Clearing" Id="{1716cf1b-94c6-4995-8b3f-c7ebcf5727d3}">
<Declaration><![CDATA[METHOD M_Clearing
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Complete" Id="{33df5dea-d83b-48e1-8898-d7c8e1f031bd}">
<Declaration><![CDATA[METHOD M_Complete
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Completing" Id="{341608cb-1218-481f-929c-cb79602c11ab}">
<Declaration><![CDATA[METHOD M_Completing
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Execute" Id="{2a469169-0eb2-43c9-be21-48909285ee44}">
<Declaration><![CDATA[METHOD M_Execute
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Held" Id="{05b040b0-b1b9-4afd-81d0-88fc1f1a7f9b}">
<Declaration><![CDATA[METHOD M_Held
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Holding" Id="{519b03b3-2409-4b45-818f-535b3e16b22e}">
<Declaration><![CDATA[METHOD M_Holding
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Idle" Id="{aa784f5c-7adf-4c9f-a414-65b10afd2772}">
<Declaration><![CDATA[METHOD M_Idle
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Resetting" Id="{4050ed6f-edbe-4c3e-ac42-919a37a47ea9}">
<Declaration><![CDATA[METHOD M_Resetting
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Starting" Id="{0059e7f6-5f2a-40e4-9d9b-652f221495a9}">
<Declaration><![CDATA[METHOD M_Starting
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_StateComplete" Id="{0cf3625e-8009-4108-a9f4-d98c991f9930}">
<Declaration><![CDATA[METHOD M_StateComplete
]]></Declaration>
<Implementation>
<ST><![CDATA[_fbStateMachine.M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Stopped" Id="{9f8a09cf-f3be-4d60-b5e4-cd9572fae88c}">
<Declaration><![CDATA[METHOD M_Stopped
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Stopping" Id="{193565ef-cf20-428c-b726-e7c1b61375c5}">
<Declaration><![CDATA[METHOD M_Stopping
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Suspended" Id="{222c3ad7-f7d5-4773-8e98-863345472053}">
<Declaration><![CDATA[METHOD M_Suspended
]]></Declaration>
<Implementation>
<ST><![CDATA[]]></ST>
</Implementation>
</Method>
<Method Name="M_Suspending" Id="{0f5d52e2-2a54-4ea9-a0c4-7f08229c4f21}">
<Declaration><![CDATA[METHOD M_Suspending
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Unholding" Id="{662dd054-329b-4e57-ba77-486f92af795a}">
<Declaration><![CDATA[METHOD M_Unholding
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
<Method Name="M_Unsuspending" Id="{80fb11c4-916a-4f8f-9cf9-b9a2d51524a1}">
<Declaration><![CDATA[METHOD M_Unsuspending
]]></Declaration>
<Implementation>
<ST><![CDATA[M_StateComplete();]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,244 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_PackMLStateMachine" Id="{784ceb84-1721-424f-89d1-422a24198e57}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_PackMLStateMachine
VAR_INPUT
eMode : E_PackMLUnitMode;
eCmd : E_PackMLCmd;
END_VAR
VAR_OUTPUT
eState : E_PackMLState;
eCurrentMode : E_PackMLUnitMode;
xError : BOOL;
END_VAR
VAR
// Internal mode
_eMode : E_PackMLUnitMode;
// Internal state
_eState : E_PackMLState;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Check for mode switch
IF eMode <> _eMode THEN
// Only allow mode switch in stopped state
// or in aborted state when target mode ist manual mode
IF (_eState = E_PackMLState.STOPPED) OR (_eState = E_PackMLState.ABORTED AND eMode = E_PackMLUnitMode.MANUAL) THEN
_eMode := eMode;
END_IF
END_IF
// Base state machine
CASE _eState OF
E_PackMLState.STOPPING:
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.STOPPED:
IF eCmd = E_PackMLCmd.RESET THEN
_eState := E_PackMLState.RESETTING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.RESETTING:
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.IDLE:
IF eCmd = E_PackMLCmd.START THEN
_eState := E_PackMLState.STARTING;
END_IF
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.STARTING:
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.EXECUTE:
IF eCmd = E_PackMLCmd.SUSPEND THEN
_eState := E_PackMLState.SUSPENDING;
END_IF
IF eCmd = E_PackMLCmd.HOLD THEN
_eState := E_PackMLState.HOLDING;
END_IF
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.SUSPENDING:
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.SUSPENDED:
IF eCmd = E_PackMLCmd.UNSUSPEND THEN
_eState := E_PackMLState.UNSUSPENDING;
END_IF
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.UNSUSPENDING:
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.HOLDING:
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.HELD:
IF eCmd = E_PackMLCmd.UNHOLD THEN
_eState := E_PackMLState.UNHOLDING;
END_IF
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.UNHOLDING:
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.COMPLETING:
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.COMPLETE:
IF eCmd = E_PackMLCmd.RESET THEN
_eState := E_PackMLState.RESETTING;
END_IF
IF eCmd = E_PackMLCmd.STOP THEN
_eState := E_PackMLState.STOPPING;
END_IF
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
E_PackMLState.ABORTED:
IF eCmd = E_PackMLCmd.CLEAR THEN
_eState := E_PackMLState.CLEARING;
END_IF
E_PackMLState.CLEARING:
IF eCmd = E_PackMLCmd.ABORT THEN
_eState := E_PackMLState.ABORTING;
END_IF
ELSE
;
END_CASE
// Copy internal state value to fb output
eState := _eState;
eCurrentMode := _eMode;]]></ST>
</Implementation>
<Method Name="M_StateComplete" Id="{e2f1bae5-5059-4baa-8ba2-8dfa58d439e5}">
<Declaration><![CDATA[METHOD M_StateComplete
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[CASE _eState OF
E_PackMLState.STOPPING:
_eState := E_PackMLState.STOPPED;
E_PackMLState.RESETTING:
_eState := E_PackMLState.IDLE;
E_PackMLState.STARTING:
_eState := E_PackMLState.EXECUTE;
E_PackMLState.EXECUTE:
_eState := E_PackMLState.COMPLETING;
E_PackMLState.SUSPENDING:
_eState := E_PackMLState.SUSPENDED;
E_PackMLState.UNSUSPENDING:
_eState := E_PackMLState.EXECUTE;
E_PackMLState.HOLDING:
_eState := E_PackMLState.HELD;
E_PackMLState.UNHOLDING:
_eState := E_PackMLState.EXECUTE;
E_PackMLState.COMPLETING:
_eState := E_PackMLState.COMPLETE;
E_PackMLState.ABORTING:
_eState := E_PackMLState.ABORTED;
E_PackMLState.CLEARING:
_eState := E_PackMLState.STOPPED;
END_CASE
eState := _eState;]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<Itf Name="I_UnitState" Id="{cdb705eb-8c7b-4a1b-b75d-2d038b2142ed}">
<Declaration><![CDATA[INTERFACE I_UnitState
]]></Declaration>
<Method Name="M_Aborted" Id="{60879075-982d-46e3-879f-28a027152492}">
<Declaration><![CDATA[METHOD M_Aborted
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Aborting" Id="{a7f0b039-d3ad-461a-85a2-ba36dbff9c79}">
<Declaration><![CDATA[METHOD M_Aborting
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Clearing" Id="{6299cd97-9cf1-4270-94b0-c0bcc4e1099d}">
<Declaration><![CDATA[METHOD M_Clearing
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Complete" Id="{b3cf5b7a-9a5a-43fd-b325-d4fd150ef337}">
<Declaration><![CDATA[METHOD M_Complete
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Completing" Id="{7c1cb77d-7ca4-41f6-bf62-9389baa6ee7f}">
<Declaration><![CDATA[METHOD M_Completing
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Execute" Id="{03ab6d64-3e16-414d-9136-f9b18ea617be}">
<Declaration><![CDATA[METHOD M_Execute
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Held" Id="{68deb94e-e48b-464f-9c76-8d9ed1bf2546}">
<Declaration><![CDATA[METHOD M_Held
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Holding" Id="{559633b5-914c-40d3-8d33-7376565527fb}">
<Declaration><![CDATA[METHOD M_Holding
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Idle" Id="{67e5973f-2505-422d-bb50-93ce0b57a267}">
<Declaration><![CDATA[METHOD M_Idle
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Resetting" Id="{d1009681-05ba-46d8-97a6-e3edaa95ef55}">
<Declaration><![CDATA[METHOD M_Resetting
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Starting" Id="{a747e482-f90e-45e5-98dc-79e29c5eb846}">
<Declaration><![CDATA[METHOD M_Starting
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Stopped" Id="{4639d90c-8eac-499e-a39a-e21317512d84}">
<Declaration><![CDATA[METHOD M_Stopped
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Stopping" Id="{81d1ced0-30b6-4a0e-b4f0-f2f5159fb0a2}">
<Declaration><![CDATA[METHOD M_Stopping
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Suspended" Id="{d84aeac6-2d41-4eb9-bcab-6c5cf55f051b}">
<Declaration><![CDATA[METHOD M_Suspended
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Suspending" Id="{74fa6a0f-a468-4665-8e53-35af4d69eb0e}">
<Declaration><![CDATA[METHOD M_Suspending
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Unholding" Id="{2cbdd1fc-df75-4e65-b402-0f80d7393bf2}">
<Declaration><![CDATA[METHOD M_Unholding
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Unsuspending" Id="{b50ba50d-d8d9-4340-8bf8-95a965e5f0da}">
<Declaration><![CDATA[METHOD M_Unsuspending
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
</Itf>
</TcPlcObject>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<Itf Name="I_UnitStateActing" Id="{c702df5f-1a22-4aea-b488-0fb9e9d6d715}">
<Declaration><![CDATA[INTERFACE I_UnitStateActing
]]></Declaration>
<Method Name="M_Aborting" Id="{7c2f68db-46da-431c-ae3a-645172f1883b}">
<Declaration><![CDATA[METHOD M_Aborting
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Clearing" Id="{9d54d966-edc5-4f21-bd4e-93594fa24900}">
<Declaration><![CDATA[METHOD M_Clearing
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Completing" Id="{58605d4f-0a0c-4fdd-9d50-28facf47e281}">
<Declaration><![CDATA[METHOD M_Completing
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Execute" Id="{ab83a18f-a5bc-4b8f-b1f3-7186449d2761}">
<Declaration><![CDATA[METHOD M_Execute
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Holding" Id="{75e803d4-1308-483e-b7e2-17e7d4b226d0}">
<Declaration><![CDATA[METHOD M_Holding
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Resetting" Id="{0e18ccba-b77b-4b73-8769-7ee43b60219b}">
<Declaration><![CDATA[METHOD M_Resetting
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Starting" Id="{58fc3d45-f33e-4dd2-bcd8-33e9912df38b}">
<Declaration><![CDATA[METHOD M_Starting
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Stopping" Id="{2552a9a7-c44e-4a0f-b543-d0ead71abcad}">
<Declaration><![CDATA[METHOD M_Stopping
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Suspending" Id="{4a4db317-bf30-420e-8759-cbe6735e3cbf}">
<Declaration><![CDATA[METHOD M_Suspending
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Unholding" Id="{0552e45c-941b-4643-88d7-3142a7e014c8}">
<Declaration><![CDATA[METHOD M_Unholding
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Unsuspending" Id="{9b9d5dbc-614c-4f59-9357-18a6be86205d}">
<Declaration><![CDATA[METHOD M_Unsuspending
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
</Itf>
</TcPlcObject>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<Itf Name="I_UnitStateWaiting" Id="{39625219-05f8-4347-91c2-8778ac2bbe52}">
<Declaration><![CDATA[INTERFACE I_UnitStateWaiting
]]></Declaration>
<Method Name="M_Aborted" Id="{e9883017-eee3-45b6-a539-97564bed85bd}">
<Declaration><![CDATA[METHOD M_Aborted
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Complete" Id="{e5ea1a66-0ad7-44f0-8155-f8f6e9fb0869}">
<Declaration><![CDATA[METHOD M_Complete
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Held" Id="{22f78e55-8e74-4d03-b949-ddbec289c616}">
<Declaration><![CDATA[METHOD M_Held
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Idle" Id="{a4192dfa-4513-4296-9d67-360bb2fdd051}">
<Declaration><![CDATA[METHOD M_Idle
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Stopped" Id="{8609190c-90f0-46f9-b5b0-5dddabdfa3b1}">
<Declaration><![CDATA[METHOD M_Stopped
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
<Method Name="M_Suspended" Id="{eeb60c98-c52b-43d3-9d93-2abce6744a61}">
<Declaration><![CDATA[METHOD M_Suspended
VAR_INPUT
END_VAR
]]></Declaration>
</Method>
</Itf>
</TcPlcObject>

View File

@@ -0,0 +1,569 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_PackMLStateMachine_Test" Id="{6fbfd066-a6ec-4393-8e2f-9c56726e94be}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_PackMLStateMachine_Test EXTENDS FB_TestSuite
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Normal commands
M_InitialState();
M_StoppedToIdle();
M_IdleToExecute();
M_HoldUnholdCycle();
M_SuspendUnsuspendCycle();
M_ExecuteToComplete();
M_ResetFromComplete();
// Full cycle
M_FullProductionCycle();
// Stop tests
M_StopFromIdle();
M_StopFromExecute();
M_StopFromComplete();
// Abort tests
M_AbortFromExecute();
M_AbortDuringStarting();
M_AbortDuringHolding();
M_AbortDuringClearing();
// Clearing
M_ClearFromAborted();
// Mode switching
M_ModeSwitchInStopped();
M_ModeSwitchNotAllowedInIdle();
M_ModeSwitchAbortedToManual();
M_ModeSwitchAbortedToNonManualNotAllowed();
]]></ST>
</Implementation>
<Method Name="M_AbortDuringClearing" Id="{35f8c603-4e33-4f68-9e15-218d78d5c03b}">
<Declaration><![CDATA[METHOD M_AbortDuringClearing
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortDuringClearing');
// Setup: Get to CLEARING
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.CLEAR);
AssertEquals_DINT(E_PackMLState.CLEARING, fbPackML.eState, 'Setup: Should be CLEARING');
// Test ABORT during CLEARING
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should abort from CLEARING');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_AbortDuringHolding" Id="{aaa6bed5-41ed-40eb-8168-11c14ad58832}">
<Declaration><![CDATA[METHOD M_AbortDuringHolding
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortDuringHolding');
// Setup: Get to HOLDING
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.HOLD);
AssertEquals_DINT(E_PackMLState.HOLDING, fbPackML.eState, 'Setup: Should be HOLDING');
// Test ABORT during HOLDING
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should abort from HOLDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Should reach ABORTED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_AbortDuringStarting" Id="{fbb52ff0-3ecb-4984-be10-32efaf2d1f2b}">
<Declaration><![CDATA[METHOD M_AbortDuringStarting
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortDuringStarting');
// Setup: Get to STARTING
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
AssertEquals_DINT(E_PackMLState.STARTING, fbPackML.eState, 'Setup: Should be STARTING');
// Test ABORT during STARTING
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should abort from STARTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Should reach ABORTED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_AbortFromExecute" Id="{6eaecb2f-7c92-492a-8635-8d91354de462}">
<Declaration><![CDATA[METHOD M_AbortFromExecute
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('AbortFromExecute');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test ABORT
fbPackML(eCmd := E_PackMLCmd.ABORT);
AssertEquals_DINT(E_PackMLState.ABORTING, fbPackML.eState, 'Should transition to ABORTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Should transition to ABORTED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ClearFromAborted" Id="{672532be-23ab-4162-bb1f-60f23d043e3f}">
<Declaration><![CDATA[METHOD M_ClearFromAborted
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ClearFromAborted');
// Setup: Get to ABORTED
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Setup: Should be ABORTED');
// Test CLEAR
fbPackML(eCmd := E_PackMLCmd.CLEAR);
AssertEquals_DINT(E_PackMLState.CLEARING, fbPackML.eState, 'Should transition to CLEARING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ExecuteToComplete" Id="{d180915d-5230-4918-a72f-7d7b60cb333e}">
<Declaration><![CDATA[METHOD M_ExecuteToComplete
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ExecuteToComplete');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Setup: Should be in EXECUTE');
// Test completion
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETING, fbPackML.eState, 'Should transition to COMPLETING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Should transition to COMPLETE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_FullProductionCycle" Id="{e11b3300-6857-4b29-8000-595d07539eed}">
<Declaration><![CDATA[METHOD M_FullProductionCycle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('FullProductionCycle');
// STOPPED -> RESETTING -> IDLE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should reach IDLE');
// IDLE -> STARTING -> EXECUTE
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should reach EXECUTE');
// EXECUTE -> COMPLETING -> COMPLETE
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Should reach COMPLETE');
// COMPLETE -> RESETTING -> IDLE
fbPackML(eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should return to IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_HoldUnholdCycle" Id="{01b950b4-a901-4c0f-8993-5e8c46b75e11}">
<Declaration><![CDATA[METHOD M_HoldUnholdCycle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('HoldUnholdCycle');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test HOLD
fbPackML(eCmd := E_PackMLCmd.HOLD);
AssertEquals_DINT(E_PackMLState.HOLDING, fbPackML.eState, 'Should transition to HOLDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.HELD, fbPackML.eState, 'Should transition to HELD');
// Test UNHOLD
fbPackML(eCmd := E_PackMLCmd.UNHOLD);
AssertEquals_DINT(E_PackMLState.UNHOLDING, fbPackML.eState, 'Should transition to UNHOLDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should return to EXECUTE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_IdleToExecute" Id="{e39d1646-a140-445b-a77a-a4b3ecb6a68b}">
<Declaration><![CDATA[METHOD M_IdleToExecute
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('IdleToExecute');
// Setup: Get to IDLE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Setup: Should be IDLE');
// Test START command
fbPackML(eCmd := E_PackMLCmd.START);
AssertEquals_DINT(E_PackMLState.STARTING, fbPackML.eState, 'Should transition to STARTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should transition to EXECUTE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_InitialState" Id="{abbdf72f-ef98-4943-bd47-30822864724d}">
<Declaration><![CDATA[METHOD M_InitialState
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('InitialState');
AssertEquals_DINT(
Expected := E_PackMLState.STOPPED,
Actual := fbPackML.eState,
Message := 'Initial state should be STOPPED'
);
AssertEquals_DINT(
Expected := E_PackMLUnitMode.PRODUCTION,
Actual := fbPackML.eCurrentMode,
Message := 'Initial mode should be PRODUCTION'
);
AssertFalse(
Condition := fbPackML.xError,
Message := 'No error should be present initially'
);
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchAbortedToManual" Id="{16d80727-dea0-4822-8ac2-bb785dfb8fd9}">
<Declaration><![CDATA[METHOD M_ModeSwitchAbortedToManual
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchAbortedToManual');
// Setup: Get to ABORTED in PRODUCTION mode
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Setup: Should be ABORTED');
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should be PRODUCTION');
// Switch to MANUAL mode - should be allowed
fbPackML(eMode := E_PackMLUnitMode.MANUAL);
AssertEquals_DINT(E_PackMLUnitMode.MANUAL, fbPackML.eCurrentMode, 'Mode should switch to MANUAL');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchAbortedToNonManualNotAllowed" Id="{814f1869-6786-43ba-944f-eec48a900610}">
<Declaration><![CDATA[METHOD M_ModeSwitchAbortedToNonManualNotAllowed : REFERENCE TO FB_Test
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchAbortedToNonManualNotAllowed');
// Setup: Get to ABORTED in PRODUCTION mode
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.ABORT);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.ABORTED, fbPackML.eState, 'Setup: Should be ABORTED');
// Try to switch to MAINTENANCE - should be rejected
fbPackML(eMode := E_PackMLUnitMode.MAINTENANCE);
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should remain PRODUCTION');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchInStopped" Id="{438c169a-3232-4ff5-8d39-6d4748bb8e0c}">
<Declaration><![CDATA[METHOD M_ModeSwitchInStopped
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchInStopped');
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION);
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should be in STOPPED');
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should be PRODUCTION');
// Mode switch should be accepted
fbPackML(eMode := E_PackMLUnitMode.MAINTENANCE);
AssertEquals_DINT(E_PackMLUnitMode.MAINTENANCE, fbPackML.eCurrentMode, 'Mode should switch to MAINTENANCE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ModeSwitchNotAllowedInIdle" Id="{a1275023-bc44-4cde-b6cb-9ba394083234}">
<Declaration><![CDATA[METHOD M_ModeSwitchNotAllowedInIdle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ModeSwitchNotAllowedInIdle');
// Setup: Get to IDLE in PRODUCTION mode
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Setup: Should be in IDLE');
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should be PRODUCTION');
// Try to switch mode - should be rejected
fbPackML(eMode := E_PackMLUnitMode.MANUAL);
AssertEquals_DINT(E_PackMLUnitMode.PRODUCTION, fbPackML.eCurrentMode, 'Mode should remain PRODUCTION');
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should remain in IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_ResetFromComplete" Id="{cbdb2a33-12a7-489c-a968-e416c0488e4f}">
<Declaration><![CDATA[METHOD M_ResetFromComplete
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('ResetFromComplete');
// Setup: Get to COMPLETE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Setup: Should be COMPLETE');
// Test RESET from COMPLETE
fbPackML(eCmd := E_PackMLCmd.RESET);
AssertEquals_DINT(E_PackMLState.RESETTING, fbPackML.eState, 'Should transition to RESETTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should transition to IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StopFromComplete" Id="{6f2c0387-41ef-426f-869c-ddae93a70046}">
<Declaration><![CDATA[METHOD M_StopFromComplete
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StopFromComplete');
// Setup: Get to COMPLETE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.COMPLETE, fbPackML.eState, 'Setup: Should be COMPLETE');
// Test STOP from COMPLETE
fbPackML(eCmd := E_PackMLCmd.STOP);
AssertEquals_DINT(E_PackMLState.STOPPING, fbPackML.eState, 'Should transition to STOPPING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StopFromExecute" Id="{2399ead6-3273-4524-990f-02be84126c6a}">
<Declaration><![CDATA[METHOD M_StopFromExecute
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StopFromExecute');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test STOP from EXECUTE
fbPackML(eCmd := E_PackMLCmd.STOP);
AssertEquals_DINT(E_PackMLState.STOPPING, fbPackML.eState, 'Should transition to STOPPING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StopFromIdle" Id="{15984370-8f4c-4823-af08-97c9f70546cd}">
<Declaration><![CDATA[METHOD M_StopFromIdle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StopFromIdle');
// Setup: Get to IDLE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
// Test STOP from IDLE
fbPackML(eCmd := E_PackMLCmd.STOP);
AssertEquals_DINT(E_PackMLState.STOPPING, fbPackML.eState, 'Should transition to STOPPING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should transition to STOPPED');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_StoppedToIdle" Id="{4e29286e-7cd6-4d2e-89db-08104750a1c6}">
<Declaration><![CDATA[METHOD M_StoppedToIdle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('StoppedToIdle');
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION);
AssertEquals_DINT(E_PackMLState.STOPPED, fbPackML.eState, 'Should be in STOPPED');
fbPackML(eCmd := E_PackMLCmd.RESET);
AssertEquals_DINT(E_PackMLState.RESETTING, fbPackML.eState, 'Should transition to RESETTING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.IDLE, fbPackML.eState, 'Should transition to IDLE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
<Method Name="M_SuspendUnsuspendCycle" Id="{78311aa6-53b9-4c6e-8c1c-a43729a514d1}">
<Declaration><![CDATA[METHOD M_SuspendUnsuspendCycle
VAR
fbPackML : FB_PackMLStateMachine;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TEST('SuspendUnsuspendCycle');
// Setup: Get to EXECUTE
fbPackML(eMode := E_PackMLUnitMode.PRODUCTION, eCmd := E_PackMLCmd.RESET);
fbPackML.M_StateComplete();
fbPackML(eCmd := E_PackMLCmd.START);
fbPackML.M_StateComplete();
// Test SUSPEND
fbPackML(eCmd := E_PackMLCmd.SUSPEND);
AssertEquals_DINT(E_PackMLState.SUSPENDING, fbPackML.eState, 'Should transition to SUSPENDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.SUSPENDED, fbPackML.eState, 'Should transition to SUSPENDED');
// Test UNSUSPEND
fbPackML(eCmd := E_PackMLCmd.UNSUSPEND);
AssertEquals_DINT(E_PackMLState.UNSUSPENDING, fbPackML.eState, 'Should transition to UNSUSPENDING');
fbPackML.M_StateComplete();
AssertEquals_DINT(E_PackMLState.EXECUTE, fbPackML.eState, 'Should return to EXECUTE');
TEST_FINISHED();]]></ST>
</Implementation>
</Method>
</POU>
</TcPlcObject>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="PRG_Test" Id="{f876543c-d362-446e-a091-152833fd4557}" SpecialFunc="None">
<Declaration><![CDATA[PROGRAM PRG_Test
VAR
_fbPackMLStateMachine_Test : FB_PackMLStateMachine_Test;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[TcUnit.RUN();]]></ST>
</Implementation>
</POU>
</TcPlcObject>