Module Interface

Module_Interface_typ is used by a module to interface with the machine object and control state.

Direction Name Type Description
In ModuleName String[80] Name of piper module, for user interface
In ModuleStatus String[80] Description of module status, for user interface
OUT PiperState MACH_ST_enum Current Piper State
OUT PiperSubState DINT Current Piper SubState
In ModuleResponse MACH_ST_enum Module’s response. Respond with current state for DONE. This will be cyclically populated by Piper with MACH_ST_NOT_READY if Module did not respond with current PiperState. Respond with MACH_ST_ERROR to command machine to abort. Any other response will be treated as MACH_ST_NOT_READY
In ModuleSubStateRequest DINT Request SubState
IN ModuleBypass Bool Request module to be bypassed
OUT ModuleIsBypass Bool Module is being bypassed

Responses

Modules can respond with “done”, “busy”, “error”, “request substate”, “bypass”.

Done

Repsonding with “done” will tell Machine that Module has completed all actions required with the corresponding state. A Module can change from a “done” response to a “busy” response if needed. Each module should respond with “done” in all states (except MACH_ST_BYPASS) when the Module is completed with operations in that state.

To respond with done set ModuleResponse to current PiperState.

// Handle any machine states that this module needs to respond to
CASE ModuleInterface.PiperState OF

    MACH_ST_STARTING:
        myFub.execute := TRUE; // Start fub execution

        // Module is done
        ModuleInterface.ModuleResponse := ModuleInterface.PiperState;

    ELSE
        myFub.execute := FALSE; // Reset fub enable

        // Immediately respond with done in states that are not handled by this Module
		ModuleInterface.ModuleResponse := ModuleInterface.PiperState;

END_CASE

myFub(); // Call fub

Busy

Responding with “busy” will tell Machine that Module is busy with current state and prevent Machine from moving forward. Note: This does not prevent Machine commands such as ABORT and has no effect in Wait states.

To respond with busy set ModuleResponse to MACH_ST_NOT_READY. Responding with anything other than the handled responses will be treated as a busy responses.

CASE ModuleInterface.PiperState OF

    MACH_ST_STARTING:
        myFub.execute := TRUE; // Start fub execution

        IF myFub.done THEN
            // Module is done
            ModuleInterface.ModuleResponse := ModuleInterface.PiperState;
        ELSE
            // Module is busy
            ModuleInterface.ModuleResponse := MACH_ST_NOT_READY;
        END_IF

    ELSE
        myFub.execute := FALSE; // Reset fub enable

        // Immediately respond with done in states that are not handled by this Module
		ModuleInterface.ModuleResponse := ModuleInterface.PiperState;

END_CASE

myFub(); // Call fub

Error

Responding with “error” will tell Machine that Module has an error occur that requires Machine to ABORT. This is similar to commanding a gMachine.IN.CMD.Abort with the error Module is recorded by Piper.

To respond with error set ModuleResponse to MACH_ST_ERROR.

CASE ModuleInterface.PiperState OF

    MACH_ST_STARTING:
        myFub.execute := TRUE; // Start fub execution

        IF myFub.error THEN
            // Module has an error
            ModuleInterface.ModuleResponse := MACH_ST_ERROR;
        ELSEIF myFub.done THEN
            // Module is done
            ModuleInterface.ModuleResponse := ModuleInterface.PiperState;
        ELSE
            // Module is busy
            ModuleInterface.ModuleResponse := MACH_ST_NOT_READY;
        END_IF

    ELSE
        myFub.execute := FALSE; // Reset fub enable

        // Immediately respond with done in states that are not handled by this Module
		ModuleInterface.ModuleResponse := ModuleInterface.PiperState;

END_CASE

myFub(); // Call fub

Request Substate

Requesting a substate tells the Machine that Module requires that substate in this state. Machine will cycle through requested substates in order and will not move to the next substate until all Modules have responded with “done” or “request substate”. Requesting substates with values less than or equal to PiperSubState will be ignored. Example: Requesting substate 1 while in substate 2 is not allowed and will be ignored.

To request a substate set ModuleSubStateRequest to the request substate value while responding with Busy.

CASE ModuleInterface.PiperState OF

    MACH_ST_STARTING:
        CASE ModuleInterface.PiperSubState OF

            SUB_STATE_INIT: // substate 0
                IF Configuration.enable THEN
                    // Request substate 1
                    Module.ModuleInterface.ModuleSubStateRequest := SUB_STATE_MY_SUBSTATE;
                ELSE
                    // Module is done - No operation needed
                    ModuleInterface.ModuleResponse := ModuleInterface.PiperState;
                END_IF

            SUB_STATE_MY_SUBSTATE: // substate 1
                myFub.execute := TRUE; // Start fub execution
                IF myFub.error THEN
                    // Module has an error
                    ModuleInterface.ModuleResponse := MACH_ST_ERROR;
                ELSEIF myFub.done THEN
                    // Module is done
                    ModuleInterface.ModuleResponse := ModuleInterface.PiperState;
                ELSE
                    // Module is busy
                    ModuleInterface.ModuleResponse := MACH_ST_NOT_READY;
                END_IF

        END_CASE

    ELSE
        myFub.execute := FALSE; // Reset fub enable

        // Immediately respond with done in states that are not handled by this Module
		ModuleInterface.ModuleResponse := ModuleInterface.PiperState;

END_CASE

myFub(); // Call fub

Bypass

Requesting to be bypassed tells the Machine to not wait and ignore Module’s response. A Module can request not to be bypassed at any point but this shouldn’t be relied on for time sensitive operations as it may take several cycles before Module is no longer bypassed.

CASE ModuleInterface.PiperState OF

    MACH_ST_STARTING:
        myFub.execute := TRUE; // Start fub execution

        IF myFub.error THEN
            // Module has an error
            ModuleInterface.ModuleResponse := MACH_ST_ERROR;
        ELSEIF myFub.done THEN
            // Module is done
            ModuleInterface.ModuleResponse := ModuleInterface.PiperState;
        ELSE
            // Module is busy
            ModuleInterface.ModuleResponse := MACH_ST_NOT_READY;
        END_IF

    MACH_ST_BYPASSED:
        myFub.execute := FALSE; // Reset fub enable

        // Request to stop bypass if configuration gets enabled
        IF Configuration.enable THEN
            Module.ModuleInterface.ModuleBypass := FALSE;
        END_IF

    ELSE
        myFub.execute := FALSE; // Reset fub enable

        // Request bypass if configuration is disabled
        IF NOT Configuration.enable THEN
            Module.ModuleInterface.ModuleBypass := TRUE;
        END_IF

        // Immediately respond with done in states that are not handled by this Module
		ModuleInterface.ModuleResponse := ModuleInterface.PiperState;

END_CASE

myFub(); // Call fub

Tips

Performing operations once

To have an operation run once per entering a state you can check ModuleResponse.

// Handle any machine states that this module needs to respond to
CASE ModuleInterface.PiperState OF

    MACH_ST_STARTING:
        IF ModuleInterface.ModuleResponse <> ModuleInterface.PiperState THEN
            // TODO: Add any code to run once per Machine entering MACH_ST_STARTING
            //      Such as myFub.execute := TRUE;
            ModuleInterface.ModuleResponse := ModuleInterface.PiperState;
        END_IF

    ELSE
        // Immediately respond with done in states that are not handled by this Module
		ModuleInterface.ModuleResponse := ModuleInterface.PiperState;

END_CASE

myFub(); // Call fub
myFub.execute := FALSE; // Reset fub enable