Parsing Multiple Data Fields from One Barcode or QR Scan

Brian Holt8 min read
AutomationDirectSerial CommunicationTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

Scanning a single barcode or 2D symbol to retrieve several discrete data items (material type, part number, lot/date code, quantity, operator ID, expiration date) is a routine material-handling and traceability requirement. The scan event delivers one continuous ASCII string over the scanner's serial, USB, or Ethernet/IP interface; the PLC must then split the string into individually addressable fields.

This reference covers symbology selection, payload encoding with delimiters, serial-port configuration on AutomationDirect PLCs (Productivity 1000/2000/3000/5000, Do-more DM1/DM2, BRX BX-DM, Click C0/C2), and the string instructions used to extract fields. Three parsing strategies are demonstrated: ASCII delimiter separation, fixed-width field slots, and identifier-prefixed (tagged) records.

Prerequisites

  • AutomationDirect Productivity Series or Do-more PLC with a serial port or Ethernet scanner module
  • Barcode/QR scanner supporting the ASCII full-range command set (most modern 1D/2D imagers)
  • Productivity Suite v4.x or Do-more Designer v2.x programming environment
  • Knowledge of the scanner's serial protocol (default 9600-8-N-1 with CR/LF terminator unless reconfigured)
  • Reference to the ANSI/ISO ASCII table (ISO/IEC 646) for non-printable delimiters such as GS (0x1D) and RS (0x1E)

Selecting the Symbology

Encode length dictates the symbology. The table below maps payload size to recommended symbol.

Symbology Standard Max Alphanumeric Capacity Best Use Case
Code 128 ISO/IEC 15417 48 (uncompressed ASCII subset) Short multi-field labels, GS1-128
Code 39 ISO/IEC 16388 43 Legacy part tags, alphanumeric only
Data Matrix ISO/IEC 16022 2,335 ASCII Direct part marking, small labels
QR Code ISO/IEC 18004 4,296 ASCII (Version 40-L) Panel HMI, engineering documents

For two to five fields under ~30 characters total, Code 128 with GS1 Application Identifiers is standard. For more fields or longer records, switch to Data Matrix or QR.

Encoding Multiple Data Fields

Three reliable encoding schemes are field-proven for PLC consumption. The chosen delimiter MUST NOT appear in the source data values, and the scanner must be configured to transmit non-printable delimiters verbatim (do not enable "Convert GS to "} in the scanner setup menu).

Strategy 1: ASCII Delimiter Separation

Concatenate fields with a reserved single-byte separator. Recommended delimiters from the ISO 15417 GS1 specification:

Symbol Hex Decimal Description
GS 1D 29 Group Separator - field separator
RS 1E 30 Record Separator - record terminator
FS 1C 28 File Separator - payload boundary
CR 0D 13 Carriage Return - line end (often appended)
LF 0A 10 Line Feed - line end (often appended)

Example payload (GS delimited, CR/LF terminated):

STEEL<GS>PN-12345-A<GS>2025-11-14<GS>250<CR><LF>

Strategy 2: Fixed-Width Slots

Each field occupies a pre-defined number of bytes. Avoid if any field has variable length (e.g., serial numbers). Pad short values with a known character (typically space 0x20 or zero 0x30).

STEEL      PN-12345-A  2025-11-14250
^^^^^^^^10^^^^^^^^^^^15^^^^^^^^10^^^3

Strategy 3: Identifier-Prefixed (GS1 AI)

Prepend each field with a numeric Application Identifier per the GS1 General Specifications. The PLC parser walks the string, reads the AI, then extracts the defined-length data.

AI Meaning Format Example
10 Batch/Lot an..20 (10)LOT-9876
11 Production Date (YYMMDD) n6 (11)251114
17 Expiration Date (YYMMDD) n6 (17)271114
21 Serial Number an..20 (21)SN-00041
30 Count n..8 (30)250
241 Customer Part Number an..30 (241)PN-12345-A

For unprefixed in-house tags, define a custom mapping table inside the PLC's data block.

PLC String Buffer Configuration

Define a receive buffer sized to the worst-case payload plus terminators. Reserve 256 bytes for 2D codes and 64 bytes for Code 128 to handle scan bursts without overrun.

PLC Family Receive Instruction Buffer Type Notes
Productivity 1000 RX (Receive) STRING Serial port module P1-04S or P1-08S
Productivity 2000/3000/5000 RX / EIP Scanner STRING Built-in RS-232/485 ports or P3-08S
Do-more DM1/DM2 STREAMIN / RX STRING DM1P/R and DM2 series
BRX BX-DM RX / STREAMIN STRING BX-P-SER serial option modules
Click C0/C2 RX STRING RS-232/485 port, 50-char limit per RX

Enable end-of-message terminator detection on the receive instruction (CR, LF, or GS+CR/LF). Without a terminator the instruction will hold the data until timeout.

Step-by-Step Parsing with Productivity Suite

  1. Configure the scanner: Set the interface to ASCII command mode. Disable prefix/suffix added by the scanner except for the required terminator (CR+LF). Enable the symbology you need. Document the default baud (typically 9600), data bits (8), parity (None), stop bits (1).
  2. Wire the serial port: Connect scanner TX to PLC RX (pin 2 to pin 2 on DB9, crossed for null modem). Reference the Productivity 1000 serial module installation guide for the wiring diagram and shield grounding practice.
  3. Configure the RX instruction: In Productivity Suite, drop an RX instruction onto a rung tied to the serial port tag. Set:
    • RXLength = 256 (maximum)
    • Terminator = 13 (CR), enable LF detection separately if needed
    • String = destination STRING tag (e.g., ScanBuffer[256])
  4. Initialize parsing on first scan: Use the FIND instruction to locate the first GS (decimal 29) within the buffer. The substring left of the GS is field 1 (Material Type).
  5. Extract field 2: Use MID to copy from the character after the first GS to the character before the next GS. The result is Part Number.
  6. Extract field 3: Repeat using the second FIND result minus the prior offset to extract the Date.
  7. Extract field 4: Final field ends at the terminator; use LEFT with length = terminator position - field 3 end.

Example structured text fragment for the field extraction loop:

// Find first GS (decimal 29) delimiter
Pos1 = FIND(ScanBuffer, CHR(29), 1)
MaterialType = MID(ScanBuffer, 1, Pos1 - 1)

// Find second GS
Pos2 = FIND(ScanBuffer, CHR(29), Pos1 + 1)
PartNumber = MID(ScanBuffer, Pos1 + 1, Pos2 - Pos1 - 1)

// Find CR terminator (decimal 13)
Pos3 = FIND(ScanBuffer, CHR(13), Pos2 + 1)
ProdDate = MID(ScanBuffer, Pos2 + 1, Pos3 - Pos2 - 1)

// Optional 4th field (quantity) before terminator
Qty = TRIM(MID(ScanBuffer, Pos3 - 3, 3))

Do-more / BRX Reference Implementation

Do-more Designer exposes STREAMIN which handles arbitrary byte streams with built-in terminator handling, then string instructions STRCMP, STRFIND, STRMID, STRLEFT, STRRIGHT, and STRTRIM perform the parse. BRX (BX-DM) uses the same instruction set.

// Rung 1: receive into VB1000..VB1255
STREAMIN D/VB1000, .SCAN_LEN, 0, 13, 100, &VB0

// Rung 2: locate first GS
$V101 = STRFIND(VB1000, 29, 1) // 0-based offset returned

// Rung 3: parse material type
VB2000 = STRLEFT(VB1000, $V101)

// Rung 4: parse part number
VB2100 = STRMID(VB1000, $V101 + 1, $V102 - $V101 - 1)

Refer to the Do-more Designer Help file index for STREAMIN parameters and the BRX MPU user manual for option-module port assignments.

Verifying the Parse

  1. Create a 4-quadrant HMI tag page in Productivity View or C-more that displays each parsed field independently with the source string for visual comparison.
  2. Scan a known test label five times. Confirm each field value matches the expected text byte-for-byte, including leading/trailing characters.
  3. Force the receive buffer to a length-zero state and scan again to verify re-initialization; confirm no leftover data from the prior scan contaminates field 1.
  4. Test edge cases: missing trailing field (label truncated), embedded delimiter in a value (must be escaped at print time or use a different strategy), and double scans back-to-back within the receive timeout.
  5. Use the PLC's task monitor (Productivity Suite Task Manager or Do-more Data View) to inspect the STRING tag contents in real time.

Troubleshooting Matrix

Symptom Likely Cause Diagnostic Corrective Action
Buffer empty after scan Wrong baud or wrong port Loopback test (TX→RX jumper) send known string Match scanner settings to RX instruction; verify port tag
Buffer contains garbage Parity/data-bit mismatch Read first 4 bytes as hex; look for FF FA pattern Set both sides to 8-N-1; disable hardware flow control unless wired
Delimiter not found Scanner strips non-printable Hex-dump buffer from laptop tap Disable "ASCII control char filter" in scanner; enable GS/RS passthrough
Field offset drift after each scan Buffer not reset Inspect RXLength return value Clear STRING on first CR; use a copy-to-buffer-then-clear pattern
RX never completes No terminator transmitted Terminator log in scanner Add CR+LF suffix; configure RX to use 0x0A as alternate terminator
Only first field correct, rest shifted FIXED-WIDTH mismatch Compare actual byte positions to layout Re-measure fields with hex monitor; document lengths in HMI help
Click PLC truncates at 50 chars RX buffer size limit Reference manual Use BRX or Productivity series for 2D codes > 50 chars

Field-Engineering Notes

  • Print the same delimiter scheme on EVERY label template; mismatched delimiters between line A and line B are the single most common cause of data-corruption calls.
  • Always terminate the scanner's transmitted string with CR or CR+LF; without it, the RX instruction waits the full timeout (typically 100 ms-1 s depending on configuration) before exposing data to the parser.
  • Reserve the FS (0x1C) character as a payload boundary marker if you ever multiplex two barcode records into one scan event. PLCs cannot de-multiplex without an explicit record separator.
  • For GS1-128 with AI parsing, store the AI length table (fixed vs variable) in a lookup block at startup; this avoids hard-coding lengths inside the parse rung and keeps the logic reusable.
  • Do not perform ASCII string manipulation in the same scan that triggers a high-speed motion axis. Move the parsing to a separate low-priority task or interrupt to avoid scan jitter.

What is the simplest delimiter to use between fields when designing an in-house barcode label?

Use ASCII GS (0x1D, decimal 29). It is reserved for field separation in the GS1 specification, never appears in typical alphanumeric part data, and is supported as a passthrough character by virtually every modern 1D/2D imager. Configure the scanner to transmit GS unfiltered.

Can a Click series PLC handle QR codes with 100+ characters?

No. The Click C0 and C2 RX instruction accepts at most 50 characters per receive. Use the Productivity 1000/2000/3000/5000 or BRX BX-DM series with a 256-byte STRING buffer for QR or Data Matrix codes that exceed 50 bytes.

How do I parse GS1 Application Identifiers like (10)LOT9876 in a Productivity Suite project?

Read the two-digit AI after each opening parenthesis, look up its fixed length in a data block (e.g., AI 10 = variable up to 20 alphanumeric), then use MID to extract the exact byte range. The FNC1 separator (0x1D, GS) must be enabled as a passthrough on the scanner or variable-length AIs cannot be terminated.

What scanner settings cause the PLC to see only the first field after a delimiter?

The scanner is filtering ASCII control characters below 0x20. In most 2D imagers this setting is labeled "Send Control Characters," "GS Substitution," or "Enable ASCII Extended." Disable it so GS, RS, and CR pass through unmodified.

How should I handle a delimiter character that appears inside a part number?

Either (a) escape it at label print time by prefixing with a backslash and writing an unescape routine, (b) switch to a different delimiter that cannot legally appear in the data, or (c) move to fixed-width slots so the parser does not search for delimiters. Option (b) is the most common fix in practice.

Back to blog