The short answer
Program Organization
A well-organized controller program mirrors the plant: a main routine that calls the others in a fixed order, an input mapping routine that copies physical inputs to named tags, a routine per process area or piece of equipment built from standard device blocks, separate routines for alarms and communications, control loops in a periodic task at a fixed rate, and an output mapping routine at the end. Tags are named by equipment and attribute, setpoints live in named registers rather than as constants, every rung or block has a comment that says what it is for, and a revision record inside the program says what changed and when. The test is whether a technician who has never seen the program can find the logic for one pump in under a minute.
Key points
- Structure follows the plant: area, then equipment, then device. Nobody should have to search a 3,000-rung routine.
- Map physical I/O to named tags in one routine at the start and one at the end; the logic never touches an address.
- Standard device blocks for pumps, valves, and analyzers; every pump behaves the same and is configured, not programmed.
- Fixed execution order: inputs, logic, alarms, communications, outputs. A tag written after it is read costs a scan.
- Setpoints in named registers with limits, never constants in the code.
- Comments say why, tag descriptions say what, and a revision record inside the program says what changed.
The test
Hand the program to a technician who has never seen it, and ask them to find why pump 2 is not starting. If they open the program tree, see a routine named for the lift station, open it, find pump 2, and read a permissive list, the program is organized. If they scroll through one enormous routine searching for the output tag, it is not. Organization is not tidiness for its own sake; it is the property that makes a control system maintainable by someone other than the person who wrote it.
The vocabulary by platform
| Concept | IEC 61131-3 | Rockwell Logix | Schneider Control Expert | Siemens TIA Portal |
|---|---|---|---|---|
| Scheduling unit | Task | Task (continuous, periodic, event) | Task (MAST, FAST, event) | Organization block (OB) |
| Container of logic | Program | Program with routines | Section | Function (FC) or function block (FB) |
| Reusable block with memory | Function block | Add-On Instruction | Derived function block (DFB) | Function block with instance data block |
| Reusable block without memory | Function | Add-On Instruction without state | Elementary function | Function (FC) |
| Structured data type | Structure | User-defined type (UDT) | Derived data type (DDT) | PLC data type (UDT) |
| Global data | Global variables | Controller tags | Unlocated variables | Global data block (DB) |
A layout that works
| Routine or section | Purpose | Notes |
|---|---|---|
| Main | Calls every other routine in a fixed order | Nothing else; a reader sees the whole program flow on one page |
| FirstScan | Initialization after power up or download | Sequence recovery, default setpoints if lost, communication resets |
| Inputs_Map | Copy physical inputs to named tags; scale analog inputs | The only place physical input addresses appear |
| Area routines | One per process area: LiftStation, Filters, Chemical, Disinfection | Each built from device blocks; pump 2 lives in its area routine |
| Loops | PID and other continuous control | In a periodic task at a fixed rate; never in the continuous task |
| Alarms | Alarm conditions, delays, and acknowledgment handling | Every alarm in one place, in the order of the alarm list |
| Comms | Messages to other controllers and devices, with status handling | Communication status bits feed signal validation in the area routines |
| HMI | Handshakes, command pulses, and the tags the HMI writes | Commands from the HMI are consumed and cleared here |
| Outputs_Map | Copy named output tags to physical outputs | The only place physical output addresses appear |
| Diagnostics | Module status, scan time, battery, redundancy | Feeds the controller health alarms |
Mapping I/O
The logic reads a tag named for the device, not a channel address. An input mapping routine at the start of the scan copies each physical input to its named tag and scales the analog ones; an output mapping routine at the end copies the named output tags to the physical channels. The cost is a few dozen rungs. The return is that a failed input card can be replaced by a spare in another slot by editing one routine, the program can be tested in simulation by disabling the mapping, and every rung in the logic reads in plain language.
Standard device blocks
A plant has twelve pumps that all need the same things: a run command, running feedback, a fail-to-start timer, a fail-while-running check, run hours, start counts, permissives, interlocks, HOA handling, and an HMI faceplate. Written twelve times, the twelve copies drift apart until no two pumps behave alike. Written once as a device block and instanced twelve times, every pump behaves the same, a fix applies to all of them, and a new pump is an instance with a configuration. The same applies to valves, analyzers, and drives. The block interface becomes the vocabulary of the whole system: every pump has a Sts.Running, a Cmd.Start, and an Alm.FailToStart, and the HMI faceplate binds to them by name.
Execution order
The controller executes the routines in the order the main routine calls them, once per scan. If the alarm routine reads a tag that the area routine writes, and the alarm routine runs first, the alarm sees the value from the previous scan. One scan late rarely matters, but a chain of such dependencies can add several scans of delay to a sequence and produce behavior that is hard to reproduce. Call the routines in the order data flows: inputs, area logic, loops, alarms, communications, HMI, outputs. And write each output from exactly one place; two rungs writing the same coil is the classic error, and the last one wins silently.
Naming
A tag name says what equipment and what attribute: P_101_Run, LT_101_PV, FV_102_ZSO. Where the platform supports structures, the device tag is the structure and the attribute is the member: P_101.Sts.Running. Use the tag numbers from the drawings and the instrument list, so the field, the drawings, the program, and the HMI all use the same identifiers. Descriptions carry the words: Lift Station 1 Pump 1 Running. Setpoints are named tags with engineering units and limits, editable from the HMI: LS1_LeadStartLevel_ft, not a constant 8.5 in a compare instruction.
Comments and revisions
A tag description says what a tag is. A rung or block comment says why the logic is the way it is: Delay is 15 s because the check valve slams if the pump stops with the discharge valve open. The reader can see what the rung does; the comment explains the intent, which is the thing that is lost when the author leaves. Keep a revision record inside the program, in a comment or a dedicated routine: date, who, what changed, and why, and export the project file to version control at every change so the history exists somewhere other than the laptop.
Signs of a program that needs reorganizing
- One routine of thousands of rungs, or routines named Routine1 through Routine9.
- The same pump logic copied per pump with small, undocumented differences.
- Physical input and output addresses scattered through the logic.
- Constants in compare and math instructions where setpoints should be.
- Outputs written from more than one rung.
- No comments, or comments that restate the instruction: Turn on output.
- No record of what changed since the last time anyone looked.
Frequently asked questions
- How big should a routine be?
- Small enough to read in one sitting and to describe in one sentence: this routine runs the filters. A routine that needs a table of contents is two routines. On most projects that is a few dozen to a couple of hundred rungs, and a device block instance counts as one rung.
- Are device blocks worth it on a small system?
- Yes, on anything with more than one pump. The block takes longer to write the first time than a few rungs of logic, and it pays back on the second pump, on the HMI faceplate that binds by name, and on every future change. Small systems grow.
- Should loops really be in a periodic task?
- Yes. A PID computes with an assumed sample time; in a continuous task that time varies with scan length and the loop tuning changes with it. A periodic task at 100 to 500 ms gives the loop a fixed sample time and predictable behavior. The same applies to totalizers and rate calculations.
- What is the minimum for a program someone else can maintain?
- A main routine that shows the flow, routines named for the plant areas, I/O mapped in one place, tags named from the drawings with descriptions, setpoints as named tags, a comment on every rung whose purpose is not obvious, and a revision record. That is a day of work on a program of any size, and it is the day that saves the most later.
Related topics
- IEC 61131-3The standard behind PLC programming languages: the five languages, the common elements of data types, variables, and program organization units, what conformance actually means, and how the standard shows up in real platforms.
- Ladder Logic FundamentalsRungs, contacts, coils, and the relay conventions the language inherited — plus the patterns you will meet in almost every industrial program.
- Function Block DiagramThe graphical data-flow language of IEC 61131-3: how blocks, pins, and wires work, execution order, where FBD beats ladder and structured text, building reusable equipment blocks, and the habits that keep a diagram readable.
- Tasks and Execution PriorityHow a controller schedules its work: the continuous task, periodic tasks at a fixed rate, event tasks triggered by something happening, how priority preempts, and where each kind of logic belongs.
- The PLC Scan CycleRead inputs, solve logic, write outputs, housekeeping. Understanding scan order explains most PLC behavior that looks wrong at first glance.
- How to Program Lead/Lag Pump ControlBuild duplex pump control with alternation, failure detection, minimum run and off timers, and an operator override that survives a restart.
Direct contact
Have a controls question?
Reach Eric Sullivan directly about anything on this site, a controls or automation topic, or one of his personal projects.