PLC Book Part III — Advanced Instructions & Data Handling Chapter 10
Chapter 10 Part III · Advanced Instructions & Data Handling Advanced ⏱ 50 min read ✦ 5 PLC Programs

10

Data Manipulation Instructions

Up until now, almost everything the PLC has done is at the level of single bits — coils, contacts, timers, counters. Real industrial work also needs to handle numbers: setpoints, recipe parameters, analog readings, scaled measurements, lookup-tables of configuration values. This chapter introduces the instructions that move numbers from one place to another (MOV, MVM, COP, FLL), compare them against limits (EQU, NEQ, LES, GRT, LIM), connect them to the outside world (BCD thumbwheels, 7-segment displays), and feed them into a closed-loop control calculation — your first taste of how PLCs run continuous processes rather than just discrete machinery.

What you’ll be able to do after this chapter

Your goals for this chapter:

  • Explain how PLC data files are organised — integer (N), floating-point (F), binary (B) — and why the file type matters.
  • Use MOV to transfer a single value, MVM to transfer selected bits with a mask, COP to transfer an array of words, and FLL to fill a region with a constant.
  • Apply the comparator family — EQU, NEQ, LES, GRT, LEQ, GEQ, LIM — to drive outputs based on numerical conditions.
  • Build a recipe-selection program that loads different parameter sets into the running tags based on operator selection.
  • Read a BCD thumbwheel switch using FRD and write to a BCD 7-segment display using TOD.
  • Distinguish open-loop from closed-loop control and identify the components of a feedback control loop.
  • Implement a simple proportional controller using SUB and MUL — the core of every PID loop.
  • Recognise where the dedicated PID instruction would replace your hand-built calculation.

Key Concepts & Terms

Word · RegisterInteger file (N7)Float file (F8)Binary file (B3) MOV · MoveMVM · Masked MoveCOP · File CopyFLL · File Fill MaskSource / Destination EQU · EqualNEQ · Not EqualLES · Less ThanGRT · Greater Than LEQ · Less EqualGEQ · Greater EqualLIM · Limit Test Recipe selectionLookup table BCD encodingFRD · BCD→BinaryTOD · Binary→BCD Thumbwheel switch7-segment display Setpoint (SP)Process variable (PV)Error (E = SP − PV) Open-loop · Closed-loopProportional controlGain PID controller
Section 10.1

Data Manipulation Concepts

So far in this book we’ve worked almost entirely with bits — single 1-or-0 values that represent contact states, coil states, sensor states, lamp states. Bit-level logic gets you a long way; you can build entire conveyor lines, batch fills, and start-stop circuits without ever moving anything bigger than a single bit.

But the moment you need to store a setpoint, read an analog sensor, look up a recipe, or do arithmetic, single bits are no longer enough. You need numbers — values like 120.5 °C, or recipe number 7, or oven setpoint 360 seconds. Numbers in a PLC live in data files, and the file type tells the PLC how to interpret the bits inside.

Data file types

Every modern PLC organises its memory into files, each holding values of one specific type:

FileContainsRange / FormatExample address
I · Input fileLive input imageBits and words from input cardsI:1/3 (bit), I:3.0 (analog word)
O · Output fileLive output imageBits and words to output cardsO:2/0, O:4.0
B3 · Binary fileInternal bit storage16-bit words, accessed bit-by-bitB3:0/0, B3:5 (whole word)
T4 · Timer fileTimer instancesEach instance: PRE, ACC, EN/TT/DN bitsT4:0.ACC, T4:0/DN
C5 · Counter fileCounter instancesEach instance: PRE, ACC, CU/CD/DN/OV/UN bitsC5:0.ACC, C5:0/DN
N7 · Integer fileSigned 16-bit integers−32 768 to +32 767N7:0, N7:25
F8 · Float file32-bit IEEE-754 floating-point±3.4 × 10³⁸ with ~7 digits precisionF8:0, F8:14

The file letter (N, F, B, T, C, I, O) tells the PLC how to interpret the bits. Mixing them up is a common beginner error: try to MOV from F8:0 (float) into N7:0 (integer) and you’ll truncate the decimal portion silently. Try to MOV from N7:0 into F8:0 and the integer becomes a float — usually fine, but you should know it’s happening.

DATA FILE STRUCTURE — A SINGLE WORD ACROSS THREE FILE TYPES Same 16 bits — interpreted three different ways depending on file type. B3:5 binary 0 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 → 16 individual bits, addressed B3:5/0 to B3:5/15 N7:5 integer 21 537 → same 16 bits read as a signed integer F8:5 float 120.500 → paired words read as IEEE-754 32-bit float

Figure 10.1 — Data file interpretationThe same memory holds the same bits, but the file type chosen by the programmer determines whether those bits represent 16 separate flags, a signed integer, or a floating-point number. Picking the wrong file type silently misinterprets the data.

Once you have data in the right file, you have to do something with it. The two basic actions are moving data (copy a value from A to B) and comparing data (test whether one value is equal to / greater than / less than another). The next two sections cover each in turn.

Section 10.2

Data Transfer (MOV) Operations

Data transfer instructions copy a value from a source register to a destination register. The source isn’t changed; only the destination receives the new value. Four instructions cover almost every transfer need:

MOV — single-word move

The workhorse. Copies one value from source to destination on each scan that the rung is true.

MOV source: N7:5 destination: N7:20

That rung copies whatever’s in N7:5 into N7:20 every scan the rung is true. If you want to do the move only once (when a button is pressed, for example), put a one-shot in the rung — otherwise the destination is overwritten every scan.

MVM — masked move

Copies selected bits from source to destination, leaving the other bits in the destination unchanged. The “mask” is a 16-bit pattern: where the mask is 1, the bit is copied; where the mask is 0, the destination bit is preserved.

MVM source: N7:5 mask: 0000 0000 1111 0000 dest: N7:20

That rung copies bits 4–7 from N7:5 into bits 4–7 of N7:20. Bits 0–3 and 8–15 of N7:20 are untouched. Useful when several different program sections each “own” different bits of a shared status word.

COP — file copy

Copies an array of words — N elements in a row. Useful for loading a recipe (10 parameters at once) or transferring a logged set of samples.

COP source: #N7:50 destination: #N7:100 length: 10

That rung copies N7:50–N7:59 into N7:100–N7:109. The # prefix tells the PLC “this is the start of an array, not a single word”.

FLL — file fill

Writes the same value into every word of an array. Useful for clearing a buffer or initialising an array of setpoints.

FLL source: 0 destination: #N7:100 length: 10

That rung writes 0 into N7:100–N7:109 — the same as 10 consecutive MOVs of zero, but in one instruction.

Why MOV every scan is usually fine

Most MOV rungs are conditional — gated by an XIC of “system enabled” or a one-shot. But sometimes you’ll see unconditional MOVs that fire every scan. That’s also acceptable when the source value is something that genuinely does change every scan (like a live analog reading) and the destination is meant to track it. The pattern to avoid is a MOV that fires every scan when the source changes only on a button press — that’s wasted CPU and a sign you forgot the gate.

Section 10.3

Data Compare Instructions

Comparators are input-style instructions. They sit on the left side of a rung where you’d normally put XIC contacts. Their output is true (passing power) when the comparison they describe is true; false otherwise. The rung’s coil fires according to that result.

Seven comparators handle every numeric test you’ll need:

InstructionReadsOutput is TRUE when…Typical use
EQU — EqualSource A, Source BA = BRecipe-number dispatch, finished-state detection
NEQ — Not EqualSource A, Source BA ≠ BMismatch alarms, change detection
LES — Less ThanSource A, Source BA < BLow-level alarms, lower thresholds
GRT — Greater ThanSource A, Source BA > BHigh-level alarms, upper thresholds
LEQ — Less or EqualSource A, Source BA ≤ B“Stop when at or below” logic
GEQ — Greater or EqualSource A, Source BA ≥ B“Trigger at or above” logic
LIM — Limit TestLow, Test, HighLow ≤ Test ≤ High (or High ≤ Test ≤ Low)“Inside operating window” tests

The LIM instruction is special

LIM tests three values at once: a low limit, the test value, and a high limit. Its output is true when the test value is between the two limits. This is enormously more compact than wiring two separate comparators (LEQ + GEQ) in series — one LIM, three sources, done.

An interesting quirk: if the engineer programs Low > High (e.g., Low = 50, High = 10), LIM treats it as an inverted test — true when the test value is OUTSIDE the [10, 50] range. This is occasionally useful but is a frequent source of confusion, so most engineers stick to writing Low < High and using NEQ-style logic when they want “outside window”.

Comparators are not edge-triggered

A comparator’s output stays true as long as the comparison is true — many scans, possibly forever. If you want a one-time response when the condition first becomes true, follow the comparator with a one-shot. Otherwise downstream counters and timers may fire repeatedly.

Comparators with floats

Floating-point equality is tricky. A value computed as 0.1 + 0.2 doesn’t exactly equal 0.3 due to IEEE-754 rounding. Avoid EQU on floats; use a LIM with a small tolerance band instead. For example: “level is at setpoint” → LIM source A: SP−0.5 test: PV source B: SP+0.5.

Section 10.4

Data Manipulation Programs — Recipes, Lookup Tables, and File Operations

Once you have the basic move and compare instructions in your toolkit, the patterns they enable are some of the most powerful in PLC programming. Three patterns cover the majority of real-world data-manipulation work.

Recipe selection

A machine that runs multiple products needs different setpoints for each one — different cook times, different temperatures, different mix ratios. Hard-coding 25 separate cases is unmaintainable. Better: store each product’s parameters as a contiguous block in memory (a “recipe”) and use COP to load the chosen recipe into the running tags.

The structure looks like this:

  • Recipe storage: N7:50–N7:59 = recipe 1, N7:60–N7:69 = recipe 2, etc.
  • Active recipe (running): N7:100–N7:109 — the parameters the program currently uses.
  • Selection: an EQU comparator on the operator’s selection number triggers a COP that copies the right recipe into the active block.

Adding a new recipe is now just adding 10 more words of data — no code changes. We’ll build this out in Worked Example 1.

Lookup tables

Some calculations are easier as a table than as math. The classic case is non-linear sensor calibration: a thermocouple’s reading-vs-temperature curve isn’t a straight line, but a 50-point table with linear interpolation between points captures the curve perfectly. The PLC indexes into the table using the raw reading and reads out the calibrated temperature. The MOV-with-indexed-address pattern (e.g. MOV N7:[N7:0] N7:50) makes this one rung.

File arithmetic and statistics

For batch operations across an entire array — “compute the average of these 100 samples”, “find the maximum”, “sort this list” — the FAL (File Arithmetic Logic), AVE, STD, and SRT instructions exist. They operate on whole arrays the way MOV operates on single words. We won’t dive deep into FAL in this chapter; the key idea is to recognise that any operation you can do on a single value, you can do on a whole array with one rung if your platform supports it.

Why this matters

The difference between a junior PLC programmer and a senior one is often visible right here. A junior writes 25 separate rungs for 25 separate recipes. A senior writes one COP rung dispatched by an EQU comparator, with the recipes stored as data the production team can edit without touching the program. Same machine behaviour, dramatically different maintainability. Whenever you find yourself copying-and-pasting rungs that differ only by their constants, ask: could those constants be data instead of code?

Section 10.5

Numerical Data I/O Interfaces

Numbers don’t only live inside the PLC — they have to get in and out. Operators set values on physical interfaces; displays show values to the team on the floor. Most modern installations use HMIs and touch-screens, but two older but still-common interfaces are worth understanding: BCD thumbwheel switches (input) and BCD 7-segment displays (output).

BCD encoding — what it is

BCD stands for Binary Coded Decimal. Each decimal digit (0–9) is encoded as 4 bits — the binary representation of that digit. So the number “37” in BCD takes 8 bits: 0011 for the 3, then 0111 for the 7. The number “1024” in BCD takes 16 bits: 0001 0000 0010 0100.

BCD is wasteful compared to plain binary (you can’t use the patterns 1010–1111 in any digit position), but it has one huge practical advantage: each decimal digit lives in its own 4-bit nibble. That means a 4-digit BCD thumbwheel switch wires directly to the PLC: 4 wires per digit, 16 wires total, each thumbwheel switch turning gives you a clean 4-bit binary representation of that digit.

FRD and TOD instructions

BCD numbers in the PLC’s memory aren’t directly usable by math instructions — math expects plain binary integers. So the PLC has two conversion instructions:

  • FRD — From BCD — Converts a BCD-encoded number (read from a thumbwheel input word) into a plain binary integer. The result is stored in an N7 file ready for use in math, comparisons, and recipe lookups.
  • TOD — To BCD — Converts a plain binary integer back into BCD encoding ready to drive a 7-segment display module.

Where this still matters

Most new builds use HMI screens for everything, so BCD interfaces are less common than they once were. But:

  • Legacy machinery in service for 20+ years often still has thumbwheel switches and 7-segment indicators, and you’ll need to read and write them.
  • Simple panel-mount interfaces for setpoints (a single thumbwheel for “batch count target”) are still widely used because they are mechanically rugged and require no software on the operator side.
  • Some safety-rated interfaces still mandate physical switches over touch-screens — and those switches typically come back into the PLC as BCD.

Modern alternative: scaled analog and HMI

For most new applications, you’ll skip BCD entirely. Setpoints come from an HMI tag (already a binary integer or float in PLC memory, no conversion needed); displays go to the same HMI as live values. The chapter on numerical I/O is here partly so you can read and maintain older machines, and partly because the BCD/binary distinction shows up in unexpected places — like when interfacing to certain VFD drives or weighing scales that report values in BCD over a fieldbus.

Section 10.6

Introduction to Closed-Loop Control

Until now, our PLC programs have been mostly discrete: a switch turns on, a motor runs; a sensor blocks, a counter increments. The PLC observes inputs and decides outputs. There’s no continuous measurement of how well the machine is performing the task.

Now imagine controlling the temperature of a chemical reactor. You can turn the heater on or off — but if you simply leave it on, the reactor overheats. If you turn it off and on by a temperature limit switch, the temperature swings up and down dramatically. To hold the temperature steady at exactly 75 °C, you need closed-loop control: continuously measure the temperature, compare it to the desired setpoint, and adjust the heater output proportionally.

Open-loop vs closed-loop

The distinction is clear once you see it:

  • Open-loop control: the controller commands the actuator and hopes for the best. There’s no feedback measurement of whether the goal was achieved. Example: a timed bake — turn on the oven for 30 minutes regardless of actual oven temperature.
  • Closed-loop control: the controller measures the result, computes the error, and adjusts the actuator continuously to drive the error toward zero. Example: a thermostatically controlled oven — measure temperature, compare to setpoint, modulate heater power based on the difference.
CLOSED-LOOP CONTROL — THE FEEDBACK STRUCTURE Setpoint and process variable feed an error signal that drives the actuator. Setpoint SP = 75°C Σ Controller P, PI, or PID error Actuator heater / valve CV Process reactor Sensor RTD / 4-20 mA Process Variable (PV) — measured value

Figure 10.2 — The closed-loop control structureSetpoint minus measured PV gives the error. The controller acts on the error to produce a control variable (CV). The actuator drives the process. The sensor reads the result and feeds it back. The loop runs continuously.

Components of a feedback loop

  • Setpoint (SP) — the desired value, set by the operator. “I want the temperature to be 75 °C.”
  • Process variable (PV) — the actual measured value, read from a sensor. “The temperature right now is 71.4 °C.”
  • Error (E) — the difference: E = SP − PV. “Error is +3.6 °C; we’re below setpoint.”
  • Control variable (CV) — what the controller commands the actuator to do. “Open the heater valve to 60 %.”
  • Process — the physical thing being controlled (the reactor, the tank, the temperature, the flow rate).

The simplest controller — proportional only

A proportional (P) controller sets the actuator output proportional to the error: bigger error, bigger correction. The math is one line:

CV = Kp × (SP − PV)

Kp is the proportional gain, a number you tune. Larger gains make the controller respond faster but risk oscillation; smaller gains are stable but slow. A pure P-controller will leave a small steady-state offset (a non-zero error at equilibrium), which is why most real systems add an integral (I) term to drive that offset to zero, plus a derivative (D) term to anticipate rate of change. The combination is the famous PID controller.

Modern PLCs include a dedicated PID instruction that wraps all three terms, gain scheduling, output limiting, anti-windup protection, and tuning interfaces in one block. We’ll use the PID instruction in detail in later chapters; for this chapter we’ll build a P-only controller by hand using SUB and MUL — both to demystify what the PID block is doing under the hood and to give you a tool you can use today on simple loops.

Worked PLC Programs

Five Programs — From Recipe Selection to a Proportional Controller

The five programs build progressively: single-word MOVs dispatched by EQU, multi-bound checks with LIM, masked transfers with MVM, file-level COP for recipe blocks, and finally a complete proportional control loop using SUB and MUL — the foundation of every PID controller you’ll ever tune.

01

PLC Program · MOV + EQU

Recipe Selection — Five Products, One Dispatch Rung Each

MOV / EQU

The problem: a packaging machine runs five different products. Each product has its own oven temperature setpoint. The operator selects the product number (1–5) on a thumbwheel, and the program loads the correct setpoint into the running oven temperature register. Today we’ll handle just one parameter (oven setpoint) to keep the example focused; in Worked Example 4 we’ll extend this to a 10-parameter recipe.

Inputs & Outputs

INPUTS

N7:0 — Product selector (1–5, from thumbwheel via FRD)

OUTPUTS

N7:50–N7:54 — Stored setpoints for products 1–5 (constants)

N7:100 — Active oven setpoint (used by the rest of the program)

Recipe Storage Map

AddressProductOven Setpoint (°C)
N7:50Product 1 — Standard180
N7:51Product 2 — Premium205
N7:52Product 3 — Light165
N7:53Product 4 — Crispy225
N7:54Product 5 — Frozen240

Ladder Diagram (Five Dispatch Rungs)

L1 L2 000 EQU — Equal N7:0 = 1 MOV — Move N7:50 → N7:100 001 EQU — Equal N7:0 = 2 MOV — Move N7:51 → N7:100 002 EQU — Equal N7:0 = 3 MOV — Move N7:52 → N7:100 003 EQU — Equal N7:0 = 4 MOV — Move N7:53 → N7:100 004 EQU — Equal N7:0 = 5 MOV — Move N7:54 → N7:100 N7:100 always holds the active setpoint matching the selected product number.

Five rungs, each with one EQU comparator and one MOV. Whichever EQU’s condition is true, that MOV fires and loads its recipe value into the active setpoint.

How it works

  1. Operator dials product 3 on the thumbwheel. The thumbwheel reads 3 through the FRD, landing in N7:0.
  2. Every scan, all five EQU comparators run. Only the rung 2 EQU (test “N7:0 = 3“) is true. The other four are false.
  3. Rung 2’s MOV fires. The value at N7:50+2 = N7:52 (165 °C) is copied into N7:100.
  4. The rest of the program reads N7:100 as the active oven setpoint and drives the heater logic accordingly.
  5. Operator switches to product 5. Now only rung 4’s EQU is true; N7:54 (240 °C) gets MOVed into N7:100. The change is instant — no special “recipe load” button needed.
What we learned: the EQU + MOV pattern dispatches between several pre-stored values based on a selector. It’s verbose for many cases (5 rungs for 5 products; 25 rungs for 25 products) but easy to read and easy to extend. For larger recipe sets we’ll move to indirect addressing or COP — see Worked Example 4. The key insight is that the recipe values are data, not code — the production team can edit them via the HMI without touching the program.
02

PLC Program · LIM comparator

Reactor Operating Window — Single-Rung Range Check

LIM

The problem: a chemical reactor’s temperature must stay between 60 °C (low) and 80 °C (high). When it’s inside that window, a “PROCESS HEALTHY” lamp lights and the recipe sequencer is allowed to advance. Outside the window, the lamp drops and an “OUT OF RANGE” alarm fires. Two limits, one rung — perfect for LIM.

Inputs & Outputs

INPUT

F8:0 — Reactor temperature, °C (live, scaled from RTD)

OUTPUTS

O:2/0 — “PROCESS HEALTHY” green lamp

O:2/1 — “OUT OF RANGE” amber alarm lamp

Ladder Diagram (Two Rungs)

L1 L2 000 LIM — Limit Test Low limit 60.0 Test value F8:0 High limit 80.0 O:2/0 Healthy 001 XIO Healthy O:2/0 O:2/1 Out of range

One LIM rung handles the in-range test. The alarm rung uses an XIO of the healthy lamp — a clean inverse, no second LIM needed.

How it works

  1. Temperature inside the window (62 °C, say). 60 ≤ 62 ≤ 80, so LIM is true. Rung 0’s output passes — the green “PROCESS HEALTHY” lamp lights.
  2. Rung 1’s XIO of the healthy lamp. Healthy is on, so XIO is false. The amber “OUT OF RANGE” lamp stays off.
  3. Temperature drops to 55 °C. 55 is less than the low limit (60), so LIM is false. The healthy lamp drops.
  4. Rung 1’s XIO is now true (healthy is off). The amber alarm lamp lights.
  5. Operator restores temperature to 70 °C. 60 ≤ 70 ≤ 80 → LIM true → healthy lamp returns → alarm drops.

Why one LIM beats two GEQ/LEQ

The alternative would be: GEQ F8:0 60 — branch — LEQ F8:0 80 in series. That works, but LIM is more compact (one block instead of two), reads more naturally (“is the value between 60 and 80?”), and the source-A and source-B values can be tags rather than constants — making it trivial to convert hard-coded limits into HMI-editable setpoints later.

What we learned: use LIM for any “in-range” or “outside-range” test. One instruction reads three sources and produces one comparison result. Pair it with an XIO contact downstream to get the inverse condition for free. For floating-point setpoints, this pattern also dodges the “never use EQU on a float” trap from Section 10.3 — SP − 0.5 ≤ PV ≤ SP + 0.5 via LIM is the right way to detect “at setpoint” with tolerance.
03

PLC Program · MVM masked move

Fault Status Display — Selective Bit Transfer with a Mask

MVM

The problem: a packaging line collects fault bits from across the program into one 16-bit fault status word, B3:10. Bits 0–7 are process faults (high temperature, low pressure, jam, etc.) that the HMI should display. Bits 8–15 are diagnostic flags used internally by the program but not relevant to the operator. We need to copy only bits 0–7 of B3:10 to N7:200 (the HMI fault display register), without disturbing bits 8–15 of N7:200 — which the HMI uses for other purposes.

Inputs & Outputs

SOURCE

B3:10 — Aggregated fault word (bits 0–7 = process, 8–15 = diagnostic)

Mask: 0000 0000 1111 1111 = decimal 255

DESTINATION

N7:200 — HMI display register (bits 0–7 receive process faults; bits 8–15 unchanged)

Ladder Diagram (One Rung)

L1 L2 000 MVM — Masked Move Source B3:10 Mask 0000 0000 1111 1111 Destination N7:200 For each bit position: mask=1 copy from source · mask=0 destination unchanged

A single MVM rung does the whole job. The mask is a 16-bit constant entered at programming time.

Bit-by-bit walkthrough

Bit positionMask bitSource (B3:10)Dest beforeDest afterEffect
0 (LSB)11 (jam fault)01copied from source
11010copied from source (overwrote)
2–71variousvarious= sourceall process bits transferred
801 (diag flag)11preserved (mask = 0)
9–150variousvarious= dest beforediagnostic bits not touched
What we learned: MVM transfers just the bits you point the mask at. Mask = 1 means “copy this bit from source”; mask = 0 means “leave this bit alone in the destination”. One rung replaces what would otherwise be eight separate single-bit MOVs (or eight conditional rungs). The mask is itself a 16-bit pattern, written in decimal, hex, or binary depending on programming software preferences. Use MVM whenever multiple sections of the program write to the same status word and each section needs to update only its own bits.
04

PLC Program · COP file copy

Multi-Parameter Recipe Loader — Block Copy with COP

COP / FLL

The problem: the same packaging machine from Worked Example 1 actually has 10 parameters per recipe, not just one — oven temperature, conveyor speed, fill volume, dwell time, label-applicator pressure, and so on. With five products, that’s 50 stored values. We could write 50 MOV rungs… or one COP rung per product. We’ll go with COP — and add an FLL rung that clears the active recipe to a known state on system start-up.

Memory Map

Address BlockContentsLength
N7:50–N7:59Recipe 1 — Standard (10 parameters)10
N7:60–N7:69Recipe 2 — Premium10
N7:70–N7:79Recipe 3 — Light10
N7:80–N7:89Recipe 4 — Crispy10
N7:90–N7:99Recipe 5 — Frozen10
N7:100–N7:109Active recipe — what the program reads while running10

Inputs & Outputs

INPUTS

I:1/0 — “Load Recipe” pushbutton (with OSR)

I:1/1 — System start-up bit (true for first scan)

N7:0 — Selected recipe number (1–5)

OUTPUTS

N7:100–N7:109 — Active running recipe

B3:0/0 — Recipe-load OSR bit

Ladder Diagram (Six Rungs)

L1 L2 000 First scan I:1/1 FLL — File Fill source 0 → dest #N7:100 length 10 001 I:1/0 OSR B3:0/0 EQU N7:0 = 1 COP — File Copy #N7:50 → #N7:100 len 10 002 B3:0/0 XIC OSR bit EQU N7:0 = 2 COP — File Copy #N7:60 → #N7:100 len 10 003 XIC B3:0/0 OSR bit EQU N7:0 = 3 COP — File Copy #N7:70 → #N7:100 len 10 004 XIC B3:0/0 OSR bit EQU N7:0 = 4 COP — File Copy #N7:80 → #N7:100 len 10 005 XIC B3:0/0 OSR bit EQU N7:0 = 5 COP — File Copy #N7:90 → #N7:100 len 10 N7:100–N7:109 always holds the 10 active parameters of the loaded recipe.

FLL clears the active block on first scan. Five COP rungs (gated by OSR + EQU on recipe number) each transfer 10 words from one recipe block to the active block.

How it works

  1. System powers up. Rung 0’s “first scan” XIC fires. FLL writes 0 into N7:100N7:109. The active recipe is in a known empty state.
  2. Operator sets the recipe selector to 3 and presses LOAD. The button takes I:1/0 high. The OSR fires once and lights B3:0/0 for one scan.
  3. For that one scan, all five COP rungs scan with B3:0/0 true — but only rung 3’s EQU (test “N7:0 = 3“) is also true. The COP on rung 3 fires and transfers N7:70N7:79 (recipe 3) into N7:100N7:109 in a single instruction.
  4. Next scan, B3:0/0 is back to 0. No COP rungs fire. The active recipe stays at recipe 3’s values until the operator presses LOAD again.
  5. Operator selects recipe 5, presses LOAD. Same sequence — COP rung 5 fires once and overwrites the active block with recipe 5’s values.

Why use the OSR instead of the LOAD button directly?

If we put I:1/0 directly into each COP rung, the COP would fire every scan the button is held down — wasted cycles and an unnecessary memory write every scan. The OSR ensures the COP fires exactly once per button press regardless of how long the operator holds the button.

What we learned: COP transfers a whole array of words in one instruction. For an N-parameter recipe, COP replaces N separate MOV rungs with one. FLL is the same idea but writes a constant — useful for clearing a buffer to a known state. The “block of recipe parameters at a known address, COP’d into the active running block on operator selection” pattern is one of the most reused designs in industrial PLC code; you’ll see it in every batch process, every multi-product line, every machine that runs more than one variant.
05

PLC Program · Closed-Loop Control

Tank Level — Proportional Controller from Scratch

P-CONTROL

The problem: a holding tank is filled by a control valve and drained continuously by a downstream pump. We want to hold the tank’s level at a fixed setpoint — say 50 % full — by modulating the inflow valve. Higher level → close the valve more; lower level → open the valve more. We’ll build the simplest possible closed-loop controller: a P-only controller using just SUB and MUL. This is the same idea the PID instruction uses internally, just without the I and D terms.

Inputs & Outputs

INPUTS

F8:0 — Tank level, % (PV, from 4–20 mA level transmitter)

F8:1 — Setpoint, % (SP, from operator HMI)

F8:2 — Proportional gain Kp (tuneable)

OUTPUTS

F8:10 — Error (calculated)

F8:11 — Raw control output (calculated)

O:4.0 — Control valve, % open (CV, to 4–20 mA analog out)

Ladder Diagram (Three Rungs — the Heart of P-Control)

L1 L2 000 — Compute error: E = SP − PV — SUB — Subtract F8:1 (SP) − F8:0 (PV) → F8:10 (error) 001 — Apply gain: CV_raw = Kp × error — MUL — Multiply F8:2 (Kp) × F8:10 (error) → F8:11 (CV_raw) 002 — Clamp output to 0–100 % range, then write to analog out — LIM 0 ≤ F8:11 ≤ 100 MOV — Move (in-range only) F8:11 → O:4.0 (analog out) 003 GRT F8:11 > 100 MOV — saturate high 100 → O:4.0

Three rungs implement the entire P-controller: subtract for error, multiply for gain, clamp and write the result to the analog output. (Rung 3 shown for the high-saturation case; a similar GRT-low rung handles negative outputs.)

How it works — a numerical walkthrough

Let’s say SP = 50.0 %, Kp = 2.5, and the tank starts empty (PV = 10.0 %):

TimePV (level %)Error = SP − PVCV_raw = Kp × EValve outputEffect
t = 010.0+40.0+100.0100 % open (clamped)Maximum fill
t = 30 s30.0+20.0+50.050 % openSlowing fill
t = 60 s45.0+5.0+12.512.5 % openApproaching SP
t = ∞~48~+2.0~+5.0~5 % openSteady-state offset!

Notice the steady-state offset at the bottom of the table. With pure proportional control, the controller needs a non-zero error to keep producing a non-zero output — and that non-zero output is necessary to balance the continuous drain on the tank. The result: PV settles a few percent below SP, never quite reaching it. This is a fundamental limit of pure P-control.

Where I and D come in

The I (integral) term accumulates the error over time and adds it to the output — it slowly increases the valve position to drive the residual error to zero, eliminating the steady-state offset. The D (derivative) term reacts to how fast the error is changing — it brakes the controller’s response if PV is approaching SP rapidly, preventing overshoot. Together with the P term we just built, you get the full PID controller — and modern PLCs wrap all three terms (plus output limits, anti-windup protection, gain scheduling, and tuning interfaces) into a single PID instruction. We’ll meet that instruction properly in a later chapter.

What we learned: closed-loop control is just “compute the error, multiply by a gain, write the result to an actuator” — three lines of math. Building it by hand from SUB, MUL, and LIM gives you complete control and is perfectly adequate for slow, simple, single-variable processes. For fast or multi-variable processes, you’ll graduate to the dedicated PID instruction and its tuning tools. Either way, the underlying idea is the same one you just built — measure, compare, correct, repeat.

Common Student Mistakes

Things to watch out for in this chapter:

  • Mixing file types in a MOV. A MOV from F8:0 (float) to N7:0 (integer) silently truncates the decimal portion. 120.7 becomes 120. Always check that source and destination file types match — or that the conversion is intentional.
  • Using EQU on floating-point values. Floating-point equality is unreliable due to rounding. Two values that should be equal (mathematically) frequently aren’t, due to IEEE-754 round-off. Use a LIM with a tolerance band instead.
  • Forgetting that MOV fires every scan it’s enabled. If the source value is constant and you only want to load it once, gate the MOV with a one-shot. Otherwise the destination gets overwritten every scan — usually harmless but wasteful.
  • Forgetting the # prefix on COP/FLL addresses. Without it, the PLC interprets the address as a single word, not the start of an array. The COP would copy 1 word instead of 10. Different platforms vary; check the syntax for yours.
  • Off-by-one errors on COP length. COP #N7:50 #N7:100 length 10 copies exactly 10 elements (N7:50 to N7:59). It does not include N7:60. Length is a count, not an end address.
  • Using LIM with Low > High accidentally. When Low > High, LIM tests for “outside the range” instead of “inside” — a frequent source of inverted comparisons. If you find LIM behaving the opposite of what you expect, check whether your low and high values are reversed.
  • Forgetting to clamp the output of a hand-built P-controller. Without LIM/GRT/LES rungs to limit the output to 0–100 % (or whatever the actuator accepts), large errors produce out-of-range values that confuse the analog output card or saturate the actuator unsafely.
  • Tuning Kp by raising it until the loop oscillates. A common student method, occasionally appropriate, often catastrophic on real machinery. For mission-critical loops, follow a structured tuning method (Ziegler-Nichols, IMC, lambda) rather than the trial-and-error approach.
  • Expecting a P-only controller to hit setpoint exactly. Pure P-control always leaves a steady-state offset. If “exactly at setpoint” is required, you need the I term — i.e., move to a PI or PID controller.

Quick Recap

The ten things to take away from Chapter 10:

  • PLC memory is organised into files, each holding a specific data type — bits in B, integers in N, floats in F. The file letter tells the PLC how to interpret the bits.
  • MOV copies one value from source to destination every scan its rung is true. Use a one-shot if you only want to copy once per event.
  • MVM copies only the masked bits from source to destination, preserving the unmasked bits. Use it when several program sections own different bits of a shared status word.
  • COP copies an array of N words in one instruction. FLL writes the same value into every element of an array.
  • Comparators (EQU, NEQ, LES, GRT, LEQ, GEQ) sit on the input side of a rung and pass power when their condition is true.
  • LIM tests three values at once (Low, Test, High) and is the cleanest way to ask “is this value inside an operating window?”
  • Recipe selection — five COP rungs gated by EQU on a recipe number — is the standard pattern for multi-product machinery.
  • BCD encoding stores each decimal digit in 4 bits. FRD converts BCD-from-thumbwheel to plain binary; TOD converts plain binary to BCD-for-display.
  • Closed-loop control measures the process variable, computes error against the setpoint, and continuously adjusts the actuator. Key terms: SP (setpoint), PV (process variable), E (error), CV (control variable).
  • A proportional controller is just CV = Kp × (SP − PV) — three rungs of SUB, MUL, and a LIM clamp. Pure P always leaves a steady-state offset; integral and derivative terms (the I and D of PID) eliminate it.

Review & Self-Assessment

Chapter 10 Review Questions

Try answering each question on your own first. Tap to reveal the answer when you’re done.

Q1What is the difference between integer file N7 and floating-point file F8?+
N7 holds signed 16-bit integers in the range −32 768 to +32 767 — whole numbers only. F8 holds 32-bit IEEE-754 floating-point numbers with about ±3.4 × 10³⁸ range and roughly 7 digits of precision — fractional values supported. Use N7 for counts, indices, and integer setpoints; use F8 for analog measurements, temperatures with decimals, calculated rates, and any value that needs a fractional part.
Q2A MOV rung has source N7:5 and destination N7:20, gated by an XIC of an “Enable” bit. The Enable bit stays true for 100 scans. What happens to N7:20?+
N7:20 is overwritten with the value of N7:5 every single scan for all 100 scans. If N7:5 doesn’t change during that period, N7:20 stays at the same value — but the MOV is still performed every scan. If you only want the MOV to fire once when Enable first goes true, put a one-shot in the rung between Enable and the MOV. Otherwise leave it as-is — the repeated MOV is harmless if N7:5 is supposed to track changes in N7:5 in real time.
Q3Explain in your own words what the mask in an MVM instruction does.+
The mask is a 16-bit pattern that controls which bits the MVM copies. Where the mask bit is 1, the corresponding source bit is copied into the destination, overwriting whatever was there. Where the mask bit is 0, the destination bit is left unchanged — its previous value is preserved. So MVM with mask 0000 0000 1111 1111 copies only the lower 8 bits from source to destination; the upper 8 bits of the destination are not touched.
Q4What does a COP instruction with source #N7:50, destination #N7:100, and length 10 actually do?+
It copies 10 consecutive words starting at N7:50 into 10 consecutive words starting at N7:100. So N7:50→N7:100, N7:51→N7:101, … N7:59→N7:109. The contents of N7:50 through N7:59 are unchanged (source isn’t modified); N7:100 through N7:109 are overwritten with the source values. The # prefix tells the PLC to treat the address as the start of an array.
Q5Why is LIM more compact than wiring a GEQ and a LEQ in series?+
A LIM instruction takes three sources (Low, Test, High) and produces one comparison result in a single block. The GEQ + LEQ alternative requires two separate instructions wired in series, plus you have to repeat the test value twice (once in each comparator). LIM reads more naturally — “is this value between 60 and 80?” — and makes it easier to convert hard-coded limits into HMI-editable setpoints. It’s the same logical test, just expressed in one step.
Q6Why should you avoid using EQU on floating-point values?+
Floating-point arithmetic uses approximations under the hood (IEEE-754 binary representation). Two values that should be equal mathematically — for example 0.1 + 0.2 and 0.3 — may not be equal at the bit level due to round-off. EQU does a bit-by-bit comparison and returns false even though the values are conceptually identical. The fix is to use a LIM with a small tolerance band instead: SP − 0.5 ≤ PV ≤ SP + 0.5 reliably detects “PV is at SP” within an acceptable margin.
Q7An operator selects recipe number 4 from a thumbwheel. What sequence of events loads the corresponding 10-parameter recipe into the active running block?+
(1) The thumbwheel hardware presents the digit 4 as BCD bits to an input card. (2) An FRD instruction converts the BCD value to binary and stores it in N7:0. (3) The operator presses LOAD. (4) The button input goes high; an OSR generates a single-scan pulse on a “load trigger” bit. (5) Five COP rungs scan; only the rung gated by EQU N7:0 = 4 sees both the trigger bit and a true comparator. (6) That COP fires, transferring the recipe-4 block (e.g. N7:80–N7:89) into the active block N7:100–N7:109. (7) The rest of the program reads from N7:100 onwards and runs with the new parameters.
Q8In a closed-loop control system, what do SP, PV, E, and CV stand for?+
SP = Setpoint — the desired value, set by the operator. PV = Process Variable — the actual measured value from a sensor. E = Error — the difference, calculated as E = SP − PV. CV = Control Variable — what the controller commands the actuator to do (valve position, heater duty, motor speed, etc.). The controller’s job is to drive E toward zero by adjusting CV based on the current PV.
Q9Write the equation for a pure proportional controller’s output, and explain what each term means.+
CV = Kp × (SP − PV) — i.e., CV = Kp × E. Kp is the proportional gain, a tuneable constant. SP − PV is the error. CV is the control output sent to the actuator. The output is directly proportional to the error: a bigger error produces a bigger correction, and when the error is zero the output is zero. This is the simplest possible feedback controller, implementable with one SUB and one MUL on any PLC.
Q10Why does a pure P-controller leave a steady-state offset, and how is that offset eliminated?+
A pure P-controller produces output proportional to the current error. To produce any non-zero output (which is needed to balance ongoing disturbances like a continuous drain or load), the error itself must be non-zero. So the system settles at PV slightly different from SP — that small steady error is what generates the small steady output. The fix is to add an integral (I) term, which accumulates the error over time and adds to the output. The accumulated integral keeps growing as long as any error remains, eventually producing enough output to drive PV to SP exactly — at which point the error is zero, the integral stops accumulating, and the system holds. This is the I in PID.
Q11A 4-digit BCD thumbwheel switch is set to “0245”. What does the corresponding raw 16-bit BCD word look like, and what binary integer does FRD produce from it?+
The raw BCD word is 0000 0010 0100 0101 — each decimal digit (0, 2, 4, 5) encoded as 4 bits in its own nibble. The FRD instruction recognises this is BCD encoding and converts it to the plain binary integer 245 — which in 16-bit binary is 0000 0000 1111 0101. Notice the bit patterns are completely different even though both represent the same number — that’s why the conversion step is required before doing math on the value.
Q12Compare and contrast open-loop and closed-loop control with one practical example of each.+
Open-loop control sends a command to the actuator without measuring the result. Example: a microwave oven set to “30 seconds at high power” — the magnetron runs at full duty for 30 s and stops, with no measurement of food temperature. The result depends on the food’s starting temperature, mass, and moisture. Closed-loop control measures the result and continuously adjusts. Example: a domestic thermostat — it measures room temperature, compares it to the setpoint, and turns the heating on or off (or modulates it) to drive the difference to zero. The room reaches the requested temperature regardless of weather, draughts, or how many people are in it. Open-loop is simpler and cheaper but can’t compensate for disturbances; closed-loop is more complex but holds the result to a goal regardless of variation.

Need help architecting a recipe system or tuning a closed-loop controller?

Get one-on-one tutoring or design-review help from Dr Ahsan Rahman — Head of Electrical Engineering, with two decades of experience teaching PLC data architecture, recipe systems, and process-control loop design.

Request Consultation →