Writing Your First PLC Program: Ladder Logic Starter Guide

Brian Holt11 min read
AutomationDirectHMI ProgrammingTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

Every first PLC program follows the same proven workflow, whether the controller is an AutomationDirect CLICK, a ProductivityOpen P1AM, or an entry-level Do-more BRX. The hardware is forgiving; the discipline is not. Engineers who skip the sequence-of-operations document and jump straight into ladder logic end up rewriting the program two or three times. This guide walks through the field-proven methodology that takes a blank project to a working machine, using the same checklist that a controls integrator would apply to a small home-shop project or a single-station production cell.

Key principle: A PLC program is a written description of the machine's behavior. Write the description in plain English first, convert that description to ladder, then verify the ladder against the description. Never write ladder against a mental model that lives only in the programmer's head.

Prerequisites

Before opening the programming software, gather the following:

  • Mechanical sketch – A dimensioned drawing of the machine, including actuator mounting, sensor locations, and the human operator's reach. A simple freehand sketch is fine for a home shop; production work requires a controlled drawing.
  • Electrical schematic – Power distribution, fuse/breaker sizing, and the I/O wiring detail for every sensor and coil connected to the PLC.
  • PLC platform selected – For a first project, the AutomationDirect CLICK series (C0-1x, C0-2x) is a common starting point with free CLICK programming software. See the CLICK PLC product page for current part numbers and the CLICK User Manual for hardware specs.
  • Programming cable and software – USB or Ethernet depending on the platform; CLICK uses the free CLICK Programming Software v3.x and a USB-C cable for the C0-1x series.
  • Spare inputs and outputs – Always allocate 20% spare discrete I/O for revisions and troubleshooting indicators.

Step 1 – Write the Sequence of Operations

The sequence-of-operations (SeqOps) document is the single most important artifact of any PLC project. Without it, the programmer is guessing. With it, the ladder logic writes itself.

A SeqOps for a small machine is usually a one-page table with five columns:

Step Action Permissive (must be true) Output energized Next state
0 Idle / Ready Power on, E-stop closed, no faults Wait for Start PB
1 Start cycle Start PB pressed, guard closed, home sensor true Output 1 (extend cylinder) 2
2 Cycle in progress Extended sensor true, dwell timer done Output 5 (energize next device) 3
3 Retract Retract PB or auto Output 4 (retract cylinder) 0

List every operator action, every interlock, and every fault condition that must drop the machine out of auto. The AutomationDirect community knowledge base article on PLC programming fundamentals reinforces the same point: a clear SeqOps with named I/O lets the program be written deterministically, regardless of who writes it.

Step 2 – Build the I/O Map

The I/O map is a fixed table that ties every PLC address to a real-world signal. Tag it with a name that matches the schematic so anyone can trace from code to wire. The table below is a typical template for a CLICK-series discrete I/O module.

PLC address Tag name Type Device Normally Notes
X0 PB_Start DI, 24 VDC sinking Start pushbutton, panel Open Momentary N.O.
X1 PB_Stop DI, 24 VDC sinking Stop pushbutton, panel Closed Momentary N.C.
X2 ES_OK DI, 24 VDC sinking E-stop contact string Closed Must be N.C. per NFPA 79
X3 Guard_Closed DI, 24 VDC sinking Guard interlock switch Closed Safety input
X4 LS_Extended DI, 24 VDC sinking Limit switch, cylinder extended Open Mechanical actuator
X5 LS_Home DI, 24 VDC sinking Home proximity sensor Open Initiator, PNP
Y0 SOL_Extend DO, relay/SSR 5/2 solenoid, double-solenid valve Off Output 1 in user reference
Y1 SOL_Retract DO, relay Same valve, A-port solenoid Off Output 4 in user reference
Y2 Motor_Run DO, relay Spindle motor contactor coil Off Output 5 in user reference

Symbolic tag names eliminate the classic first-project mistake of writing to the wrong address three months later when no one remembers what X3 does.

Step 3 – Ladder Logic Building Blocks

Every first program uses the same five ladder primitives. Learn these and the rest is composition.

3.1 Examine-If-Closed (XIC) and Examine-If-Open (XIO)

The XIC contact is true when its bit is a logic 1. The XIO contact is true when its bit is a logic 0. In Allen-Bradley RSLogix 500 terminology these are --| |-- and --|/|--. In AutomationDirect CLICK the equivalents are STR (start, XIC) and STR NOT (XIO).

3.2 Output Energize (OTE)

The OTE coil turns its assigned bit on when the rung is true and off when false. Use it for non-retentive outputs that must drop out the instant the rung goes false.

3.3 Latch / Unlatch (OTL / OTU)

Use OTL/OTU pairs when a step must remain active after the input that started it drops out. Classic example: Start PB is momentary, but the machine must keep running until Stop PB, fault, or cycle-complete unlatches it.

3.4 Seal-In (Seal-Around) Contact

The classic seal-in pattern is the fundamental building block of any start-stop circuit:

|  PB_Start  PB_Stop  ES_OK  Motor_Run  |
|-------| |------|/|----|/|----|/|------( Y2 Motor_Run )------|
                              |                                   |
                              +-----------| |--------------------+ 

The Motor_Run XIC contact in parallel with PB_Start is the seal. It holds the rung true after the pushbutton is released. PB_Stop (N.C.) and ES_OK (N.C.) are wired in series; opening either one breaks the seal and drops the output. This is the first rung of essentially every PLC program ever written, and it is the one that should be mastered first.

3.5 Timer / Counter

Use a TON (on-delay) timer for dwell, debounce, or restart-inhibit timing. Address conventions differ by platform; CLICK uses the T data type with preset values in 100 ms increments, while ProductivityOpen uses _TIMER structures. See the CLICK User Manual, Chapter 6 for the exact instruction set.

Step 4 – Build a Simple State Machine

For any machine with more than two steps, a state machine beats a long ladder of seals. The simplest implementation is an integer tag (e.g., State) and one rung per state. Each state rung contains two parts: the permissives to enter the state, and the conditions to leave it.

State value Name Active outputs Exit conditions
0 Idle None Start PB + Home + E-stop OK
10 Extending Y0 (SOL_Extend) LS_Extended = 1 (or timeout fault)
20 Dwell Y2 (Motor_Run) + dwell timer Dwell timer done
30 Retracting Y1 (SOL_Retract) LS_Home = 1
40 Fault Y3 (Beacon red) Reset PB

For the CLICK platform, a SG (Stage) instruction is a built-in state-machine primitive. For ProductivityOpen P1AM-100, ladder with integer State and comparison instructions is more flexible. Either approach is acceptable; what is not acceptable is to encode states as a tangled web of non-overlapping seal-in rungs.

Step 5 – Add a Safety Routine

Even a home-shop machine deserves the following three rungs, in this order at the top of the program:

  1. E-stop drop-out: any E-stop opening forces the machine into State = 0 or State = 40 via a normally-closed contact that overrides every seal.
  2. Guard interlock: opening a guard door while a hazardous motion is in progress must either prevent start or de-energize the hazardous outputs immediately.
  3. Fault latch: any unacknowledged fault must be latched into a FaultWord bit that survives a power cycle so the operator can see what happened.
NFPA 79 reference: Emergency stop devices must use direct-opening (force-guided) contacts and be wired in a manner that a single fault does not prevent the stop command from functioning. This is a basic requirement for any machine, including hobby machines, because liability and insurance follow the same electrical rules. See NFPA 79 for the current edition.

Step 6 – Program Structure on a Multi-Task Controller

Once the program grows beyond about twenty rungs, split it into named tasks or subroutines. The ProductivityOpen P1AM-100 and Do-more BRX platforms support task-level prioritization; CLICK supports program files. A standard split is:

Routine Scan priority Contents
SAFETY Highest E-stop, guard, fault latch
IO_SCAN High Input debounce, output forcing for HMI
STATE_MACHINE Normal Mode select, state transitions
OUTPUTS Low Final OTE/OTL rungs driving Y-coils
HMI Lowest Display tags, mode select

Putting the safety routine first guarantees that even if the state machine locks up, the E-stop still drops the outputs in the same scan.

Step 7 – Testing and Verification

Never trust untested ladder. Verify in this order:

  1. Offline simulation. Most CLICK software versions and all Do-more Designer releases include a built-in simulator. Step through the SeqOps line by line and confirm each transition fires the right output.
  2. Power-on bench test. With all actuators disconnected, watch the output LEDs on the PLC as you actuate each input. The output LED should follow the OTE coil truth table exactly.
  3. Force-disable test. With the machine in a safe state, force the start input high in the software. The outputs should come on. Remove the force and they should drop. If they don't, the seal is wrong.
  4. Single-cycle test. Run the machine through one full cycle, watching every limit switch and output LED in real time. Use the software's trend or data view to capture the scan-level behavior.
  5. Fault-injection test. Trigger every documented fault (E-stop, guard open, timeout, overload) and confirm the machine enters the fault state and requires an explicit reset.

Document each test result in a one-page commissioning sheet. That sheet is your evidence that the machine was verified against the SeqOps.

Common First-Program Pitfalls

Pitfall Symptom Fix
Seal-in contact wrong polarity Output drops out as soon as Start PB releases Verify the seal-in XIC uses the OUTPUT bit, not a duplicate of the PB bit
Two outputs that should be mutually exclusive are both on Valve or contactor buzzes, motor overheats Add interlock contacts in series with each output; the truth table must be exclusive
Double-coil (OTE driving the same tag twice) Scan-order dependent behavior; works in sim, fails on hardware Use a single OTE/OTL and use the tag (not the coil) elsewhere in the program
Timer preset too short Cycle aborts under load but not no-load Measure the worst-case cycle time with a stopwatch and add 30%
No fault latching Operator cannot tell why the machine stopped Add a fault word with one bit per alarm; latch on detect, unlatch on reset
Inputs wired to the wrong terminal block PLC reads the wrong sensor Build the I/O map and verify the wiring with a multimeter before applying power

From First Program to Production Program

Once the home-shop program is working, the next three things to add before treating the code as production-grade are:

  1. Comments on every rung – the rung comment should say in plain English what state the machine is in and what this rung does. Future you will thank you.
  2. Revision history in the file header – date, author, change description. CLICK and ProductivityOpen both support free-form project notes; use them.
  3. Backup of the program off the PLC – upload the project to a versioned directory on a PC or a Git repository. A PLC without a backup is a maintenance liability.

The first PLC program is rarely the last. Treat each revision as a learning artifact, document the changes, and the code will be portable to the next machine.

What is the simplest PLC for a first home-shop project?

The AutomationDirect CLICK series (C0-12DD1E or C0-12DD2E for 12 discrete I/O, or C0-14xxx for mixed discrete/analog) is a common starting point with free CLICK Programming Software v3.x, built-in discrete I/O, and a USB programming port. See the CLICK product page for current part numbers and the CLICK User Manual for specifications.

What is a seal-in contact and why is it needed?

A seal-in (or seal-around) is a contact wired in parallel with the start pushbutton that uses the output bit itself as the holding element. It is needed because start pushbuttons are momentary, but the machine must keep running until a stop, fault, or cycle-complete signal drops the output. The seal is what turns a momentary input into a sustained output.

How many steps should a first PLC program have?

Start with three to five states: Idle, Running, Dwell, Retract, Fault. More than that usually indicates the SeqOps document was incomplete, and the ladder should be redesigned around a state machine rather than expanded with additional seals. See the state-machine section above for the typical four-state template.

Do I need a separate safety relay if I have a PLC?

For a hobby or home-shop machine with a single E-stop, wiring the E-stop string in series with a redundant contactor and into a PLC safety input is a common starting point. For production machinery in the US, NFPA 79 typically requires a category-3 or category-4 safety circuit, which generally means a dedicated safety relay (e.g., a Pilz PNOZ, Banner XS26, or SICK Flexi Soft) rather than relying on a standard PLC. Verify the applicable edition of NFPA 79 and any local machinery-safety directives before commissioning.

How do I test a PLC program before connecting the real machine?

Use the built-in simulator in CLICK Programming Software or Do-more Designer to step through the SeqOps one state at a time and verify the output truth table. Then bench-test with the actuators disconnected, watching the PLC output LEDs against the ladder. Only after both pass should the program be downloaded to a machine and run under a controlled single-cycle test with the operator ready to hit E-stop.

Back to blog