Make an HMI pot read and write a PLC V-memory value

9 min read · Published November 11, 2026

Point an HMI pot's remote position source straight at a writable PLC address and one control reads and writes it. Keep the zero offset, the clamp and the 0-4095 scaling in the ladder, because the URL field does no math, and switch the representation to signed 16-bit when values go negative.

A pot that only sends numbers into the PLC is half a control. Set the same pot to follow the PLC as well, and the operator's pointer and the register can never disagree. The direct way is to point the pot's remote position source at a writable PLC address and leave every bit of arithmetic to the ladder: the zero offset, the clamp and the scale to a 12-bit count. This page sets up a 0 to 10.0 V pot that drives a 0-4095 BCD count at V4000, works the arithmetic through at a real setpoint, and fixes the two places the simple version breaks: an offset that pushes the count past full scale, and negative values that a BCD word cannot carry.

How do you make an HMI pot read and write the same PLC value?

Point the pot's remote position source at a writable PLC address, such as the real 0 to 10.0 at V2000, and the pot becomes fully reciprocal: the pointer follows PLC-side changes and an operator move writes the same address back.

The position source is the pot's write path. The rule in the setup manual is blunt: Edit Connections is not the path for a control object to reach its controlled data member; it is there for reading data members. With the URL on the position source there is one path, one writer and nothing to wire in reverse.

The other route, a scaled database point wired to the pot in both directions, also works and keeps its place in projects that already scale there. For a control object, the URL is the cleaner of the two: the scaling lives in ladder rungs you can open and test, and no second writer exists to disagree with the first.

What do you need before you start?

You need the link name your HMI project already uses for the PLC, two free words at V2000 and V2001 for the real, one BCD word at V4000, a pot face at minimum 0, maximum 10 and resolution 0.1, and the zero value.

  • The link name exactly as the project's PLC link prints it, because the URL is that name, the address and a representation code joined by full stops.
  • Two free words at V2000 and V2001: a real is a two-word value.
  • One BCD word at V4000 for the scaled count. A 16-bit BCD word holds 0000 to 9999, so the 0-4095 count fits with room over.
  • The zero, 2.0 in the example below, in a register the ladder can read.
  • Ladder room for the offset add, the clamp and the scale rungs, with the multiply and divide in their 32-bit forms.
  • A machine state for the first live test where a changed setpoint cannot move anything.

How do you point the pot at a writable PLC address?

Set the pot's position source to Remote, enter the PLC URL with the representation code the ladder expects, and keep every arithmetic step in the ladder, because the URL field passes the stored value through and accepts no math.

  1. Create the pot control in the project (Object > Create > Control > Pot in the desktop HMI package this setup was built on).
  2. Set the pot's position source to Remote.
  3. Enter the URL in three parts: the link name, the address and the representation code, in the form yourlink.V2000:R, where yourlink stands in for the name the project prints. The :R code passes a signed real, which matches a 0 to 10.0 engineering value stored in two words.
  4. Set Minimum to 0, Maximum to 10 and Resolution to 0.1. The 0.1 step matches one decimal place, so the pot face reads volts directly.
  5. In the ladder, read the real, add any offset and scale. The sequence, in the mnemonics of the PLC family this setup comes from, is LDD V2000 (load the real), MULR R10 (multiply by 10.0, through a real register if your instruction set takes no real constants), RTOB (real to BCD), MUL K4095, DIV K100, OUT V4000. Multiplying by 10 moves the decimal place into a whole number, and the divide by 100 removes it again after the 4095 scale.
  6. Run the multiply and the divide in their 32-bit forms: 100 × 4095 is 409500, and a signed 16-bit word tops out at 32767.

Order matters inside the scale rung. Multiply before divide keeps every count: 50 × 4095 ÷ 100 lands on 2047. Divide first and 50 ÷ 100 is 0 in integer math, so the whole span collapses to zero. An independent write-up of the same trap, why PLC scaling wants the multiply before the divide, works the truncation through step by step.

Where does the zero offset go?

Add the zero in a ladder rung on the engineering value before the conversion, so a pot that reads 5.0 with a 2.0 zero puts 7.0 into the scale rung, and keep the convention written once where every rung sees it.

The zero is the process value that reads 0 on the pot face. Keep one rule: the register gets the pot entry plus the zero, and the pot shows the register minus the zero. Store the zero in its own register so re-zeroing the machine is one move, and put the add ahead of the conversion rung. The URL field cannot help here: it carries a link name, an address and a representation code and no arithmetic, and a symbolic link only re-references an address and stays read-only, so it cannot add the offset either. Check the convention against one known pair before you enable writes: pot 5.0, zero 2.0, register 7.0. The same offset idea on the reading side is in removing an offset in HMI scaling with PLC raw counts.

Worked example: what does a 5.0 V pot entry write into V4000?

The operator moves the pot to 5.0 with a 2.0 zero, so the rung converts 7.0 and V4000 ends at 2866 BCD: 70 × 4095 = 286650, 286650 ÷ 100 = 2866 with the 0.5 truncated, and 2866 is the count the analog hardware receives.

  • The pot writes 5.0 into V2000 as a real.
  • Offset rung: 5.0 + 2.0 = 7.0.
  • Scale rung: 7.0 × 10 = 70, real to BCD, 70 × 4095 = 286650, 286650 ÷ 100 = 2866.5, stored as 2866.
  • V4000 holds 2866 in BCD, one word.

The same rung at the pot's ends: entry 0.0 converts 2.0 and lands on 819, so full left sits at the zero value, not at no signal. Entry 10.0 converts 12.0 and asks for 4914, which is where the next section picks up. The divide truncates, so the stored count can sit up to one count low; one count of a 0-4095 value is 10 V ÷ 4095, about 2.4 mV.

How do you handle negative values?

Change the pot URL's representation from :R to :S when the value can go below zero, keep a sign bit beside the word, and run the multiply and divide rungs on positive magnitudes only, because BCD carries no sign and integer multiply and divide corrupt negatives.

The failure the simple build hits: the register should carry -10 (a 10 entry with a -20 zero) and BCD has no sign to store it in. Two moves fix it. Give the pot URL the :S code, which passes one signed 16-bit decimal word, and give the ladder a sign bit.

Read bit 15 of the word: when it is 1, invert the word and add 1 to get the magnitude and set the sign bit; when it is 0, the word already is the magnitude. Route the following rungs through that sign bit as a permissive. Keep the multiply and the divide on magnitudes: addition and subtraction behave with negative operands in these instruction sets, and the multiply and divide rungs do not.

Agree on the word's unit before you wire anything: with the word carrying tenths, 0 to 100 covers the 0 to 10.0 span and the scale rung becomes the same multiply by 4095 and divide by 100, with the real-handling steps dropped. A large-odd-number symptom before any of this usually means the data format at one end of the link, which setting the signed decimal data format when an HMI shows large positive numbers covers.

What stops the count from passing 4095?

Clamp the post-offset engineering value to 10.0 before the conversion rung, because 10.0 on the pot with a 2.0 zero asks for 12.0, and 12.0 × 4095 ÷ 10 is 4914, which no 12-bit register accepts.

4095 is the full scale of 12 bits (2^12 - 1), so there is nowhere above it to store. Put a clamp rung between the offset and the scale: when the post-offset value passes 10.0, move 10.0 in and set a saturation bit; when it drops below 0.0, move 0.0 in and set the same bit. Put that bit on the operator display so a pegged pointer reads as saturation, not as a fault. The face-only alternative is setting the pot Maximum to 8.0 so full right lands exactly on 4095; take the clamp, because it keeps the face in honest engineering units and the bit tells the operator what happened. When a recipe stage must not take setpoint writes at all, block the address the way locking a PLC V-memory value against HMI writes during a stage shows.

How do you check that both directions work?

Test the two legs separately from a safe machine state: force 3.5 into V2000 from other code and watch the pot settle at 3.5, then move the pot to 6.5 and watch V2000 read 6.5 and V4000 read 3480 after the offset and scaling.

Make that first pot edit from the safe state you picked in the setup list, because the moment the write leg works, nudging the pot moves a live register.

  1. Read leg. Change the engineering value from the PLC side, by another rung or a force, from 5.0 to 3.5. The pointer must settle at 3.5. If it holds, the URL address or representation does not match what the ladder writes, or the value sits outside the pot minimum and maximum.
  2. Write leg. Move the pot to 6.5. V2000 must read 6.5 and V4000 must read 3480 (6.5 + 2.0 = 8.5; 85 × 4095 = 348075; 348075 ÷ 100 = 3480). If the pointer moves and the register holds, the write never reached the PLC: check that the address is writable through the URL and that no connection-dialog link is fighting it.
  3. Three-point scale check. Pot 0.0, 5.0 and full right must read 819, 2866 and 4095 with the saturation bit set, in that order.
  4. Sign check, if you run :S. Enter a value below the zero and confirm the display shows the sign bit pattern, not a large positive word.
What you see What it points to
Pointer never moves when PLC code changes the value Read leg: address, representation code, or a value outside the pot minimum and maximum
Pointer moves, V2000 never changes Write leg: address not writable through the URL, or a connection-dialog link on the controlled member
V2000 right, V4000 wrong Scale rung: operand formats, multiply before divide, 32-bit product
Small entry, huge number BCD versus binary mismatch at one end of the link
Negative entry shows as a large positive Sign handling missing: :S plus the bit-15 pattern
Count pegged from mid-range entries Saturation clamp active: check the saturation bit and the pot maximum against the zero

Recommendation: Put the pot's remote position source on the real address (yourlink.V2000:R), keep the face at minimum 0, maximum 10 and resolution 0.1, and leave the offset, the clamp and the ×4095 ÷ 100 scale in the ladder with 32-bit multiply and divide rungs. Move the URL to :S with the bit-15 sign pattern only when the process value can go below zero, and give every V-memory address exactly one writer.

Questions

Do you have to convert the rest of your project to direct URLs?

No. A control object drives its own controlled member through the remote position source, so the pot gets the URL; indicators, trends and recipe fields can keep reading scaled database points. The rule that matters is ownership: one writer per V-memory address. If a reciprocal database connection and a pot URL both write V2000, every fault on that register has two suspects.

What is the difference between :R and :S on a pot URL?

:R passes a signed real and occupies two consecutive words, so V2000 and V2001 carry 0 to 10.0 with the pot's 0.1 resolution. :S passes one signed 16-bit word from -32768 to 32767, which is what you need when the value goes below zero, because a BCD word carries no sign. Match the code to what the ladder reads at that address.

How fine is a 0.1 pot step at the analog output?

One count of the 0-4095 value is 10 V ÷ 4095, about 2.4 mV of span. The pot's 0.1 step is 40.95 counts, about 41, so each pot step moves a 0-10 V output 0.1 V. The integer divide truncates, so the stored count can sit up to one count, about 2.4 mV, below the exact figure.

Why does the multiply by 4095 need 32-bit math?

The intermediate product does not fit in one 16-bit word: 100 × 4095 is 409500 and a signed 16-bit word tops out at 32767. Run the multiply and the divide in their 32-bit forms so the product survives the rung; a 16-bit multiply wraps and the count jumps to a nonsense value mid-scale.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote