System designHow-to

Parse tab-delimited results from a smart camera into pass or fail

How to parse smart camera results into pass/fail booleans: split the TCP line on tab 0x09, strip CR/LF, compare field text exactly, and hand bits to a PLC.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01What does the camera actually send down the TCP connection?
  2. 02How do I split the line into fields?
  3. 03How do I turn a field into a pass/fail boolean?
    1. The worked example
  4. 04How do I parse it in a LabVIEW host?
  5. 05How do I write the booleans to a PLC?
  6. 06Why does every compare fail on a fresh set-up?
  7. 07Which camera and host should run this?
  8. 08What should I check before the first production shift?
  9. 09Questions

A smart camera that inspects on its own processor still has to tell the line what it saw, and the most dependable way is a line of plain text: fields separated by tab characters, a verdict spelled out in ASCII, sent down the TCP connection you already use to trigger it. Opening that socket is its own task, covered in triggering a smart camera over TCP with ASCII commands; this guide starts when the first string arrives. You will fix a field layout, split the line on the tab, compare one field exactly, and hand a pass bit, a fail bit and a valid strobe to the PLC.

What does the camera actually send down the TCP connection?

One line of printable ASCII per inspection: the fields you configured, left to right, separated by a single tab (ASCII 0x09, decimal 9) and terminated with CR LF (0x0D 0x0A), which is why the parser must strip two bytes before comparing anything. You choose the contents and the order on the sensor's export page; on sensors that follow the common layout that is the Data Export tab under System Settings > Communications, and every result you tick there becomes one field, left to right, in the order shown.

Fix the layout before writing any parser code. The one parsed end to end here:

  • field 0 — part ID, free text, unique per part
  • field 1 — overall verdict, the token PASS or FAIL
  • field 2 — the tightest measurement
  • field 3 — inspection time, milliseconds

Verdict second is deliberate: field 0 carries a unique ID for the stale-data check later, and the verdict stays clear of the terminator bytes that ride on the last field. One inspection arrives as:

LOT-4471<TAB>PASS<TAB>0.84<TAB>23.7<CR><LF>

Count the bytes: 8 for the lot number, 4 for the verdict, 4 for the measurement, 4 for the time, 3 separators, 2 terminator bytes — 8 + 4 + 4 + 4 + 3 + 2 = 25 bytes:

4C 4F 54 2D 34 34 37 31 09 50 41 53 53 09 30 2E 38 34 09 32 33 2E 37 0D 0A
 L  O  T  -  4  4  7  1 TAB  P  A  S  S TAB  0  .  8  4 TAB  2  3  .  7 CR LF

When the payload is read text rather than a verdict, the sensor side is the same page; smart camera OCR string output over TCP walks that configuration.

How do I split the line into fields?

Split the stripped line on the single byte 0x09 and index left to right from zero: the example line yields four fields, and the verdict lives in field 1 no matter what the other fields contain. Split on that one byte, never on "any whitespace": a part ID containing a space shifts every later index by one, and the parser then reads the measurement as the verdict. Strip before splitting — one trailing 0x0D, one 0x0A, then any trailing spaces the export adds.

Then count. Three separators mean four fields, and the count is a structural check: a line with the wrong count is a communication fault with its own alarm, never a judgement about the part.

Buffer discipline matters more than the split itself. If the host reads late, one read can hold two lines; split the receive buffer on 0x0A first and keep the last complete line. The framing traps are the same in ladder logic — nulls, partial frames, races — and ASCII data framing in the PLC receive buffer works through them. A robot host receiving several results in one socket string runs this split twice, lines then tabs, exactly as parsing four vision results from one socket string on a UR10e shows.

How do I turn a field into a pass/fail boolean?

Compare field 1 as text to the exact token PASS: equal means pass, and everything else — empty, short, misspelt or a line that never arrived — means fail, with a communication alarm attached. The whole decision in one place:

pass = (field_count == 4) AND (field[1] == "PASS") fail = NOT pass comm_fault = (field_count != 4) OR timeout

The procedure, once per trigger:

  1. Read the socket until 0x0A arrives, with a 500 ms timeout. A small inspection answers trigger-to-string in roughly 10-50 ms, so 500 ms is ten times the worst case; a timeout fails the part with a comm alarm.
  2. Strip one trailing 0x0D and 0x0A, then trailing spaces.
  3. Split on 0x09 into fields indexed from 0.
  4. Require exactly four fields; anything else raises the comm fault and stops the parse.
  5. Set pass on the case-sensitive compare of field 1 against the token PASS.
  6. Optional plausibility gate: parse field 2 as a decimal and compare numerically — 0.84 mm against a 0.90 mm limit passes with 0.06 mm of margin. Parse first: as text, "9" would sort above "10".
  7. Combine: final = pass AND gate. Fail is NOT final, written as its own signal.
  8. Write pass, fail and the valid strobe to the controller in one update.

The worked example

Index Raw field Rule applied Output
0 LOT-4471 log with the result —
1 PASS equal to "PASS"? true
2 0.84 0.84 mm ≤ 0.90 mm true
3 23.7 log only —

final = true AND true, so the pass bit sets, the fail bit clears and the strobe fires.

Gate on the camera's verdict, not on a host-side re-decision from the numbers. The camera owns the tolerances; a host that re-decides duplicates them, and two copies drift apart within a season.

How do I parse it in a LabVIEW host?

With two string operations and one comparison: split into an array on the tab, take index 1, and the output of the string-equality comparison is already the boolean — no separate conversion step exists or is needed. Concretely: the comparison output wires straight to the pass indicator and to the case structure that writes the controller bits. When the export sends the words True and False instead of tokens, compare against the constant True — the equality comparison is the string-to-boolean conversion.

Pace re-reads with a small wait carried on the error chain rather than a sequence structure, so the timing lives in one wire and the diagram stays flat. The wider pattern — connect, trigger, read, use results as data — is laid out in smart camera LabVIEW integration: use inspection results as data; the same parse in a text language appears in reading smart camera data from a VB.NET TCP client safely.

How do I write the booleans to a PLC?

Write three signals, never one: a pass bit, a fail bit and a valid strobe of about 100 ms, because a PLC that scans every 1-10 ms needs the result held for at least ten scans to catch it reliably. Three signals, one update:

  • PASS — true only for the part the strobe marks.
  • FAIL — its own bit, true for a rejected part or a comm fault.
  • VALID — a 100 ms strobe; the PLC latches on its rising edge.

Give the comm fault a separate bit as well, so the line can tell a rejected part from a deaf camera.

The socket exchange end to end is in smart camera to PLC over TCP: trigger and pass/fail, and vision system to PLC: send pass-fail results, not images explains why the images stay on the camera. A result line that lives for one scan vanishes before the logic sees it — the barcode string that disappears after one PLC scan is that failure, latched on the pulse. Counters built from these bits should reset with the batch, as resetting pass/fail counters per batch in a vision inspection script shows.

Why does every compare fail on a fresh set-up?

Almost always it is the carriage return: CR LF termination leaves the last field carrying an invisible 0x0D, and any text compare against a clean token fails on every single part until you strip it. The causes, in the order you meet them:

  • Invisible CR on the last field. Print the line in hex and look for 0D before the 0A; the fix is step 2 of the procedure.
  • Whitespace split. Send a part ID containing a space; if the verdict index moves, the split is wrong. Split on byte 0x09 only.
  • Re-configured export. Someone ticked one more result on the export page. The field-count check catches it; put a layout version in field 3 so the host can name the change.
  • Two lines, one read. Trigger twice without reading in between. Split on 0x0A and keep the last complete line.
  • Case drift. The export sends Pass while the host compares PASS. Fix it on the sensor page — token uppercase — not with a case-insensitive compare, which hides the drift.
  • Stale result. The host parsed the previous part's line. Make field 0 a unique part ID and check what came back against what was sent.

Which camera and host should run this?

Any smart camera whose export page lets you order the fields and spell the verdict token will do; choose the sensor for the inspection, then confirm the host has a LAN port for the camera and one for the PLC. The link speed is irrelevant — a line on this layout is 25 bytes, so even a busy part rate leaves the network idle. Filter the smart cameras range on sensor format, resolution and mount in the camera finder.

Two examples from the shelf:

Smart cameras & vision sensorsHikrobot MV-SC5060XM-08M-WBN SC5000X series Smart Camera, 6 MP, Mono, 8 mm focal length, M12-mountMV-SC5060XM-08M-WBN
Interface
GigE
Resolution
6-10 MP
$1,629.00View part
Smart cameras & vision sensorsHikrobot HK-TD032-12-WBN 1.6 MP mono vision sensorHK-TD032-12-WBN
Interface
Fast Ethernet
Resolution
Up to 3 MP
$1,699.00View part

Three side by side — what differs is on the sensor and the lens, not on the link:

Specification MV-SC5060XM-08M-WBN MV-SC6050C-08M-XBN HK-TD032-12-WBN
Function module Vision Master Platform (include deep learning module) Vision Master Platform (include deep learning module) –
Communication protocol TCP, UDP, Modbus, Serial Port, PROFINET, EtherNet/IP, Fins, MC, FTP, etc. TCP, UDP, MODBUS, Serial Port, PROFINET, EtherNet/IP, Fins, MC, FTP, etc. RS-232, TCP, UDP, FTP, PROFINET, Modbus, EtherNet/IP, MELSEC/SLMP, FINS, Keyence KV
Sensor type CMOS, rolling shutter CMOS, global shutter CMOS, global shutter
Pixel size 2 μm × 2 μm 3.45 μm × 3.45 μm 3.45 μm × 3.45 μm
Sensor size 1/2.4" 1/1.45" 1/2.9"
Resolution 3200 × 1920 2432 × 2048 1408 × 1024
Max. frame rate 15 fps 80 fps 60 fps
Gain 0 dB to 34 dB 0 dB to 18 dB 0 ~ 15 dB
Exposure time 72 μs to 150 ms 16 μs to 1 sec 16 μs ~ 1 sec
Pixel format Mono 8 Mono 8, RGB 8 Mono 8
Mono/color Mono Color Mono
Memory 8 GB 8 GB –
Price $1,629.00 $3,449.00 · quoted $1,699.00

All 3 share: Humidity 20% RH to 95% RH (no condensation); Certification CE, KC. Values as printed in each product's data sheet; open a part for its drawing and full specifications.

When the host is not a line PC, a vision controller runs the parse, the lighting and the PLC handshake in one box; where that work belongs is its own question, answered in smart camera results to an RT controller: how to split the work. One host built for exactly that split:

Vision controllersHikrobot MV-VC3301H-128G66 I3-8100, 8GB+128G SSD, No PoE, PCIe expansion supported, Incl. VM6200Pro licenseMV-VC3301H-128G66
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
Light outputs
4 built-in channels
Memory
8 GB
$2,419.00View partBuild a system with it

The vision controllers range carries the same job in several sizes.

What should I check before the first production shift?

Run five known parts — three good, two deliberately bad — and demand five logged lines, the booleans flipping on exactly the wrong two, and a communication alarm the moment you pull the cable mid-cycle. The full list:

  • The line ends 0x0D 0x0A, and the parser strips both before any compare.
  • Three separators give four fields; a mismatch raises the comm fault, and three consecutive comm faults stop the line.
  • The verdict token is uppercase PASS on the sensor page and in the host constant, compared case-sensitively.
  • Field 0 carries a unique part ID, and the host checks returned against sent.
  • The strobe is 100 ms and the PLC latches on its rising edge, not its level.
  • The socket timeout is 500 ms; a timeout fails the part and counts toward the stop threshold.
  • After a camera power cycle, the first parsed line is live — its part ID matches the part in front of the lens.

From here, start the system configurator at the camera step and let it carry lens, light and controller from there. More on moving results into control systems sits on the systems topic page, and for a cell bigger than one parser — several cameras, one controller — send the part list through the contact page.

Questions

How much network bandwidth do the result strings need?

Almost none. One line on this layout is 25 bytes; at 10 parts per second that is 250 bytes per second, about 2,000 bits per second, or 0.002 percent of a 100 Mbit/s link. A four-camera cell sending one line per part stays far under one percent. Bandwidth only becomes a question if images share the same link — keep image streaming on its own port.

Should the pass/fail decision live in the camera or in the host parser?

In the camera. It owns the tolerances, so it should send the verdict as a text token and let the host compare that one field. A host that re-decides from raw numbers duplicates every tolerance, and the copies drift apart. Keep the host numeric check as a plausibility gate only — catch an empty field or an impossible zero, not the decision of record.

What read timeout should the host use waiting for a result line?

500 ms. A single small inspection typically runs trigger-to-string in 10-50 ms, so 500 ms is ten times the worst case and still fails a part within one cycle on a line at a few parts per second. Treat a timeout as a fail with its own alarm, and stop the line on three consecutive timeouts instead of rejecting parts indefinitely.

Why not search the whole line for the word PASS?

Because another field can contain it. A lot number, a grade code or a free-text field holding PASS inside a longer string returns a false pass. The indexed compare plus the field-count check also catches what a substring search hides: a re-configured export layout and a truncated line. Compare one field, exactly, and the verdict and the line's shape are both proven.

The sensor sends 1 and 0 instead of PASS and FAIL — how do I parse that?

The same way, with a different token: pass = field 1 equals 1, and everything else — 0, empty or missing — fails. Do not cast the field to a number and test for non-zero: a lost line leaves an empty field that some casts turn into zero and others into an error, and the two behave differently on the night shift. One token, one text compare.