Two HMI lookup text fields show the same message when their registers hold equal values, because both fields resolve the same key in one shared message database. Keep the first field on its raw register, compute a derived register for the second as value plus an offset, and choose the offset so the two key ranges cannot overlap: offset = (highest first-range value) minus (lowest second-range value) plus 1. Then test the equal-value case and the range endpoints before the line runs.
Two HMI lookup text fields print the same message whenever their registers happen to hold equal values, because both fields resolve the same key in one shared message database. The fix is separate keys, not new wording. Keep the first field on its raw register, compute a derived register for the second field as source value plus an offset, and size the offset so the two key ranges cannot overlap: offset = (highest first-range value) - (lowest second-range value) + 1. With states 0 to 7 in V2000 and fault codes 0 to 4 in V3000, an offset of 10 puts the derived register V3001 between 10 and 14, above the state range, so a value of 1 in both registers still shows two different messages. This page gives the offset rule, the symptoms, the worked arithmetic and the tests to run before the line starts again.
Why do two HMI text fields show the same message?
A lookup text object resolves one register value to one message entry, and when two fields read registers that can hold equal values, both fields hit the same key and the shared message database hands back the same text for both.
That is the documented job of the object: it displays the message that corresponds to the value in a tag register. One table, one key space. The collision lives in value space, not address space: V2000 and V3000 are different addresses, but a 1 stored in each is the same key. If both objects draw on one message database, or on two tables keyed over the same values, equal values print equal text.
Duplicated keys inside one table are a second trap: a search that scans for a key stops at the first match, the behavior documented for array range searches that return the first match index, so the second entry becomes dead text and the first entry decides what the operator sees. Give every key one meaning per field.
How do you separate two fields that share one message database?
Keep the first field on its raw register and feed the second from a derived register that the PLC computes as the second value plus an offset, so the two key ranges cannot collide even when the source values are equal.
In the classic form the rung is V3001 = 10 + V3000. The second field's object reads V3001 and its message table carries entries keyed 10 and up; the first field stays on V2000 with entries keyed from 0. The database now never sees one key asked to serve two fields.
The fix has two halves, and both are required. Moving the object to V3001 without the rung just renames the collision, and adding entries under the new keys without the rung changes nothing on screen. Wire both halves: the rung computes the key, and the re-keyed table translates it into text.
How large must the offset be?
Take the offset equal to the highest value the first field's register can reach, minus the lowest value the second register can reach, plus 1; that places the derived range entirely above the first range and leaves no shared key.
As a formula: offset = max1 - min2 + 1, where max1 is the largest valid value in the first field's range and min2 the smallest in the second's. The check is one line: derived minimum = offset + min2 = max1 + 1, strictly above max1. Any larger offset also works; a rounder number just leaves spare keys.
Then check the top end. A 16-bit word register holds 0 to 65,535 unsigned or -32,768 to 32,767 signed, so the largest derived key, offset + max2, must stay inside that span. Matching each operand's data format is the rung-level rule to apply, because a signed constant dropped into an unsigned slot corrupts the key quietly.
When the upward offset will not fit because both ranges are wide, invert it: renumber the first field's keys into a high block by adding K = max2 - min1 + 1 to every first-field key and its entries, and leave the second field raw. Check: the first field's lowest key becomes max2 + 1, still clear of the second range, and the new top key max1 + K must fit the register format.
What do the symptoms point to?
Four symptoms cover nearly every case: matching values produce matching text, the second field mirrors the first, part of the second range shows nothing, and the text sits one offset away from the truth; each points to a specific mapping fault.
- Both fields change to the same text whenever the registers hold equal values. One shared key space. Apply the offset fix.
- The second field mirrors the first even when the registers differ. Both objects still read the same register. Check which address the second object is bound to.
- Part of the second field's range shows nothing at all. Those derived keys have no message entry. Count the entries against the reachable values.
- The wording is right but the message is for a neighboring value. The object reads the offset register while its table holds raw keys, or the reverse. Read the live derived register and compare it with the table's first and last keys.
Where should the offset calculation run?
Run the offset calculation in the PLC as one extra instruction writing to the derived register, so the key stays correct whether the panel is running, and keep the second field's original register untouched for the rest of the logic.
One add instruction per field is the whole cost. Computing the key in the PLC keeps it correct while the panel reboots or reloads its project, the same reasoning as keeping PLC schedules running when the HMI panel is offline. Pick a register the rest of the project does not touch, and write the offset result only there: V3000 keeps its process value for trends, logic and every other screen that reads it.
Keep the offset out of any number the operator reads. An operator who sees fault 11 for fault code 1 stops trusting the screen. If the true code must appear beside the message, embed the raw register inside the message string or add a small numeric field reading V3000, and avoid the display-transform traps covered in fixing an HMI value that shows ten times too small.
Worked example: what offset separates states 0 to 7 from fault codes 0 to 4?
With states 0 to 7 in V2000 and fault codes 0 to 4 in V3000, the smallest safe offset is 8, giving V3001 = 8 + V3000 a range of 8 to 12; the rounder 10 keeps 8 and 9 free for two more states.
The arithmetic, step by step:
- Offset: 7 - 0 + 1 = 8 minimum; choosing 10 leaves keys 8 and 9 spare for future states.
- Derived range: 10 + 0 = 10 up to 10 + 4 = 14. Five keys, five entries.
- Overlap check: the state range tops out at 7 and the fault keys start at 10, so no key is shared.
- Equal-source case: V2000 = 1 and V3000 = 1. Field one resolves key 1, field two resolves key 11, two different messages out of one database.
- Format check: the largest key is 14, far inside a 16-bit register's 65,535.
Decision: use 10 when the machine may grow to states 8 and 9; use 8 when the state list is closed. Either way the second field needs exactly 5 entries, keyed 10 to 14, or 8 to 12.
How do you test the fix before the line runs again?
Test the equal-value case first, then the range endpoints, because those are the only points where a wrong offset can still collide; run them with the machine in a safe commissioning state and record value, key and displayed text.
Set the test values with the machine keyed out or in an approved commissioning mode, because machine logic may act on the registers you write. Force, observe, restore.
| Test | Values set | Expected result |
|---|---|---|
| Equal sources | V2000 = 1, V3000 = 1 | state 1 text in field one, key 11 text in field two |
| Distinct sources | V2000 = 6, V3000 = 0 | each field follows its own table |
| Endpoints | V3000 = 0, then V3000 = 4 | keys 10 and 14 both resolve in field two |
| Unmapped key | V3000 = 5, if reachable | record what the project shows, and decide whether logic must block that value |
If the derived register never changes after you force V3000, the second object is probably bound to an address that ignores PLC writes; work through fixing an imported HMI tag that ignores PLC register writes before touching the offset again.
Should you number the keys in blocks instead of adding an offset?
Numbering each field's keys in its own block, states as 0 to 99 and fault codes as 1000 to 1099, does the same job as an offset and is easier to read later, when you control the PLC code from the start.
This is the convention behind banners keyed from 1000 upward, 1000 for stopped and 1001 for spare. It scales cleanly: give each new field a fresh block wider than its range and the collision question never returns. The same one-line check applies: the second block's start must sit above the first block's end, so 1000 above 99 works and 90 above 99 does not.
Choose blocks when you are writing the PLC program anyway, before commissioning. Choose the offset rung when the program is already running and you want the smallest change that cannot disturb tested logic, which is the case in the worked example above.
What do you write down so the collision stays fixed?
Write the chosen offset, both valid ranges, and the derived register into the project notes, so the next edit cannot reuse the register or add an unshifted key that collides again.
Keep three lines in the project file: the derived register's address, purpose and format in the register map; the valid range of each field, so the next engineer can re-run the one-line overlap check; and the rule that new entries for the second field take offset keys, never raw ones. Keep a trial offset only after the full range check, because a constant that separates one test pair can still collide at an endpoint nobody tried.
Recommendation: for any two lookup text fields that draw on one shared message database, keep the first field on its raw register, compute the derived register in the PLC as second value plus offset, with offset = (highest first-range value) - (lowest second-range value) + 1, point the second field at the derived register, and add one message entry per derived key. Use a rounder offset only to leave spare keys, renumber the first field's keys into a high block when the upward offset would push the largest key past 65,535, and verify the equal-value case plus both range endpoints before the line runs again.
Questions
Can the HMI panel's own internal registers hold the derived key?
Yes in many projects. Most HMI lines provide internal or temporary addresses alongside the PLC data table, intended as scratch variables, and a lookup object can read them like any other register. The trade-off is location: a value stored only in the panel disappears from the machine's own data map, so record the address in the project notes either way. Check your configuration software's address list for the internal range before you pick one.
How many message entries does the second field need?
One per reachable derived key. The count is the second field's span plus 1: a fault register that runs 0 to 4 needs 5 entries, whatever the offset is, because the offset moves the keys without changing how many there are. Number them from the first key upward and leave no gaps inside the span, then any value outside the valid range is a key you have deliberately chosen not to map.
Does the offset change any other screen that reads the same register?
No, as long as the original register is untouched. The offset result lives in a new address, so every other screen, trend and logic rung that reads the original register keeps seeing the true process value. The risk runs the other way: if someone later points another lookup field at the derived register, its table must be keyed to the offset range, or it inherits the same collision problem in reverse.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.