Code readingHow-to

Barcode reader sends hex data: convert words to ASCII text

Barcode data arriving as hex words already holds ASCII bytes: convert each word to high and low bytes, read each byte as a character code and rebuild it.

LumaSpec Vision9 min read Share on LinkedIn

On this page 9 sections
  1. 01The bytes are already ASCII: the hex display is only notation
  2. 02What you need
  3. 03Worked example: LG4711 in three words
  4. 04Convert the buffer in five steps
  5. 05Verify with three test labels
  6. 06Four mistakes that turn good reads into garbage
  7. 07Skip the conversion: read a string instead of words
  8. 08From raw words to a string the line can use
  9. 09Questions

A barcode reader on a Profibus link does not hand the PLC a string; it fills a block of input words, and the word monitor shows them in hex: 16#4C47 where the label prints LG. Nothing is broken. Each word already carries two ASCII character codes, and the only real work is splitting bytes and copying them. This guide walks through the split, the character mapping, the trim of terminators and padding, and the three test labels that prove the logic before the line runs.

The bytes are already ASCII: the hex display is only notation

Split the word and read it as two byte values. The high byte 16#4C is 4 × 16 + 12 = 76, and character code 76 is L. The low byte 16#47 is 4 × 16 + 7 = 71, the code for G. The buffer arrived as ASCII text; the monitor prints raw bytes in hex because a fieldbus I/O image moves bytes, not text. No base conversion runs anywhere, and no 256-entry lookup table is needed where the runtime can move a byte into a string position directly. If a table is unavoidable, 95 entries cover the printable range, bytes 32 to 126.

low byte = word AND 16#00FF (word mod 256) high byte = (word - low byte) / 256 (word div 256) character = the printable symbol for that byte value, valid for 32 to 126

The bytes around the text explain why setup tools lean on the hex display: a configured prefix, a CR or LF suffix and, on some fieldbus profiles, status and counter bytes share the buffer with the code. Treat code bytes and framing bytes as one stream, trim at the end, and the text falls out clean.

What you need

Four facts remove every guess from the logic:

  • Data area. The start address and word count of the reader's block in the I/O image, from the fieldbus or gateway configuration.
  • Output format. The fixed data length and any prefix or suffix, such as CR (16#0D) or LF (16#0A). The setting lives in the reader's own configuration, next to its interface settings.
  • A test label. Write LG4711 on paper. It mixes uppercase letters with digits, exactly what the byte order test needs.
  • The symbology. Code 128 and QR codes arrive as plain character bytes. Code 39 with full ASCII conversion sends a two-byte pair for some characters, covered among the mistakes below.

If the trigger line or an I/O module for the reader is still on the bench, the code reader accessories category carries light boards, protective covers and I/O modules for that wiring stage.

Worked example: LG4711 in three words

Print LG4711 and trigger one read. Six characters at two bytes per word fill three words, and every byte lands in the printable range:

Characters Word High byte Character Low byte Character
L G 16#4C47 16#4C L (76) 16#47 G (71)
4 7 16#3437 16#34 4 (52) 16#37 7 (55)
1 1 16#3131 16#31 1 (49) 16#31 1 (49)

The arithmetic, worked once per distinct byte: 16#34 = 3 × 16 + 4 = 52, and 52 is the character 4, because digits run from 16#30 = 48 for 0 up to 16#39 = 57 for 9. Rebuilt in stream order, the buffer reads LG4711, six characters long. A reader set to append CR LF adds a fourth word, 16#0D0A - decimal 13 then 10 - and the trim step drops it.

Five ranges cover nearly everything a barcode contains:

Byte values Decimal Characters
16#30 to 16#39 48 to 57 digits 0 to 9
16#41 to 16#5A 65 to 90 uppercase A to Z
16#61 to 16#7A 97 to 122 lowercase a to z
16#20 32 space
16#0D, 16#0A 13, 10 CR, LF

Convert the buffer in five steps

  1. Capture one known read. Trigger the reader on the LG4711 label and copy the data words from the input image into a work buffer, so the live link cannot overwrite them while you test.
  2. Settle the byte order once. If the first word shows 16#4C47, the first character of each pair sits in the high byte; if it shows 16#474C, the gateway streams low byte first. Pick the split that matches and apply it to the whole buffer, never per word.
  3. Split every word. The high byte is the word divided by 256 and truncated; the low byte is the remainder, or the word masked with 16#00FF. Three words become six bytes for this code.
  4. Copy each byte into its string position, in stream order. Byte i of the buffer goes to position i + 1, and the byte moves unchanged, because its value already is the character code.
  5. Trim the tail. Find the first byte below 32 - CR, LF or NUL - or, on space-padded fixed-length fields, count back over the trailing 16#20 bytes, then set the string length to the last printable character. The result compares and parses cleanly downstream.

Verify with three test labels

Run three reads before the logic goes live; each label targets one failure mode:

  • All zeros, 0000. Every byte must read 16#30. If a four-digit code instead arrives as two small words such as 16#47 and 16#11, the reader is sending BCD, two decimal digits packed per byte; split each byte into two nibbles and add 16#30 to each nibble to build the characters.
  • Mixed case. A code with a lowercase letter: lowercase runs 16#61 to 16#7A, so a byte of 16#68 (104) must print as h. An H in its place means something upstream shifts case, and string comparisons will drift later.
  • Length. Count printable bytes against the symbology: characters equal two per word, minus terminator and padding bytes. A mismatch usually means a prefix byte such as STX (16#02) sits in front of the code.

Four mistakes that turn good reads into garbage

  • Subtracting 16#30 from every byte. 76 - 48 = 28 puts a control code where L belongs. Reserve that subtraction for turning one digit character into its numeric value.
  • Trusting the manual's byte order without the label test. One swapped pair turns LG4711 into GL4711 - right characters, wrong order, no match.
  • Mixing conventions. Half the buffer split high byte first and half low byte first produces text that decodes but never compares. The convention from step 2 belongs to one device, so keep one conversion block per reader.
  • Counting Code 39 full ASCII pairs as two characters. A symbol prefix plus a letter encodes one extended character, so two bytes can be one character of text, and the length check must count such pairs as one.

The same symptom on a serial link - words where text should be - has a documented field fix in a barcode reader hex-to-ASCII walkthrough for a legacy PLC platform, worth reading before the logic is rebuilt from zero.

Skip the conversion: read a string instead of words

A fieldbus word image is not the only route into the PLC. Set the reader's output format to send the decoded string with a terminator over serial or Ethernet, and the buffer arrives as characters - no split, no trim. The serial, USB and Ethernet input paths a scanner can take compare those routes, and wiring the reader as a TCP server with the PLC as the client shows the socket version. An implicit I/O assembly on EtherNet/IP moves the same byte stream as words, so the split from this guide applies there too.

If the station is still on the drawing board, choose a reader that talks Ethernet from the start: the decode result crosses as data you can read as text, and the conversion loop never gets written. Both readers below read 1D and 2D codes and connect over Fast Ethernet or GigE:

Fixed code readersHikrobot MV-ID3013PM-12M-WBN 12mm focal length 1.3 MP Compact Industrial Code ReaderMV-ID3013PM-12M-WBN
Interface
Fast Ethernet
Resolution
Up to 3 MP
$1,979.00View part
Fixed code readersHikrobot MV-ID813M-05S-WBN-SR 1.3 MP resolution, 4.9 mm focal length, White light, SR, GigE, Static cableMV-ID813M-05S-WBN-SR
Interface
GigE
Resolution
Up to 3 MP
$719.00View part

MV-ID3013PM-12M-WBN is the compact Fast Ethernet model. MV-ID813M-05S-WBN-SR runs on GigE and carries its own white light. Deeper reading on the reader side sits on the code-reading topic page.

From raw words to a string the line can use

Once the conversion runs, the string is ready for real work. Store it the way storing ASCII barcode strings in PLC memory: bytes, words and clears lays out, split it into lot and part numbers as in parsing barcode string data into fields, or hold two readers against each other with string comparison logic in the PLC. Plan the whole path - trigger, data format, handshake, error handling - before writing logic; the reader-to-PLC communication planning checklist puts those decisions in order.

For hardware, the fixed code readers category lines up every interface and resolution filter side by side, and the code reader finder narrows the list by trigger and mounting needs:

Code readers & vision sensorsFixed code readers

1D/2D codes on the line

658 models · from $399.00

When a conversion or a handshake still misbehaves after these checks, send the word list and a photo of the label through the contact page and the applications team will read the buffer with you.

Questions

Why does a barcode reader send hex instead of ASCII text?

The link moves bytes and the monitoring tool displays bytes, so the buffer shows up as hex words whether or not it holds text. Decode data itself is ASCII bytes; extra bytes around it - a configured prefix, a suffix such as CR or LF, and status or counter bytes the fieldbus profile adds - are why a setup tool may present everything in hex by default.

How do I recognize BCD data instead of ASCII in my words?

Read a code you know, such as 4711. ASCII digits arrive as 16#34, 16#37, 16#31, 16#31; BCD arrives packed, two decimal digits per byte: 16#47, 16#11. For BCD, split each byte into two nibbles and add 16#30 to each nibble before building the string - small values that never reach 16#30 are the tell.

Does byte order differ between readers on the same PLC?

It can, because word byte order comes from how each reader or gateway maps its serial buffer into the I/O image, not from the codes themselves. Two devices on one bus can legitimately disagree. Test every reader with its own known label and keep one split convention per device instead of copying the same conversion block everywhere.

Can the HMI do the conversion instead of the PLC?

Often yes: HMI and SCADA software can address the raw buffer and format each byte as a character, the same split this guide describes. The trade-off is that the PLC never sees a clean string, so comparisons, archiving and MES hand-off lack the text. Converting in the PLC once and passing the string on keeps one copy of the logic to maintain.

What if the code length changes from label to label?

Set the string length from the terminator or the first non-printable byte rather than from the fixed buffer size, and one loop then handles a three-character code and a twenty-character code alike. Size the buffer for the longest code the symbology allows - Code 128 can carry more than forty characters - and let the trim step do the rest.