PLC Programming SAPLC ProgrammingSOUTH AFRICA

exercises · South Africa

PLC sorting program example: sort by height

A PLC sorting program example: two photoeyes classify carton height, a latched flag tracks the box to a diverter, and a TP fires the pusher. Ladder and ST.

Difficulty: advanced · 60–90 minutes

This is a build-along exercise, not a reading page. You get a short job card of the kind a contractor actually receives, an I/O table to wire against, and a worked solution to check yourself with once your own version runs — plus the test sequence that proves it, because a program you haven't tried to break is a program you haven't tested. Sketch first, build second, test third. Same order as on site.

Open the simulator and build along →

The job card

Job card: a parcel depot in Germiston feeds mixed cartons down one belt. Tall cartons (double-stacked returns) must divert to a second belt before the strapping machine, which only accepts the low profile. At the gauge point two photoeyes sit one above the other: every carton breaks the low eye; only tall cartons break the high eye as well. The pneumatic pusher sits 600 mm downstream at its own detection eye. Classify each carton at the gauge point, remember the verdict while the carton travels, and fire the pusher for 0.8 seconds when a tall one arrives at the divert position. The belt runs at fixed speed and cartons are spaced at least 400 mm apart by an upstream metering belt — one carton between gauge and diverter at a time, for now.

Read it the way a foreman hands it to you. Every requirement on that card is a test case: when you think the program is done, walk the card line by line and force each condition in the watch table. Any line without a matching test you actually ran means you're not done yet. That habit — card in one hand, watch table in the other — is what separates a programmer who commissions clean from one who gets the call-back at month end.

I/O assignment

Wire your simulator project to this table exactly. Half the value of an exercise like this is tag discipline: name the points the same way the table does and the solution steps further down will read straight onto your rungs without translation.

TagTypeAddressPurpose
StartPBDI%I0.0Belt start pushbutton, normally open, momentary.
StopPBDI%I0.1Belt stop pushbutton, normally closed, wired fail-safe. TRUE = healthy.
EyeLowDI%I0.2Lower gauge photoeye, beam at 50 mm. TRUE while any carton blocks it.
EyeHighDI%I0.3Upper gauge photoeye, beam at 300 mm. TRUE only while a tall carton blocks it.
EyeDivertDI%I0.4Photoeye at the divert position, TRUE while a carton sits in front of the pusher.
ConveyorRunDO%Q0.0Main belt contactor.
PusherDO%Q0.1Pneumatic pusher solenoid; extend while energised, spring return.

A note on the Type column: DI is a digital input, DO a digital output, AI and AO are analogue in and out, and M is an internal memory bit that never leaves the CPU. The addresses use IEC notation (%I, %Q, %M). If your head is in Allen-Bradley land, map %I0.0 to I:0/0 and carry on — the logic doesn't change, only the spelling of the addresses.

Think before you build

Don't open the ladder editor yet. The notes below are the design decisions that determine whether your program works first time or fights you for an hour. Read them, then sketch the rung shapes on paper. Pencil and the back of a delivery note is fine — most working programs start exactly there.

  • Classify on an edge, decide once, latch the verdict. The high eye must be sampled while the carton is in the gauge — the clean trigger is the rising edge of the low eye plus a short settling delay, or the falling edge (carton leaving) with the high-eye reading latched during transit. Decide-once beats polling: a carton with a torn flap waving at the high eye gets one verdict, not forty.
  • The latched TallFlag is the tracking mechanism for the single-carton case. The flag set at the gauge is consumed by the first carton to reach the divert eye — valid only because the metering belt guarantees one carton in transit. Write that assumption down; it is the first thing that breaks when production speeds up.
  • Sample the high eye at the moment the low eye clears, not the moment it blocks. The leading edge of a tall carton's lid may sag below the top beam for the first 100 mm of travel; integrating the high eye over the whole gauge transit (did it EVER block?) is the honest measurement.

Step-by-step solution

Build one rung at a time and test after every rung. Never write the whole program and then test the lot — when five rungs go in untested and the machine misbehaves, you're debugging five suspects instead of one. The steps below follow that order. In the pseudo-rungs, ] [ is a normally-open examine, ]/[ is normally-closed, and ( ) is the output coil.

Rung 1: the belt

Plain seal-in for ConveyorRun with StartPB, StopPB — the same first rung as the conveyor exercise, here just the stage the sorting plays on. All sorting logic below is gated by the belt running, because a verdict latched while the belt is stopped belongs to a carton that has not moved.

// ──┬──[ ]StartPB──┬──[ ]StopPB──( )ConveyorRun
//   └──[ ]ConveyorRun─┘

Rung 2: accumulate the height reading in the gauge

While EyeLow is blocked, any TRUE on EyeHigh sets a SeenHigh bit — a latch that integrates the high eye over the whole transit, so a sagging lid or a late-rising flap still registers. SeenHigh resets when a new carton enters the gauge (rising edge of EyeLow).

// rGauge(CLK := EyeLow)  // new carton entering
// rGauge.Q ──(R)SeenHigh
// EyeLow AND EyeHigh ──(S)SeenHigh

Rung 3: latch the verdict as the carton leaves the gauge

On the falling edge of EyeLow (carton fully past the gauge), copy SeenHigh into TallFlag. From this scan until the divert eye, TallFlag is the carton's identity. Note the order dependency: the verdict copies on exit so a short carton following a tall one cannot inherit a stale SeenHigh.

// fGauge(CLK := EyeLow)  // F_TRIG, carton leaving
// fGauge.Q AND SeenHigh ──(S)TallFlag
// fGauge.Q AND NOT SeenHigh ──(R)TallFlag

Rung 4: fire the pusher at the divert eye

When EyeDivert sees a carton AND TallFlag is set, trigger a TP (pulse timer) of T#800ms on the Pusher output and reset TallFlag in the same breath — the verdict is consumed. A short carton at the divert eye with TallFlag clear sails past untouched. The TP guarantees a full-length push even though the eye clears as the carton leaves the belt.

// rDivert(CLK := EyeDivert AND TallFlag)
// rDivert.Q ──[TP tPush, PT := T#800ms] ── tPush.Q drives Pusher
// rDivert.Q ──(R)TallFlag

Test with carton sequences, not single cartons

One tall carton: verdict latches, pusher fires 0.8 s at the divert eye. One short: nothing fires. Now sequences — tall then short: the short one must NOT be pushed (stale-flag check). Short then tall: the tall one must be pushed. A tall carton with the high eye flickering (force 50 ms blips): still classified tall. Stop the belt with a verdict in flight, restart: the verdict must survive and the right carton must still divert. Finally block the divert eye with no flag set and confirm the pusher stays home.

The structured text version

The same logic in IEC 61131-3 structured text — each output written as a boolean equation you can read aloud.

(* Height sorting with verdict latch, IEC 61131-3 ST *)
ConveyorRun := (StartPB OR ConveyorRun) AND StopPB;
rGauge(CLK := EyeLow);
fGauge(CLK := NOT EyeLow); (* rising edge of NOT = carton left *)
IF rGauge.Q THEN SeenHigh := FALSE; END_IF;
IF EyeLow AND EyeHigh THEN SeenHigh := TRUE; END_IF;
IF fGauge.Q THEN TallFlag := SeenHigh; END_IF;
rDivert(CLK := EyeDivert AND TallFlag);
IF rDivert.Q THEN TallFlag := FALSE; END_IF;
tPush(IN := rDivert.Q, PT := T#800ms); (* TP: fixed-width pulse *)
Pusher := tPush.Q;

Ladder wins this argument when an electrician has to fault-find your program at 02:00 with a multimeter mindset — the rung looks like the circuit diagram it replaced, and that familiarity is worth real money on a breakdown. ST starts winning when the pattern repeats: ten pumps with the same interlock shape is one ST function called ten times, where ladder hands you ten near-identical rungs to keep in sync by hand forever. Learn both. Build the exercise in ladder first, then write the ST version and confirm the two behave identically in the simulator. That translation skill — same logic, two languages — is exactly what technical interviews and commissioning work both test.

Common mistakes

Every mistake below comes from a real program: either one of ours from years back, or one we were called in to fix. Check your build against the list before you call the exercise done.

  • Wiring the pusher straight to EyeDivert AND EyeHigh. The two eyes are 600 mm apart — by the time a tall carton reaches the diverter, the gauge eyes are reading the NEXT carton, and the pusher hits short cartons that follow tall ones. The verdict must travel with the carton, hence the latch.
  • Sampling the high eye only on the low eye's rising edge. A tall carton with a sagging leading flap reads short for the first instant and classifies wrong; integrating over the whole gauge transit (the SeenHigh latch) reads the carton's true height.
  • Driving the pusher directly from the divert eye level for tall cartons. The eye clears as the carton starts moving sideways, the solenoid drops mid-push, and tall cartons end up jammed half-on the divert belt. The TP pulse gives a full push regardless of when the eye clears.
  • Forgetting to consume the verdict. TallFlag left set after a successful divert pushes every subsequent carton until a short one happens to clear it — reset the flag in the same scan that fires the pusher, and test the tall-then-short sequence explicitly.

Most of these share one root cause: the rung shape doesn't match the intent, so the program passes the obvious test and fails the edge case. That's why the solution steps force the edge cases deliberately instead of stopping at "it starts and it stops". Steal that habit for every program you write from here on.

Take it further

Got it working first time? Good — now make it earn its keep. Each extension below changes the spec the way a real client does: after you've finished. Treat each one as a fresh job card, and re-test the whole program afterwards, not just the new part. Regressions hide in the rungs you didn't touch.

  • Break the one-carton assumption: replace TallFlag with a small FIFO or shift register clocked by cartons leaving the gauge, so three cartons can be in transit with three queued verdicts — this is the real version of the exercise and a serious step up.
  • Add a divert-confirm eye on the reject belt and alarm if a commanded push produced no carton within 2 seconds — actuator feedback, the difference between commanding and knowing.
  • Add a counter pair (diverted vs passed, from the bottle-counting exercise) and a percentage calculation for the depot's daily report.

If you build even one extension, screenshot the finished rungs and keep them somewhere organised. A folder of working, tested exercise solutions is the start of a portfolio — and hiring engineers ask candidates to explain a rung far more often than they ask to see certificates.

Run this in the simulator

The sandbox on the free tier lets you build the core rungs of this advanced exercise yourself — no card details, no install, signed up and on a rung inside two minutes. The watch table is the part that matters here: force the inputs, watch the outputs, and run the test sequence from the solution steps against a live scan cycle instead of imagining it. To be straight about what's paid: the guided version of this exercise — graded checkpoints, feedback on every submission, plus the fault-injection variants that break your program the way a real plant does — sits in the curriculum on the Basic tier at USD 12 per month and Pro at USD 29 per month, alongside the wiring track, sensor school and cert packs. Training centres and engineering departments wanting this in a lab should look at the Teams tier (USD 199 per seat per year, minimum 5 seats); the training-centres page carries the institutional details and the contact form. If you're an individual learning the trade, prove the core rungs in the free sandbox first and decide whether the graded track is worth the money. And once this one runs clean, line up the next exercise a notch harder — the step up is where the skill gets built.

Start in the free sandbox →

Reference

plcprogramming.io simulator covers the background theory behind this exercise, and it's worth twenty minutes of your time after the build — theory sticks better once your hands have done the work. The languages used here are defined by the IEC 61131-3 standard from iec.ch, and your CPU vendor's manual remains the canonical source for how a specific controller executes them.

What we don't claim

This site is not SAQA-registered, not MerSETA-accredited, and not an NQF-registered qualification provider. Our completion certificates are course-level only — they describe what you covered, not an NQF Level X qualification. The CCST cert from ISA is the portable industry credential we recommend; we are not an ISA cert delivery partner either, but our cert packs are CCST-aligned. The exercise on this page is practice material written by working programmers: finishing it proves the skill to yourself and to the simulator's progress tracking, not to a regulator.

By PLC Programming SA · Last updated 2026-06-12