PLC Programming SAPLC ProgrammingSOUTH AFRICA

exercises · South Africa

PLC up down counter example: parking garage

A PLC up down counter example with a CTUD: entry and exit loops track 50 parking bays, drive a FULL sign, and survive the double-trigger sensor problems.

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 basement parking at a Sandton office block has 50 bays and a permanent argument at the boom. The FULL sign is switched by the guard, who guesses. Loop detectors are already cast into the entry and exit lanes. Count cars in on the entry loop, out on the exit loop, and light the FULL sign at 50 so the boom can hold new arrivals. The guard gets a reset button for Monday mornings after the count drifts (it will drift — pedestrians, trolleys and tailgating all happen). The building manager also wants the live count available for the lobby display later, so keep the value in one clean variable.

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
EntryLoopDI%I0.0Inductive loop in the entry lane, TRUE while a vehicle sits over it.
ExitLoopDI%I0.1Inductive loop in the exit lane, TRUE while a vehicle sits over it.
ResetPBDI%I0.2Guard's count-reset pushbutton behind the desk, normally open, key-protected.
FullSignDO%Q0.0FULL sign at the entrance, on when the count reaches 50.
SpacesLampDO%Q0.1Green SPACES lamp, the inverse of the FULL sign.

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 IEC CTUD gives you up, down, reset and load in one instruction, with QU true when the count reaches the preset. Use it rather than two separate counters fighting over one value — synchronising a CTU and CTD by hand is a solved problem you do not need to re-solve.
  • Vendors differ on clamping: some stop the CTUD at zero on the way down, others go negative. Do not rely on either — gate the down input so an exit pulse with the count already at zero is ignored, and the behaviour is yours instead of the vendor's.
  • A car parked half on the loop produces a held TRUE, not a pulse. The CTUD's inputs are edge-sensitive internally, so a held loop counts once — but a loop that flickers as a car creeps counts repeatedly. A short debounce TON in front of each loop input mirrors what the bottle-counter exercise does for its photoeye.

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-2: debounce both loops

A 200 ms TON on each loop input produces clean CarIn and CarOut bits. A creeping vehicle in heavy traffic can dither the raw loop signal; 200 ms of confirmation is invisible to a real car and removes the flicker counts entirely.

// EntryLoop ──[TON tIn, PT := T#200ms] ── tIn.Q = CarIn
// ExitLoop  ──[TON tOut, PT := T#200ms] ── tOut.Q = CarOut

Rung 3: the CTUD

CTUD with CU from CarIn, CD from CarOut gated by the count being above zero, R from ResetPB, and PV of 50. The counter's CV is the live bay count and QU is the full signal — the single variable the lobby display will read later.

// CarIn ── CU ┐
// CarOut AND (CV > 0) ── CD ├─[CTUD cBays, PV := 50]
// ResetPB ── R ┘

Rungs 4-5: signs from the counter

FullSign follows QU; SpacesLamp is NOT QU. Driving both from the same counter output means the signs can never disagree with each other — only with reality, which is what the guard's reset button is for.

// cBays.QU ──( )FullSign
// NOT cBays.QU ──( )SpacesLamp

Test the boundaries

Pulse 50 entries and confirm FULL lights on exactly the 50th. Pulse one exit: FULL must clear at 49. Now the boundary everyone forgets: with the count at zero, pulse five exits — the count must stay at 0, not go negative or wrap. Hold a loop TRUE for a minute (one count only), flicker it with 100 ms pulses (no counts), and press reset with cars 'present' to confirm the count zeroes regardless. If your platform clamps CV at PV on the way up, note it — at 50 with one more entry, what does CV read?

The structured text version

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

(* Parking bay counter, IEC 61131-3 ST *)
tIn(IN := EntryLoop, PT := T#200ms);
tOut(IN := ExitLoop, PT := T#200ms);
cBays(CU := tIn.Q,
      CD := tOut.Q AND (cBays.CV > 0),
      R  := ResetPB,
      PV := 50);
FullSign   := cBays.QU;
SpacesLamp := NOT cBays.QU;

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.

  • Using two separate counters (a CTU for in, a CTD for out) and subtracting. Reset logic now has two targets, the subtraction lives in a third place, and the three disagree after the first power cycle — the CTUD exists precisely so you do not do this.
  • Letting the count go below zero. Saturday morning, garage empty, a delivery van exits twice past a flaky loop: count is -2, and the FULL sign now lights at what the counter thinks is 50 but is actually 52 cars. Gate the CD input.
  • Counting raw loop signals. A car creeping in traffic over the entry loop registers three 'cars' and the garage reads full at 47 actual vehicles — the guard's reset button gets worn shiny and the logic gets the blame it deserves.
  • Treating the count as exact forever. Tailgating through the boom and pedestrians over the loops guarantee drift; the design answer is the reset button and (the extension) a periodic reconciliation, not pretending drift will not happen.

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.

  • Send CV to a lobby display tag and add a 'spaces available' calculation (PV minus CV, clamped at zero) — your first taste of presenting internal values to people who will phone when it is wrong.
  • Add a second level with its own loops and counter, plus a combined FULL decision — then notice how much of the logic wants to become a reusable function block, and make it one.
  • Add an entry boom interlock: the boom may only open when QU is false, with a 30-second timeout alarm if a car sits on the loop while FULL — the genuinely tricky conversation between counting and access control.

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

Programmable logic controller on Wikipedia 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