Fix an HMI string compare that never matches the PLC string

8 min read · Published November 14, 2026

An HMI string compare fails because a fixed-size ASCII field accepts only even character counts and pads the unused bytes with spaces: a 7-character code arrives as 8 bytes with a 20 hex space on the end. Trim both operands and compare, or use a string find guarded by match position 0 and equal trimmed lengths, then pulse the recipe trigger one scan after the index is set.

An HMI string compare that never matches usually has nothing to do with the recipe logic. A fixed-size ASCII field on the panel accepts even character counts only and fills the unused bytes with spaces. A 7-character part code arrives as 8 bytes with a space at 20 hex (32 decimal) on the end. A byte-for-byte compare against the 7-byte key stored in the PLC fails on every scan, while both strings look identical in the data view. Trim both operands before the compare, or locate the code with a string find and guard the hit by position and length. Then write the recipe index and pulse the panel's write trigger one scan later. With the recipes stored in the PLC, the compare, the search and the copy become ordinary ladder logic and the screen constraint disappears.

Why does an HMI string compare never match the PLC string?

The compare fails on trailing space bytes, not on the text. A 7-character code in an 8-character ASCII field arrives as 8 bytes with a 20 hex space on the end. It never equals the 7-byte key stored in the PLC.

The panel sizes ASCII data objects in even character counts only, so no odd-length code ever fits a field exactly. Whatever room is left gets filled with space characters. The data view on the programming tool hides trailing spaces, so the received value and the stored key read identically on screen while their byte counts differ by exactly the padding. A compare instruction works on all the bytes, so one 20 hex byte at the end defeats it every time. The cure confirms the diagnosis: strip the spaces and the compare starts matching on the next scan.

What do the symptoms tell you?

Read the symptoms and the cause names itself. A compare that stays false while the data view shows identical text points to padding. A compare that fails only after a scan points to the scanner. A compare that broke after a field resize points to the new size.

  • Compare stays false, data view shows identical text. The display drops trailing spaces. Read the string length on both operands and compare the two numbers instead of trusting the screen.
  • Panel-produced strings fail, PLC-to-PLC compares pass. The padding is created on the panel side of the write, so that is the operand to trim.
  • A scan never matches but a keyed-in test string does. The scanner appends a terminator after the code, most often a carriage return at 0D hex (13 decimal).
  • It matched until someone widened the ASCII object. A wider field means more padding bytes over the same text, so every compare against that tag dies at once.

One test separates all four causes: dump the received string as bytes, which the checks at the end of this article show.

Example: how many space bytes does an 8-character field add to a 7-character code?

One space byte. The panel rounds a 7-character code up to the next even size, 8 characters, and fills the unused byte with a 20 hex space. The received string is 8 bytes against a 7-byte key, so the compare is false before the text is even read.

A packaging line keeps 80 recipes, each keyed by a 7-character code such as A123456. The panel's ASCII object is set to 8 characters, the next even size above 7.

  • Code as scanned: A123456, 7 bytes.
  • Field size: 8 characters, so 8 - 7 = 1 unused byte, filled with one space at 20 hex.
  • Received string: A123456 plus one space, 8 bytes.
  • Stored key: A123456, 7 bytes.
  • Compare: bytes 1 through 7 are equal, byte 8 is 20 hex on one side and missing on the other, so the result is false on every scan.
  • After the trim: 7 bytes against 7 bytes, the compare is true, and the matched record number becomes the recipe index.

The same code in a 12-character field carries 12 - 7 = 5 trailing spaces and fails the compare the same way; the trim still returns 7 bytes. That happens when a longer string type is picked for headroom.

Strings that travel as packed words hide the difference too. Two characters occupy one 16-bit register, so the padded 8-byte field and the trimmed 7-byte string both sit in 4 registers, the last one half empty. Byte counts catch what register counts equalize. The same packing arithmetic puts a 12-character barcode in 6 registers, as packing an ASCII string into V-memory words for an HMI tag works through step by step.

How do you trim the padding before the compare?

Trim both operands, then compare. Copy the panel-produced string to a scratch string, run the trim instruction (STRTRIM in the Do-more instruction set strips leading and trailing spaces) on each side, and compare the trimmed results, where a 7-byte code finally equals its 7-byte key.

  1. Copy the panel's value into a scratch string, scan_string (illustrative name), sized 12 characters and initially empty, so the compare never runs against a tag the panel is still writing.
  2. Trim it. STRTRIM strips the leading and trailing spaces and writes the result to trimmed_scan.
  3. Trim the stored key once, at program setup, into trimmed_key. A key entered through the panel carries its own padding.
  4. Compare trimmed_scan and trimmed_key for equality. On a true result, move the record number into the recipe index tag recipe_index.
  5. Set a no-match fault bit no_match_fault when nothing compares true, so an unknown scan stops the sequence instead of leaving the previous recipe loaded.

STRTRIM removes spaces only. A scanner carriage return at 0D hex (13 decimal) survives the trim, so if the hex dump showed one, clear the scanner's terminator or suffix setting, or cut the string down to the known code length before trimming. Trim both sides whenever the panel or the scanner produced either operand. A compare between two PLC-generated, length-controlled strings needs no trim at all.

When does a string find beat an exact compare?

Use a string find when the payload arrives framed or padded beyond a simple trim. STRFIND locates the code inside the received text, and the match counts only when it starts at position 0 with the trimmed lengths equal, so 7-character A123456 can never match A1234567.

A find tolerates whatever sits around the payload: padding, a terminator, a fixed prefix. Run the find, take the start position, then apply two guards before accepting the hit: the position must be 0 and the trimmed lengths must be equal. Without the guards, a 7-character code matches inside any longer code that contains it.

Method Fails on padding False-match risk Use when
Exact compare, untrimmed Yes None Both operands are PLC-generated and length-controlled
Trim, then compare No None One operand comes from the panel or a scanner
Find with position-0 and equal-length guards No None The payload carries framing a trim cannot remove
Find without guards No Real: A123456 matches inside A1234567 Never

The same instruction family handles variable-width serial input; parsing variable-width ASCII strings in a Do-more PLC covers the delimiter side for scanners wired to a serial port.

How do you trigger the recipe load once the strings match?

Write the matched record number into the recipe index tag first, then pulse the panel's write trigger one scan later, so the index is stable before the transfer executes. Pulsing on the same scan can move a half-updated index into the load.

The panel's Recipe Button object accepts a PLC trigger: enable the Write Event Tag check box and assign the pulse bit. Under the Recipe tab, select the Multiple Source Recipe type and the Recipe Sheet, and leave the recipe selection itself on a tag so the same button serves all 80 recipes.

One constraint decides the sequence: the transfer executes only while the screen holding that button is displayed. Two panel features get you there from the PLC. The Event Manager evaluates a tag and runs a Screen Change action, or the PLC to Panel Settings page lets the PLC write the target screen number straight into the panel's screen number register. The full sequence reads: scan, match, index write, screen change, a short settle, the one-scan pulse, transfer check, back to the run screen. Skip the rescan-to-load arrangement, where the first scan changes screens and the second loads, because it depends on operator timing and fails quietly.

The cleaner architecture removes the constraint altogether: keep the recipes in the PLC. Allocate the archive as a fixed-stride block, record n starting at base + n x stride, keep the stride constant even where fields go unused, and hold the key strings in a parallel array, one entry per record. The trimmed compare or the guarded find searches the key array and returns the pointer, and an indirect copy moves the record into the working registers the machine logic reads. The panel becomes the editor that writes new and changed records into the archive through the same pointer. Nothing in that path cares which screen is showing.

Treat the pulse like any panel write: trigger, wait for a PLC-side confirmation, then release the machine. fixing an HMI numeric entry handshake the PLC never completes shows the same confirm pattern from the failing side.

Recommendation: store the recipes in the PLC and let the panel edit them. Trim both operands and run the exact compare for scans that deliver the bare code; reach for the string find only when framing rides along, and then only with the position-0 and equal-length guards. Write the index first and pulse the panel's write trigger one scan later, and hold the machine until the copied record has been checked against the archive.

How do you check the compare is fixed?

Check bytes, not pixels. Read each operand's length with the string length instruction. Seven against 8 proves padding survives. Seven against 7 after the trim proves the compare now tests the code. A deliberately wrong code must still return false.

  1. Log the string length every scan. Eight on a 7-character code is padding; nine or ten is padding plus a scanner terminator.
  2. Dump the tail bytes as hex after a scan. 20 hex (32 decimal) bytes are the padding; a single 0D hex (13 decimal) byte after the code is the scanner's carriage return.
  3. Run the negative test: scan a code that matches no recipe. The compare must stay false and the no-match fault bit must set.
  4. After the pulse and transfer, compare the working registers against the archive record before any machine step consumes them, and return the panel to the run screen only after that check passes.

That sorts every case. Two PLC-generated strings compare directly with no trim. A panel- or scanner-produced string gets trimmed on both sides and compared. A framed payload gets the find with both guards. And the load itself waits for a stable index, a displayed screen or a PLC-resident archive, and a verified copy.

Questions

What size should the ASCII object be so padding stays small?

Set the field to the next even character count at or above your longest code, because the panel offers even sizes only. A 12-character code fits a 12-character field with zero padding bytes; a 13-character code needs 14 characters and always carries one trailing space, which the trim removes on the PLC side. Size for the longest code you will ever scan, then trim every operand before a compare.

How do I stop the barcode scanner from adding characters?

Set it in the scanner, not the PLC. Scanner configuration menus have a suffix, terminator or postamble setting that appends a carriage return (0D hex, 13 decimal) or another control byte after each read; clear it, or set the terminator to none, so the scan delivers the code alone. If another device needs the terminator, cut the received string down to the known code length before the compare.

Will the recipe transfer run if the button's screen is not displayed?

No. The trigger tag is acted on only while the screen holding the Recipe Button object is displayed, so a pulse fired from any other screen does nothing and the load silently never happens. Either sequence a screen change first, through the Event Manager or a PLC-written screen number, or store the recipes in the PLC, where the load runs independent of whatever the panel is showing.

What happens if two recipes carry the same key?

A search stops at the first match, so the wrong record can load. Keep keys unique when records are created, and count matches in the PLC: if the find or the compare loop reports more than one match, set a fault bit and refuse the load until an operator resolves the duplicate. A no-match fault catches unknown codes; a multiple-match fault catches duplicate ones.

How do recipe slots get reused after an operator deletes one?

Keep a validity bit per record and allocate the first clear bit for the next new recipe. The deleted slot stays physically in the block as a gap that no logic reads, and every externally stored index keeps pointing at the right record. Avoid compacting the block downward, because any index printed on a traveler or saved in a log points at the wrong recipe after the shift.

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