(* Conveyor Counters: CTU, CTD and CTUD Parts Buffer — Conveyor scene X1 = Start (N.O.) X2 = Stop (N.C., TRUE when not pressed) X3 = Left sensor (load end) X4 = Right sensor (drop-off end) X5 = Part Removed X6 = Reset Counts (click these two in the I/O panel) Y1 = Motor run Y2 = Direction (TRUE = reverse, towards the load end) Every arrival at the drop-off delivers one part to a buffer. The conveyor holds at the load end when the batch of 10 is done or the buffer is full (3). *) VAR ConveyorRun : BOOL; // sealed-in run request Reverse : BOOL; // direction latch HoldAtLoad : BOOL; // do not send another part Delivered : CTU; // parts delivered, batch of 10 Remaining : CTD; // parts left in the batch, counts down from 10 Buffer : CTUD; // parts waiting in the buffer END_VAR (* Seal-in — X2 is N.C., so it is TRUE until Stop is pressed *) ConveyorRun := (X1 OR ConveyorRun) AND X2; (* Direction — reverse at the drop-off, forward again at the load end *) IF ConveyorRun AND X4 THEN Reverse := TRUE; END_IF; IF ConveyorRun AND X3 THEN Reverse := FALSE; END_IF; (* CTU — counts every rising edge of X4. Q turns on at PV *) Delivered(CU := X4, R := X6, PV := 10); (* CTD — the IEC CTD has a load input: LD copies PV into CV, then each rising edge of CD counts down. Q turns on when CV reaches 0. Press Reset Counts (X6) once to load it. *) Remaining(CD := X4, LD := X6, PV := 10); (* CTUD — up on X4, down on X5, never below 0. QU = full, QD = empty *) Buffer(CU := X4, CD := X5, R := X6, PV := 3); (* Hold at the load end when the batch is done or the buffer is full *) HoldAtLoad := X3 AND (Delivered.Q OR Buffer.QU); Y1 := ConveyorRun AND NOT HoldAtLoad; Y2 := Reverse;