Code readingTroubleshooting

ASCII barcode data framing in the PLC receive buffer: nulls and races

Why barcode strings reach the PLC with leading nulls or half a frame, the baud-rate arithmetic behind the race, and the framing and buffer rules that fix it.

LumaSpec Vision10 min read Share on LinkedIn

On this page 9 sections
  1. 01Why does my PLC receive barcode data with null characters before the code?
  2. 02What goes wrong when an ASCII scanner sends data with no handshake?
  3. 03How fast does the scanner fill the PLC receive buffer?
  4. 04How do you frame the data so a partial string never reaches your program?
  5. 05How do you strip nulls and validate the string before you store it?
  6. 06How do you stop a program switch from losing half a frame?
  7. 07How do you prove the fix before the line runs?
  8. 08When is the scanner or the label at fault instead of the program?
  9. 09Questions

A barcode that reads perfectly on a PC arrives in the PLC with null bytes in front of it, chopped in half, or glued to the previous scan. The scanner is usually innocent. ASCII output is an unsolicited one-way stream with no acknowledgement, and the PLC receive buffer holds whatever the wire has delivered by the time your logic looks. This guide gives you the arithmetic that sizes the race — a 15-byte frame occupies a 9,600 baud link for 15.6 ms, longer than a typical 10 ms PLC scan cycle — then the framing, null-trimming and buffer-ownership rules that keep a bad string from ever being stored, and the bench test that proves the fix.

Why does my PLC receive barcode data with null characters before the code?

The nulls are bytes already sitting in the PLC receive buffer before the code arrived — line-settling NUL padding from the link or the unconsumed tail of the previous frame — and your logic stored the buffer contents as the code.

The byte value is 0x00, and it is data to your program until you refuse it. A UART that sees its input held low — a break condition while a converter or radio link settles — reads 0x00, and some converters pad the start of a transmission the same way to stabilise the line. A receive routine that reads whatever is present stores those bytes with the code. The second source is residue: the previous frame's terminator was never found, the buffer was never cleared, and the new read starts with stale bytes from the last scan.

Log the raw bytes in hex for one shift before you change any logic. Leading 0x00 bytes point at link padding. Readable text ahead of the code points at residue. Gibberish in random positions points at the link settings, not the framing.

What goes wrong when an ASCII scanner sends data with no handshake?

With no acknowledgement in the protocol, the scanner transmits the frame once and forgets it, so nothing tells your program the message is complete: whatever sits in the receive buffer at the instant your logic reads becomes the code.

The scanner fires on its trigger, puts the bytes on the wire, and from that moment the frame exists only in your buffer. Three failure shapes follow. A read that lands mid-transmission stores a partial frame. Two triggers close together — 20 ms apart on a fast line — stack both frames inside one read window. Padding bytes ride in front of the first real character.

The fourth pattern comes from the PLC side and hides longest: a communication interrupt that switches into another program while a frame is still open, so the bytes are consumed by logic that never expected them. Codes then come out wrong at random intervals, and the scanner gets blamed. Decide it once: the receive path is event-framed, never a scheduled read of whatever happens to be present. If the link is still on the drawing board, the communication plan for a barcode reader on a PLC settles interface and framing choices before the first byte moves.

How fast does the scanner fill the PLC receive buffer?

At 9,600 baud with 8N1 framing the link moves 960 characters per second, so a 15-byte scan frame occupies the wire for 15.6 ms — longer than a typical 10 ms PLC scan cycle, which is why an unframed read samples mid-frame.

t_char = 10 bits ÷ baud rate t_frame = frame bytes × t_char t_timeout ≈ 3 × t_frame

Worked example: take a 12-character part code wrapped in STX, CR and LF — 15 bytes on the wire; substitute your own code length and the same sums apply. At 9,600 baud 8N1 one character costs 10 ÷ 9,600 = 1.04 ms, so the frame takes 15 × 1.04 = 15.6 ms. A PLC scanning every 10 ms has 15.6 ÷ 10 ≈ 1.6 scan windows inside one frame, so a read-whatever-is-there routine catches a partial string on most scans during a read. Set the frame timeout near three wire times: 3 × 15.6 = 47 ms, rounded to 50 ms. The same 15 bytes at 57,600 baud cost 15 × 0.174 = 2.6 ms — the race window shrinks sixfold, and nothing else about the problem moves.

How do you frame the data so a partial string never reaches your program?

Give every frame a start character and a terminator — STX (0x02) before the code and CR (0x0D) after it is the common pair — and let the PLC read from the start byte to the terminator and not one byte further.

Set the prefix and suffix in the reader's configuration, then mirror them exactly in the PLC program: wait for STX, accumulate bytes until CR, close the frame. Two guards wrap around that loop. The length window rejects any payload below your shortest real code or above your longest — with a 12-character code, limits of 4 and 16 catch both a truncated string and two codes glued together. The timeout discards anything that never terminates, then the buffer is cleared and a counter incremented. When the two ends disagree, the symptom is a frame that never closes at all; why barcode reads require matching ASCII framing walks through that failure. The prefix and suffix settings themselves deserve a check before you touch any PLC logic.

Set the prefix and suffix in the reader's own configuration once, and every host downstream receives the same delimited string.

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
Shutter
Global
Lens mount
M12
$1,979.00View part

How do you strip nulls and validate the string before you store it?

Skip every 0x00 byte from the front of the buffer, then require the first real byte to be your start character and the payload length to fall inside your known window; only a frame that passes all three checks gets copied to the holding tag.

Run the validation in this order, so a bad frame costs the least work:

  1. Locate the terminator by scanning forward from the start character; the frame is everything between them.
  2. Strip leading 0x00 bytes — they are padding, not data.
  3. Reject the frame if the first real byte is not the start character.
  4. Reject the frame if the payload length falls outside the window.
  5. Copy the payload to the holding tag and set the frame-valid flag with a timestamp; on any rejection, clear the buffer and increment that failure's counter.

In production, reject rather than repair. NUL stripping is legitimate when your converter emits padding by design; the length and start-byte checks catch everything else, including stale tails. Storage then behaves: the validated string goes into holding registers with an explicit length, which is exactly what the bytes, words and clears of PLC string storage are for. For a worked receive that lifts the code and its read position straight out of the buffer, this ASCII receive example with barcode position lookup follows the same validate-then-store order.

How do you stop a program switch from losing half a frame?

Give the receive buffer a single owner: one routine reads the complete frame — start byte to terminator — before any program or subroutine switch, and every other part of the logic consumes only the frame-valid flag and its timestamped copy.

The rules that make the ownership real:

  • The interrupt handler latches the byte-received event with a timestamp, or reads to the terminator itself; it never hands a half-open buffer to another program.
  • A program or subroutine switch waits until the frame closes or the timeout fires.
  • The buffer is cleared once, at the top of each receive cycle, before the receive is enabled.
  • Consumers read the copied string through the flag, never the raw buffer.

The clear itself has to be the proper reset for your serial hardware; how to clear an ASCII receive buffer between frames shows an order that leaves no residue behind.

How do you prove the fix before the line runs?

Scan the problem label into a PC first, with the port settings matched: a clean read there clears the scanner, the cable and the label, which leaves the PLC receive logic as the only suspect left standing.

Then bench the change in this order:

  1. Baseline: log raw bytes for 100 triggered scans before the change, and count how many hold leading 0x00 bytes, how many lack a terminator, how many hold two codes.
  2. Apply framing, validation and the single-owner rule.
  3. Run 100 more scans at line rate — a part every 500 ms if that is your takt, not one scan per button press.
  4. Require the bad-frame counter to hold at zero for the whole run; any other reading means a guard caught something real.
  5. Finish with two triggers at the minimum line interval to prove concatenation is handled.

Framing adds microseconds next to the serial link itself, so once a read decodes cleanly, the read-confidence checks tell you whether a decode is worth trusting before the string moves downstream.

When is the scanner or the label at fault instead of the program?

Garbage characters on the PC and the PLC alike point to a baud or parity mismatch; one physical label that fails everywhere, PC included, is a print problem and gets reprinted; clean PC reads with dirty PLC reads stay a framing or buffer problem.

Split the blames like this. Gibberish on both hosts is the link settings, and the garbage-character diagnosis covers that path. One label that fails over and over, even on the PC, is print quality, and the fastest fix is a reprint — the reader is telling the truth about a bad code. Reads that survive one at a time but fail at line speed point back at the read schedule, not the reader.

Pick an output you can frame. A USB keyboard wedge delivers unframed keystrokes — convenient at a manual station, wrong for PLC logic that branches on the string. Serial and Ethernet ASCII carry bytes you can frame and validate, which is what the input-method comparison for scanners into PLCs sorts out. Handheld code readers cover spot checks and material handling; the line wants fixed code readers configured once.

A fixed reader at the line gives you both framing controls in its own configuration — set the prefix and suffix once, and every host downstream receives the same delimited string over an Ethernet link.

Fixed code readersDual aviation plug fixed industrial barcode reader, 1.2 MP, focal length 12 mm (LS-CRD-0052)LS-CRD-0052
Resolution
Up to 3 MP
Shutter
Global
$559.00View part
Fixed code readers2560 x 2048 fixed code reader, 30 fps, 60 codes/s, 8 mm lens (LS-CRD-0028)LS-CRD-0028
Interface
Fast Ethernet
Resolution
5 MP
$920.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

The camera and reader finder filters by interface, so serial, Fast Ethernet and GigE outputs get chosen deliberately. Wire the trigger and output side in the system configurator. If a counter will not sit at zero after the bench run, send us the hex log through the contact page. The code-reading topic page collects the rest of the receive-logic fixes.

Questions

What ASCII bytes are CR, LF, STX and NUL?

CR is 0x0D (decimal 13), LF is 0x0A (10), STX is 0x02 (2) and NUL is 0x00 (0). Most fixed and handheld readers let you pick a suffix from CR, CR plus LF or none, and an optional prefix such as STX. Choose one pair, write it into the commissioning sheet, and match it byte for byte in the PLC logic; a mismatched terminator is the most common reason a frame never closes.

Does a faster baud rate remove the nulls and partial frames?

No. At 57,600 baud 8N1 the same 15-byte frame takes 2.6 ms instead of 15.6 ms, so the race window shrinks sixfold, but an unframed read still stores partial data and NUL padding still arrives. Speed is a tuning knob; framing and buffer ownership are the fix. A true baud or parity mismatch shows up as gibberish characters, not as clean leading nulls.

Can I plug a USB handheld scanner into the PLC HMI instead?

You can, if the HMI has a USB host port and accepts the scanner as an HID keyboard, but the wedge types keystrokes with no framing, so a slow screen can take half a code. For PLC logic that branches on the string, serial or Ethernet ASCII with a start character and terminator stays the deterministic route; keep the USB wedge for manual stations.

Does the same framing problem exist over Ethernet?

Yes, and it hides better. TCP is a byte stream with no message boundaries: two scans close together can arrive in one read, and one scan can arrive as two reads. Apply the identical rules on the socket — start character, terminator, length window and a timeout near three times the frame's wire time — and count rejected frames exactly as on the serial port.

Where should the frame timeout start on a faster link?

Scale it with the wire time. The 15-byte frame from the worked example costs 15 × 0.174 = 2.6 ms at 57,600 baud, so start at three times that — about 8 ms, rounded to 10 ms — but never below twice your PLC scan cycle, or every slow scan throws a good frame away. On timeout: clear the buffer and increment the counter.