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