MOV copies the value of its source (a tag or a constant) into its destination tag — on every scan the rung is true — leaving the source unchanged.
Join 1900+ learners practicing PLC programming
How it works
MOV is ladder logic’s assignment statement. Source in, destination out: the source may be a literal constant (MOV 500 Target_Speed) or another tag (MOV Recipe_Speed Target_Speed); the destination must be a tag, because it gets written. "Move" is a historical misnomer — nothing leaves the source. Every dialect implements it as a copy.
The behaviour that defines how you use it: a true rung executes the MOV on every scan, and a false rung does nothing at all. Both halves matter. The every-scan half means an unconditional MOV is a hammerlock on its destination — an HMI setpoint written by an unconditional MOV snaps back the instant an operator changes it, overwritten within one scan. The does-nothing half means the destination keeps its last value when the rung goes false; a MOV is not an OTE for numbers, and nothing "un-moves" when the condition drops. Recipe logic exploits exactly this: pulse the MOV once (through an ONS) and the value persists.
When the source and destination types differ, Logix converts the value on the way through — DINT to REAL, REAL to DINT — and the sharp edge is REAL-to-integer: the value is rounded (to nearest, ties to even), and values outside the destination’s range fault or clamp depending on platform. Moving between types silently is convenient right up until it hides a precision bug; the conversion instructions (and their rules) get their own page.
MOV also anchors a family: MVM (masked move — only the bits set in the mask are written, for packing bit fields into words), COP/CPS (copy raw memory across arrays and structures, no conversion), and FLL (fill a range with one value). When someone says "just MOV the whole recipe structure", they usually mean COP — MOV proper handles a single value.
Across vendors
| Platform | Name / syntax | Notes |
|---|---|---|
| Allen-Bradley (Studio 5000 / RSLogix) | MOV | MOV Source Dest, converts between numeric types on the way. Relatives: MVM (masked), COP/CPS (raw copy), FLL (fill). |
| Siemens (TIA Portal) | MOVE | MOVE box with EN/ENO and IN → OUT1 (fan-out to multiple OUTs allowed). SCL writes it as an assignment: Target := Source; |
| IEC 61131-3 (CODESYS, OpenPLC) | := / MOVE | Structured Text assignment Target := Source; LD/FBD offer a MOVE box. Strict typing — explicit conversion functions where types differ. |
| Mitsubishi (GX Works) | MOV / DMOV / MOVP | MOV K500 D0 (16-bit), DMOV for 32-bit, and the P suffix (MOVP) executes once on the rung’s rising edge — a built-in one-shot move. |
Mitsubishi’s MOVP pulse variant bakes in what AB programmers build with ONS + MOV. IEC Structured Text drops the pretence entirely: it is an assignment, written like one.
In practice
| Recipe_A_PB ONS_A MOV 1200 Fill_Time | |-----] [--------[ONS]-------------------[MOV]----------| | Recipe_B_PB ONS_B MOV 2500 Fill_Time | |-----] [--------[ONS]-------------------[MOV]----------|
Each button pulses one MOV through a one-shot, loading the fill-time setpoint for that product. The values persist after the buttons release — MOV’s do-nothing-on-false behaviour is the feature. Without the ONS the logic still works here, but the one-shots make the intent explicit and keep the tag writable from the HMI between presses (a held button would pin it).
| Bottle_At_Eye ONS_Cap MOV Flow_Rate Rate_At_Fill | |-----] [----------[ONS]------------------[MOV]--------------| | Fault_Active ONS_Flt MOV Step_Num Fault_Step | |-----] [----------[ONS]------------------[MOV]--------------|
MOV as a snapshot tool: the instant the bottle arrives, the current flow rate is captured into Rate_At_Fill; the instant a fault fires, the sequence step number is frozen into Fault_Step for diagnostics. The one-shots are essential here — a level-triggered MOV would keep overwriting the snapshot with newer values for as long as the condition held, which defeats the purpose of capturing "the value at the moment it happened".
This capture-on-event idiom is one of the highest-value five-minute additions to any machine program: faults become diagnosable after the fact instead of only while they are active.
Gotchas
An unconditional MOV fighting the HMI
A MOV on an always-true rung rewrites its destination every scan. Operators change the setpoint on the HMI, and it snaps back before their finger leaves the screen. Setpoints written by both logic and HMI need an explicit arbitration (one-shot moves on events, or a "logic owns it" mode bit).
Expecting the destination to clear when the rung goes false
MOV is not an OTE for numbers — false rungs do nothing, and the destination holds the last value written. If "condition gone" must mean "value zeroed", add a second MOV (or CLR) on the inverse condition.
Silent rounding on REAL-to-integer moves
MOV converts between numeric types, and REAL → DINT rounds. 2.5 becomes 2 (round-to-even), 2.51 becomes 3. Totals computed from rounded moves drift. Do the math in REAL and convert once, deliberately, at the boundary.
MOV where COP was needed (or vice versa)
MOV handles one value with conversion; COP block-copies raw bytes across arrays/UDTs with no conversion. COP-ing between mismatched structures reinterprets bytes rather than converting values — an INT array COP-ed onto a REAL array produces garbage that looks plausible.
Moving into a tag that something else also writes
Same rule as duplicate OTEs, but for words: two MOVs (or a MOV and a PID output) writing one destination means the last write each scan wins and the loser is invisible. Cross-reference the destination before adding "just one more MOV".
Drop the instruction on a rung in the browser simulator, toggle the inputs, and watch the rung state, accumulator values and outputs update scan by scan.
Questions
MOV copies the value of its source — a constant or a tag — into its destination tag, on every scan where its rung is true. The source is unchanged (despite the name, nothing moves), and on false rungs the instruction does nothing, so the destination retains the last value written.
Every scan the rung is true. If you need a one-time load — recipe selection, capturing a value at an event — put a one-shot (ONS) in front of the MOV, or on Mitsubishi use the pulse variant MOVP. An unconditional always-true MOV effectively locks its destination to the source value.
In Allen-Bradley Logix, yes — MOV converts between numeric types on the way through, so MOV of a DINT into a REAL performs the integer-to-float conversion implicitly. Going the other way (REAL into an integer) rounds the value. IEC 61131-3 platforms are stricter and expect explicit conversion functions such as DINT_TO_REAL.
MOV copies a single value and converts between numeric types. COP copies a block of raw memory — arrays, UDT structures — with no conversion at all, just bytes. Use MOV for one number, COP for whole structures of the same layout, and never COP between different layouts expecting conversion.