How an automatic car wash PLC program works
An automatic car wash PLC program is a fixed-order, timed sequence — a state machine that walks through one wash stage at a time. The bay does nothing until two conditions are both true: a car has driven in and broken the CAR_PRESENT photo-eye, and the operator has pressed START. Only then does the cycle begin.
The wash runs four stages in strict order, three seconds each: SOAP, then BRUSHES, then RINSE, then DRYER. Exactly one stage may be energised at any moment — there is no overlap. When SOAP's timer finishes, SOAP must turn off the instant BRUSHES turns on, and so on down the chain. After the DRYER stage completes, a DONE_LAMP latches on to tell the driver the wash is finished. Pressing STOP at any point is an emergency abort: every output drops immediately.
The I/O is pre-wired for you. Three inputs: START (%I0.0, momentary push-button), STOP (%I0.1, abort push-button), and CAR_PRESENT (%I0.2, the car-in-bay photo-eye whose beam is broken by a car). Five outputs: SOAP (%Q0.0, the pre-soak spray valve), BRUSHES (%Q0.1, the scrub-brush motor), RINSE (%Q0.2, the rinse spray valve), DRYER (%Q0.3, the blower), and DONE_LAMP (%Q0.4, the wash-complete indicator).
Because the whole program is driven by on-delay timers handing off to one another, the car wash PLC program is a textbook way to learn TON timers and sequence control before moving on to counters, interlocks and analog work.
Sequencing the stages with TON timers — the car wash PLC program structure
The cleanest way to build this car wash control using a PLC is a phase-latch state machine: one latched bit per stage (PH_SOAP, PH_BRUSH, PH_RINSE, PH_DRYER) and one TON timer per stage. The phase bit says which stage is active; the timer measures how long the stage has run; the timer's done bit hands off to the next phase.
Start the chain by latching the first phase only when both gate conditions are met — SET PH_SOAP on START AND CAR_PRESENT. This is the rung that makes the bay ignore a START press when no car is in the bay, which is exactly what the discriminating 'no-car-no-cycle' test case checks: a naive rung that just mirrors START → SOAP fails immediately because it skips CAR_PRESENT and the sequencing.
Give each phase its own on-delay timer: T_SOAP(IN := PH_SOAP, PT := 3000ms). When T_SOAP.Q goes true the three seconds are up, so RESET PH_SOAP and SET PH_BRUSH on the same rung. Because PH_SOAP just dropped, the timer's IN input drops with it and T_SOAP resets itself, ready for the next car. Chain BRUSHES → RINSE → DRYER the same way, each phase set off the previous timer's done bit.
Drive each output coil directly from its phase bit — | PH_SOAP | := SOAP — so only one stage energises at a time by construction. Latch DONE_LAMP on T_DRYER.Q, the moment the final stage completes. This single-active-phase structure is why the 'happy-path' test sees SOAP, BRUSHES, RINSE and DRYER fire in order with no overlap.
STOP abort and the DONE lamp — getting the edge cases right
Two details separate a car wash PLC ladder diagram that merely runs from one that passes every test: the abort and the completion lamp.
The STOP abort must clear the entire machine, not just the stage that happens to be running. The simplest reliable pattern is to put a | STOP | R= reset on every phase bit (PH_SOAP, PH_BRUSH, PH_RINSE, PH_DRYER) and on DONE_LAMP. When STOP is pressed, every phase latch resets, every timer's IN drops because its phase is gone, and every output coil — driven directly from its phase bit — de-energises on the same scan. The 'stop-aborts' test advances the cycle to BRUSHES, presses STOP, and asserts SOAP, BRUSHES, RINSE, DRYER and DONE_LAMP are all off. A partial abort that only stops the current stage fails here.
The DONE_LAMP must stay off through every wash stage and light only after the DRYER finishes. If you accidentally drive it from a phase bit, or latch it too early, the 'done-only-after-dryer' test catches it: it samples DONE_LAMP while DRYER is still running (it must be off) and again after DRYER completes (it must be on). Latch DONE_LAMP from T_DRYER.Q — the dryer timer's done bit — not from PH_DRYER, so the lamp lights at the end of the dryer stage rather than at its start. Include DONE_LAMP in the STOP reset so a new car starts with a clean indicator.
Why the car wash is a classic beginner PLC project
The car wash is one of the most-assigned first projects in PLC training, and for good reason. It teaches the three skills every PLC programmer needs — sequencing, timing and a clean operator interface — without any of the complications of analog signals, PID loops or communications.
First, it makes the one-stage-at-a-time discipline concrete. A learner who tries to fudge the sequence with overlapping coils sees the simulated bay run two stages at once and the auto-grader reject it. That immediate, visible feedback teaches the value of a single-active-state machine far faster than a lecture does.
Second, it is the natural home for the TON on-delay timer. Each stage is just 'run this output for three seconds, then move on', which is the canonical TON use case. Chaining four of them — each timer's done bit launching the next phase — is the pattern you will reuse for traffic lights, batch processes and any other timed sequence.
Third, it introduces fail-safe operator control: a START that is properly gated (it does nothing without a car present) and a STOP that drops everything immediately. Those are habits worth forming early.
You can build and run the whole thing on this page. Write the ladder, press Run, and watch the bay step SOAP → BRUSHES → RINSE → DRYER → DONE. Four automated test cases grade the start gate, the full cycle, the STOP abort and the completion lamp — no physical PLC, sprayers or blowers required.