Scanning Multiple Barcodes from One Wrist Camera Pose

David Krause8 min read
Other ManufacturerRoboticsTroubleshooting
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

The term snapshot position here means the taught robot pose from which the camera fires a capture; every decode below happens either at that pose or at a rigid offset derived from it. The on-board reader in a wrist camera is a single-symbol decoder. It searches the frame for one finder signature — the start/stop guard bars of a 1D symbology, the solid L and clock track of a Data Matrix — decodes it, and writes one string into a program variable. Two valid symbols in the same frame present an ambiguity the pipeline has no arbitration rule for, so the outcome is a no-read or an arbitrary pick, never two results. That behaviour is structural, not a setting you can switch off.

With eight parts on a fixture there are exactly two viable paths: isolate one symbol per frame optically by moving the camera closer to each code, or stop asking the robot to decode at all — capture one image that contains all eight symbols with the image save node and decode them off the robot. The checks below decide which path the geometry allows.

Check 1: Field of View Against Barcode Pitch

Take two measurements on the loaded fixture: the worst-case centre-to-centre pitch p between adjacent symbols, and the printed symbol width w including its quiet zone QZ. Then compute the horizontal field of view at the working distance WD you intend to shoot from.

FOV_w(WD) = 2 * WD * tan(HFOV / 2)

Isolation:  FOV_w < 2*p - w     # nearest neighbour falls fully outside the frame
Framing:    FOV_w > w + 2*QZ    # target symbol plus quiet zones stay inside

If the camera datasheet gives a field of view at one stated distance instead of an angle, scale it linearly: FOV2 = FOV1 * WD2 / WD1. A neighbour that is only partially in frame still trips the symbol locator, so leave margin on the isolation inequality rather than sizing to the limit.

Two floors bound how close you may go. The first is the camera's minimum focus distance — read it from the datasheet; below it, contrast collapses and the decode fails for reasons that look like a lighting problem. The second is resolution: save a frame with the image save node, open it in any pixel-accurate viewer, and measure the narrowest bar. Expect at least 2–3 pixels across a narrow element for 1D symbologies and 3–5 pixels per module for Data Matrix. Below that, no working distance rescues the read and the correct fix is a larger label or a coarser symbology.

Outcome: if a working distance exists that satisfies both inequalities and clears the focus minimum, single-code isolation is achievable — go to Check 2, Branch A. If the codes are packed tighter than the camera can resolve them apart, Branch A is closed and the answer is Branch B.

Check 2: Index the Pose or Capture Once

Both branches start from a single taught reference. The distinction is where the decode runs.

Criterion Branch A — eight sub-poses, on-robot decode Branch B — one capture, offboard decode
Robot motion per fixture 8 moves, 8 settles, 8 triggers 1 move, 1 settle, 1 trigger
Cycle time driver Move + settle time, multiplied by eight Image write and transfer time
Program structure One taught reference pose; the other seven derived as fixed offsets so a re-teach moves all eight Single pose, single image save node
PC-side work None; strings arrive as program variables Multi-code decode library, slot mapping, CSV writer
Slot association Implicit — the pose identifies the slot Explicit — derived from symbol position in the image
Dominant failure mode Motion blur from triggering before the arm settles; a neighbour clipping into frame Glare or blur on one label loses one of eight codes silently

Branch A satisfies the "all from the same taught position" requirement in the sense that matters on the shop floor: one point to teach and maintain, seven rigid offsets from it. Trigger only when the arm is stationary — a capture taken during deceleration smears the narrow bars and produces intermittent no-reads that get misdiagnosed as lighting.

Check 3: Where the Image Goes

The image save node accepts a network path as well as a local directory, but writing across the network puts the cycle time at the mercy of the link. Save locally on the controller and pull the files from the PC over FTP. That keeps the write fast and deterministic, and a network stall backs up in the file system instead of stalling the program.

Three details make the transfer usable rather than merely functional:

  • Filename discipline. Encode fixture or batch ID plus a sequence number or timestamp in the filename. The PC needs no side channel to know what it is looking at.
  • Write/read race. A poller that grabs a file mid-write decodes garbage. Either wait for the file size to stay constant across two polls, or have the robot write to a temporary name and rename on completion — rename is atomic within a directory.
  • Retention. Controller storage is finite. Cap the local directory and let the PC delete after a confirmed pull, or purge on age.

If the PC must react within the cycle rather than poll, signal it from the program over a socket after the save node completes, sending the filename as the payload.

Procedure: One Snapshot, Eight Decodes

  1. Constrain the fixture so label position repeats. Any slop in part seating turns into slot-mapping errors later.
  2. Teach the snapshot pose so all eight symbols sit inside the frame with visible margin on the outer two. Save one frame and measure narrow-bar width in pixels; if it is under the resolution floor from Check 1, raise the label size or lower the camera before continuing.
  3. Set the lighting off-axis and diffuse. Specular reflection from the wrist illuminator on a glossy label saturates the quiet zone and kills that one code while the other seven read fine.
  4. In the program: move to the snapshot pose, dwell until the arm is stationary, call the image save node with a unique filename, then continue the pick sequence. Tune the dwell down from a conservative value using the blur test in Check 2 of verification.
  5. Transfer the file — local save, FTP pull from the PC.
  6. Decode on the PC with a library that returns all symbols in the frame together with each symbol's bounding box or centroid.
  7. Map centroids to slots. Define eight rectangular regions of interest on a golden image of a fully loaded fixture; assign each decoded string to the slot whose region contains its centroid. This is the step that replaces the pose-per-slot association you gave up in Branch B.
  8. Write the CSV row: slot number, decoded string, timestamp, source image filename. Keeping the filename makes every disputed record auditable against the pixels it came from.
  9. Handle the short read. Fewer than eight decodes, or two centroids in one region, must raise an exception — retain the image, flag the fixture, and route the missing slot either to a close-range single-code re-scan or to manual entry. A silent seven-of-eight is the failure that reaches the customer.

Verification Checks and Recurring Failure Modes

Symptom Mechanism Correction
No-read with two codes visible Single-symbol decoder cannot arbitrate Reduce field of view per Check 1, or move the decode offboard
Intermittent no-read at one slot only Specular glare on that label's angle Change illumination angle or tilt the snapshot pose a few degrees
Reads degrade after a program edit Snapshot pose re-taught, offsets not updated Derive the seven sub-poses from the reference pose, never teach them independently
Blurred bars, sharp background Trigger fired during deceleration Extend the dwell before the save node
PC decodes an empty or truncated file Poller read the file mid-write Write-then-rename, or require stable file size across two polls

Run these before releasing the station to production:

  1. Isolation check. Trigger a decode at each of the eight sub-poses (Branch A) with a fully loaded fixture. Expect a non-empty string on 10 of 10 triggers per slot; any no-read means a neighbour is clipping into frame.
  2. Blur check. Capture at the production dwell and at double the dwell, then compare narrow-bar edge sharpness in both images. Expect no visible difference; if the longer dwell is sharper, the arm was still moving.
  3. Resolution check. Measure the narrowest bar of the worst-placed symbol in the saved image. Expect ≥2–3 px for 1D, ≥3–5 px per module for Data Matrix.
  4. Transport check. Time the interval from image save to a complete, decodable file on the PC across 20 consecutive cycles. Expect every file to arrive inside the cycle time, with zero truncated reads.
  5. Correlation check. Run 20 fixtures through the automated path while the operator also records the codes by hand. Expect a 20 × 8 exact match on both the string and the slot number; any slot swap points at the region-of-interest grid, not at the decoder.

FAQ

How do I read eight barcodes from one robot pose?

Not with the on-board decoder — it returns one symbol per frame and no-reads when two are visible. Use the image save node to capture a single frame containing all eight codes, transfer it to a PC, and decode with a multi-code library that returns each symbol's string and centroid.

How do I get saved images off the robot controller to a PC?

Write to a local directory on the controller and pull the files with FTP from the PC; that keeps the write fast and stops a network stall from affecting the program. A network path can be set directly in the save node, but it couples cycle time to the link.

How do I know which fixture slot each decoded barcode came from?

Define eight rectangular regions of interest on a golden image of a loaded fixture and assign each decoded string to the region containing its centroid. Verify the mapping against 20 hand-recorded fixtures and treat any slot swap as a region-of-interest calibration error.

Back to blog