Coordinate multiple stations on an automated production line with deterministic Master-Slave Handshaking and zone interlocks.
In complex automated assembly lines, machines consist of decoupled stations (e.g. Infeed Feeder, Pick-and-Place Gantry, Machining/Press Station, Outfeed Check).
Directly coupling stations into a single monolithic sequence leads to deadlocks and maintenance nightmares. The proven industrial pattern uses Decoupled Station Sequences coordinated by explicit handshake flags:
bReq_Start: Master requests station to begin processing.bAck_Busy: Station acknowledges execution and signals ongoing work.bDone_PartReady: Station signals successful completion and part readiness.bZone_Clear: Transfer interlock confirming the shared workspace is vacated.+----------------+ bReq_Start +----------------+
| | -------------------> | |
| MASTER LINE | | STATION 1 |
| CONTROLLER | <------------------- | (FEEDER) |
| | bDone_PartReady | |
+----------------+ +----------------+
|
| bReq_Start +----------------+
+-----------------------------> | |
| STATION 2 |
<----------------------------- | (PICK & PLACE) |
bDone_PartReady +----------------+
A robust 4-way handshake prevents race conditions between line cycles:
bReq_Start_Stn1 = TRUE when upstream conditions and safety permits.bAck_Busy_Stn1 = TRUE, and executes its local Grafcet.bDone_PartReady_Stn1 = TRUE and resets bAck_Busy_Stn1 = FALSE.bDone_PartReady_Stn1, records part transfer, and resets bReq_Start_Stn1 = FALSE.bDone_PartReady_Stn1 = FALSE upon seeing bReq_Start_Stn1 = FALSE, returning to initial state.Open station_pick_place.seq to define the subordinate sequence.
from automation_machine import Sequence, StepType
class StationPickAndPlace(Sequence):
def setup(self):
s0 = self.add_step(StepType.INITIAL, name="Wait_For_Master_Req")
s1 = self.add_step(name="Process_Cycle")
s2 = self.add_step(name="Signal_Completion")
s3 = self.add_step(name="Wait_Master_Handshake_Clear")
self.add_transition(s0, s1, condition="bReq_Start_Stn2 AND bZone_Clear_Stn2")
self.add_transition(s1, s2, condition="bPart_Transferred")
self.add_transition(s2, s3, condition="NOT bReq_Start_Stn2")
self.add_transition(s3, s0, condition="NOT bDone_PartReady_Stn2")
s1.add_action("bAck_Busy_Stn2", "Station working")
s2.add_action("bDone_PartReady_Stn2", "Station complete")
When two stations share physical airspace (e.g., an infeed conveyor and a robot arm), use boolean zone tokens:
Condition to enter zone: bZone_Clear_Shared AND NOT bRobot_In_Shared_Zone
Action entering zone: SET bRobot_In_Shared_Zone
Action leaving zone: RESET bRobot_In_Shared_Zone
bReq_Start_Stn2 = TRUE and bZone_Clear_Stn2 = TRUE.Wait_For_Master_Req to Process_Cycle.bPart_Transferred = TRUE.bDone_PartReady_Stn2 latches on, and releases properly when the master clears bReq_Start_Stn2.