exercises · South Africa
Pedestrian crossing PLC program in ladder logic
Pedestrian crossing PLC program: request button latch, minimum-green hold-off, timed amber-red-walk sequence, ladder steps plus the complete ST version.
Difficulty: beginner · 20–40 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: the road between a Pinetown factory's main gate and its parking lot carries forklifts and bakkies all shift, and at shift change a few hundred people cross it. The safety committee has bought signal heads and a push-button bollard. The sequence: traffic normally has green and pedestrians a red man. A button press latches a request; traffic green holds for at least its minimum time, then amber for 3 seconds, then traffic red; the green man shows for 8 seconds; then back to traffic green, and the button must work again for the next person. Pressing the button fifty times must not make anything happen faster.
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.
| Tag | Type | Address | Purpose |
|---|---|---|---|
RequestPB | DI | %I0.0 | Pedestrian push button on the bollard, normally open, momentary. |
TrafficGreen | DO | %Q0.0 | Traffic signal green aspect. |
TrafficAmber | DO | %Q0.1 | Traffic signal amber aspect, 3-second phase. |
TrafficRed | DO | %Q0.2 | Traffic signal red aspect, covers the whole walk phase. |
WalkGreen | DO | %Q0.3 | Green man lamp, 8-second walk phase. |
WalkRed | DO | %Q0.4 | Red man lamp, on whenever the walk phase is not active. |
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.
- The request is a latched bit, set by the button edge and cleared only when the walk phase actually starts. The button is a request, not a command — the state machine decides when to act on it, which is what makes button-hammering harmless.
- A minimum-green timer stops the crossing from strangling traffic. If the last walk phase just ended, a new request waits out the remaining minimum green (10 seconds here) before the amber starts. Without it, a queue of pedestrians can hold traffic at red almost permanently.
- Traffic red must overlap the entire walk phase and the lamps must be decoded from one state variable, same as the traffic light exercise — a state machine where green man and traffic green can never coexist by construction.
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: latch the request
Set a Request bit on the rising edge of RequestPB; reset it in the rung where the state machine enters the walk phase. An R_TRIG edge contact matters here — a finger holding the button must be one request, not a request per scan.
// rReq(CLK := RequestPB)
// rReq.Q ──(S)Request
// entering WALK state ──(R)Request
Rung 2: minimum green before responding
TON tMinGreen runs whenever the state is TRAFFIC_GREEN, PT of T#10s. The transition out of green requires Request AND tMinGreen.Q. A request that arrives mid-green waits for the timer; a request that arrives later acts immediately because the timer finished long ago.
// (State=GREEN) ──[TON tMinGreen, PT := T#10s]
// (State=GREEN) AND Request AND tMinGreen.Q ── MOVE AMBER -> State
Rungs 3-5: amber, walk, and back to green
AMBER runs a 3-second TON then moves to WALK, clearing the Request latch as it goes. WALK holds traffic red and green man for 8 seconds, then returns to GREEN. Each state has exactly one timer and one exit — resist the urge to be clever with shared timers across states.
// (State=AMBER) ──[TON tAmber, T#3s] ── done: MOVE WALK -> State, (R)Request
// (State=WALK) ──[TON tWalk, T#8s] ── done: MOVE GREEN -> State
Rungs 6-8: decode the lamps
TrafficGreen on State=GREEN, TrafficAmber on State=AMBER, TrafficRed on State=WALK. WalkGreen on State=WALK, WalkRed on everything else. Five lamps, five comparison rungs, zero ways to show contradictory aspects.
// (State=GREEN) ──( )TrafficGreen
// (State=AMBER) ──( )TrafficAmber
// (State=WALK) ──( )TrafficRed
// (State=WALK) ──( )WalkGreen
// NOT (State=WALK) ──( )WalkRed
Test like an impatient pedestrian
Press the button once and time the full sequence: up to 10 s of remaining green, 3 s amber, 8 s walk, return to green. Then hammer the button twenty times during the walk phase — the system must finish, return to green, and serve exactly one more cycle (the hammering set one latch). Press the button during amber: it must be remembered for the next cycle, not extend the current one. Confirm the red man is lit during amber, not just during traffic green.
The structured text version
The same logic in IEC 61131-3 structured text — each output written as a boolean equation you can read aloud.
(* Pedestrian crossing, IEC 61131-3 ST *)
VAR CONSTANT GREEN := 0; AMBER := 1; WALK := 2; END_VAR
rReq(CLK := RequestPB);
IF rReq.Q THEN Request := TRUE; END_IF;
tMinGreen(IN := (State = GREEN), PT := T#10s);
tAmber(IN := (State = AMBER), PT := T#3s);
tWalk(IN := (State = WALK), PT := T#8s);
CASE State OF
GREEN: IF Request AND tMinGreen.Q THEN State := AMBER; END_IF;
AMBER: IF tAmber.Q THEN State := WALK; Request := FALSE; END_IF;
WALK: IF tWalk.Q THEN State := GREEN; END_IF;
END_CASE;
TrafficGreen := (State = GREEN);
TrafficAmber := (State = AMBER);
TrafficRed := (State = WALK);
WalkGreen := (State = WALK);
WalkRed := (State <> WALK);
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.
- Acting on the button level instead of latching a request. Someone leaning on the bollard button holds the crossing in a permanent cycle, and the fault report reads 'lights possessed at shift change'.
- No minimum green. Every press flips traffic to amber immediately, so at 17:00 the road never flows — the crossing works perfectly for each pedestrian and terribly for the plant.
- Clearing the request latch at the wrong moment. Clear it on button release and a press during the walk phase is lost; clear it never and one press gives endless cycles. Clear it exactly when the walk phase begins serving it.
- Skipping the all-red overlap thinking. Here amber leads straight to walk; on a real road you would add a 1-2 second all-red clearance before the green man so a bakkie caught by the amber clears the crossing first.
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.
- Add a flashing green-man phase for the last 3 seconds of the walk using the two-timer flasher from the beacon exercise, warning slow walkers the phase is ending.
- Add a buzzer output that pulses during the walk phase for visually impaired users, and a second request button on the far bollard wired in parallel — then think about what 'in parallel' means for fault-finding.
- Upgrade to the full two-direction traffic light exercise with this crossing as one phase of the intersection controller.
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
Every beginner exercise on this site, this one included, runs on the simulator's free tier — 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. The full curriculum — the structured version of these exercises with feedback on every submission — plus the wiring track, sensor school and cert packs sit in the Basic tier at USD 12 per month and Pro at USD 29 per month. 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, start on the free tier, finish the beginner set, and decide from there.
Run this exercise on the free tier →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.