Code readingHow-to

Read barcodes on a vision controller from scratch

Read barcodes on a vision controller from zero: pixel budget, optics, trigger, ROI decode and the PLC handshake, with a worked 12 MP optics example.

LumaSpec Vision13 min read Share on LinkedIn

On this page 11 sections
  1. 01What a controller-side read actually runs
  2. 02What you need on the bench
  3. 03Step 1: Set the pixel budget, then the optics
  4. 04Step 2: Bring up the acquisition session and trigger
  5. 05Step 3: Lock the ROI, preprocess, then decode
  6. 06Step 4: Send the string to the PLC
  7. 07Step 5: Prove the read rate before go-live
  8. 08Common mistakes that cost a week
  9. 09Integrated reader or controller stack
  10. 10Go-live checklist
  11. 11Questions

You have a vision controller on the bench, a camera beside it, and a line that must log a code on every part. A read is not one opaque software block: it is four stages — trigger and acquire, preprocess, decode, report — and each stage has a number you can set from first principles. This guide takes you from an empty controller to a string arriving at the PLC. You will size the optics from the code's module width, choose trigger and exposure, set the decode ROI, and prove a first-pass read rate before go-live. The worked example reads a Code 128 label across a 220 mm conveyor field, and the same arithmetic rescales to your code, camera and field.

What a controller-side read actually runs

Four stages sit between a part arriving and a string leaving the controller. The acquisition session opens the camera, applies exposure and gain, and hands you one frame per trigger. Preprocessing lifts the bars off the background so the decode tool sees two clean grey levels. The decode tool finds the code inside your region of interest and returns the string with a confidence value. The report stage formats that string and sends it to the line controller, including an explicit answer when nothing decoded.

Budget the chain before you write any code. A stopped part with a 2 ms exposure produces a 5 MP frame of about 5 MB; over GigE at its practical 110 MB/s that is roughly 45 ms of transfer, and about 14 ms over USB 3 at 350 MB/s. A full-frame 1D search on a 5 MP image costs tens of milliseconds of controller CPU, and an ROI one-twentieth of the area cuts that roughly twentyfold. Add the stages and a stopped part lands in the 50-90 ms trigger-to-string range — fast enough for most indexing machines.

What you need on the bench

  • A vision controller with camera ports, digital I/O and a vision runtime that includes a 1D/2D code-reading tool. The vision controllers category exists for this: the MV-VC3301H-128G66 includes the VM6200Pro license, an Intel Core i3, 8 GB of RAM and four built-in light channels, so one box decodes and fires the strobe.
  • A global-shutter mono camera sized by the pixel budget in Step 1, chosen from the camera finder.
  • A lens and a light: the lens follows the field calculation in Step 1, and the light is a strobe-capable bar or ring. Add a polarizer to lens and light if labels are shiny.
  • A photoelectric sensor for the trigger, wired to the camera's opto-isolated input.
  • A link to the line controller — Ethernet for TCP, or a serial port — agreed with your controls engineer before anyone writes the handshake.

For a controller that decodes and drives the strobe in one enclosure, this is the reference part:

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

Step 1: Set the pixel budget, then the optics

Decoding is sampling, and sampling has a hard floor: two pixels across the narrowest bar or space is the minimum that decodes at all. Three to four pixels per module is the working target, because blur, tilt and print spread each take a bite. Size the budget from the code on your part, not from the camera you happen to own. The module-width rules behind that number are laid out for Code 128 in Code 128 barcode module size, reading angle and reader distance.

px/module = X ÷ (FOV ÷ pixels across) m = sensor width ÷ FOV f = WD × m ÷ (1 + m) DOF ≈ 2 × N × c × (1 + m) ÷ m²

Worked example — Code 128 with module width X = 0.25 mm, one label per carton on a 220 mm wide conveyor field:

  • The 3 px target needs 0.25 ÷ 3 = 0.083 mm per pixel, or 12 px/mm.
  • Across 220 mm: 220 × 12 = 2,640 sensor pixels.
  • A 2448-pixel 5 MP sensor reaches 2448 ÷ 220 = 11.1 px/mm, so 2.78 px per module — under target, decoding only when the print is perfect.
  • A 4096-pixel 12 MP sensor reaches 18.6 px/mm and 4.66 px per module.
  • Decision: 12 MP here; the 5 MP camera works only if the field narrows to 2448 × 0.083, about 200 mm.

Stay with that camera for the lens: 4096 × 3000 pixels at 3.45 µm gives a sensor width of 4096 × 0.00345 mm = 14.13 mm, so magnification m = 14.13 ÷ 220 = 0.064. At a 250 mm working distance, f = 250 × 0.064 ÷ 1.064 = 15.0 mm, and the nearest stock focal length is 16 mm. Set the working distance to 16 × 1.064 ÷ 0.064 = 265 mm and the field returns to 14.13 × (265 − 16) ÷ 16 = 219.9 mm, on target. Decision: a 16 mm lens at 265 mm working distance.

How sensor width, working distance and field of view set the focal length Rays from the edges of the sensor pass through the lens and spread to the edges of the field of view. The ratio of sensor width to field of view is the magnification m.CameraField of view (FOV)Working distance (WD)≈ fsensor width slensm = s / FOVf = WD × m / (1 + m)
How sensor width, working distance and field of view set the focal length. Rays from the edges of the sensor pass through the lens and spread to the edges of the field of view. The ratio of sensor width to field of view is the magnification m.
Lens focal length, field of view and working distance
Units
Solve for
Focal length
– mm
Field of view
– mm
Working distance
– mm
Magnification
– x
Angle of view
– °
Pixel on the part
– mm

Thin-lens model: m = sensor width / field of view, f = WD × m / (1 + m). Accurate to a few percent above about 150 mm; check the lens's minimum object distance.

Find lenses with this focal length Open the full calculator

Part height varies ±5 mm, so the depth of field must cover 10 mm. Take the circle of confusion as two pixels, c = 2 × 0.00345 mm = 0.0069 mm, with m = 16 ÷ 249 = 0.064. The formula gives 2 × N × 0.0069 × 1.064 ÷ 0.064² = 3.6 × N mm: 10.1 mm at f/2.8 — exactly the need, nothing spare — and 14.4 mm at f/4. Decision: f/4; if the image then runs dark, add light or narrow the field, never open the aperture back up.

Depth of field around the focus plane Light from the lens converges on the focus plane. In front of and behind it, each point spreads into a blur circle; the zone where that blur stays below about a pixel or two is the depth of field. A smaller aperture gives a narrower cone and a deeper zone.depth of fieldfocus planeapertureoutside it, pointsblur into circleswide aperture: steep cone, shallow zonesmall aperture (high F#): deeper zone
Depth of field around the focus plane. Light from the lens converges on the focus plane. In front of and behind it, each point spreads into a blur circle; the zone where that blur stays below about a pixel or two is the depth of field. A smaller aperture gives a narrower cone and a deeper zone.

If the belt runs continuously instead of indexing, exposure shrinks instead of the aperture. At 300 mm/s a 2 ms exposure smears the code 300 × 0.002 = 0.6 mm on the part, which is 0.6 × 0.064 = 0.038 mm at the sensor, or 11 pixels — fatal. Hold blur to one pixel and the strobe width comes out at 0.00345 ÷ 0.064 ÷ 300 = 0.18 ms. Decision: index the part and expose 2 ms, or run continuously with a 0.15 ms flash inside the exposure window.

Step 2: Bring up the acquisition session and trigger

  1. Install the camera driver and SDK on the controller, then the vision runtime. Bring the camera up free-running and confirm live video before any trigger wiring exists.
  2. Create one acquisition session per camera. Set the pixel format to Mono8, turn auto-exposure and auto-gain off, and enter the fixed values from Step 1: 2 ms exposure, gain at 0 dB until the histogram says otherwise.
  3. Wire the photoelectric sensor output to the camera's opto-isolated trigger input and switch the session to hardware trigger, with a short debounce so one part fires exactly one frame.
  4. Fire the strobe from a built-in light channel of the controller — the MV-VC3301H-128G66 provides four — so the flash sits inside the exposure window.
  5. Test with 20 parts: exactly 20 frames arrive, none torn, none doubled.

Hardware trigger is the default whenever parts move. A free-running camera samples the belt at random, and a rolling-shutter sensor makes it worse by exposing rows in sequence, so moving parts want a global shutter. On a manual bench, where the operator places the part and presses a button, the software trigger is fine and saves the wiring.

Step 3: Lock the ROI, preprocess, then decode

Set the region of interest before touching any decode setting. On the 2448 × 2048 frame, an 800 × 300 ROI around the label is 240,000 pixels against 5,013,504 — one twenty-first of the search area — and decode time falls roughly in proportion. Size it on a stopped part at nominal position, then add the positioning tolerance on each side. The same discipline pays on any decoding software, and Setting an ROI for inline code reading works through the speed and reliability gains.

Preprocess from the histogram inside the ROI. Two clean peaks take a fixed threshold at the valley between them; uneven light across the label takes a local adaptive threshold; glare on a shiny label is a lighting fault, not a filter problem — cross-polarize or move to a diffuse source. The preprocessing moves that survive rotation, motion blur and glare are compared in 1D barcode preprocessing for rotation, blur and glare.

Configure the decode tool last, and narrowly. Enable only the symbologies actually printed on your parts, set the expected number of codes per frame to one, and enter the module width from Step 1 so noise at the wrong scale is rejected outright. Turn the inverse option on only if labels can arrive inverted, and mirroring only for codes read through the back of a transparent liner. Every option left open is a chance for decorative print to decode.

Step 4: Send the string to the PLC

The handshake is part of the read, not an afterthought. Define one message format now — decoded string, part counter, status field, fixed delimiter — and on a failed decode send an explicit NOREAD token in that same format. Never silence: a link that says nothing is indistinguishable from a good part the PLC never heard about.

For the transport layer, Barcode reader PLC communication: plan a reliable link lays out the link plan, and Barcode reader as TCP server: wire your PLC as the client covers the connection order when the controller hosts the socket and the PLC dials in.

Archive frames with their results, at least for the no-reads — replaying them offline is how read rate improves without stopping the line, and Barcode inspection image archiving to cloud storage shows one layout. When the codes feed a traceability record, keep image and string together so every scan can be linked to its barcode in a traceability database.

Step 5: Prove the read rate before go-live

  1. Run 500 consecutive parts and log first-pass reads, no-reads and misreads separately. A misread is a defect; a no-read is a retry.
  2. Set acceptance at 99.9% first-pass reads and zero misreads. At 99% you reject one part in a hundred, and the line will complain before your metrics do.
  3. Attack the margins: shift the label 20 mm either side of nominal, tilt the part 15°, and run 100 parts at each point. Out-of-plane tilt foreshortens the modules by the cosine of the tilt — 3% at 15°, 6% at 20°, half the pixel budget at 60°.
  4. Grade the marginal labels, not only the good ones. Print graded C (1.5) or better under ISO/IEC 15416 decodes with room to spare; D-grade labels are where no-reads breed. Barcode reader verification for label inspection covers the grading set-up.
  5. Where a wrong string is worse than a retry, gate the output on the decode confidence value and re-trigger below your threshold. Barcode read confidence: how to judge whether a decode is trustworthy explains how to pick that threshold.

Common mistakes that cost a week

  • Buying resolution instead of shrinking the field. The pixel budget divides by field width first: halving the field doubles every px/module figure in Step 1 for free.
  • Auto-exposure fighting the strobe. The camera stretches exposure between flashes and the read rate wanders with the plant lighting. Fix exposure and strobe width.
  • Every symbology enabled. The tool spends its time proving the logo is not an EAN-13, and decorative print starts decoding.
  • A free-running camera over a moving belt. Frames land anywhere in the part's travel; trigger or strobe instead.
  • Silence on no-read. The PLC ships the part — see the warning in Step 4.
  • One global threshold for every label. A single glare stripe reclassifies half the code; use the local adaptive threshold or fix the light.

Integrated reader or controller stack

Many of these stations do not need the stack at all. An integrated fixed code reader carries camera, lens and light in one housing: you trade the Step 1 exercise for a printed focus distance and a connector block. Build the controller stack when the same camera must also inspect print quality, orientation or presence, or when several stations share one controller and its light channels; Multi-camera acquisition session architecture: the working design shows how those sessions scale.

Question Integrated fixed code reader Controller + camera + vision software
Station reads one code, sends one string Usually the shorter path Works, but you build all four stages
Same camera must also inspect No — a reader only decodes The natural fit
Several stations, one box One reader per station One controller, many cameras
Pixel budget Fixed by the built-in optics You size it in Step 1
Trigger and strobe wiring On the reader's connector block Camera trigger plus controller light channels

Parts that cover the common single-code cases:

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
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

The MV-ID3013PM-12M-WBN pairs a 12 mm focal length with a 1.3 MP sensor on Fast Ethernet in an M12-mount body. The MV-ID813M-05S-WBN-SR adds a built-in white light to a 4.9 mm focal length, 1.3 MP reader on GigE with an M10 mount. The LS-CRD-0028 works from a 2560 × 2048 frame at 30 fps, quotes 60 codes/s and carries an 8 mm lens. Any of them replaces the whole stack where one code is the whole job.

For the controller path in its compact form, the MV-VC2140-128G40-1T runs an Intel N97 with 8 GB RAM, a 128 GB SSD plus 1 TB HDD, and four built-in light channels.

Vision controllersHikrobot MV-VC2140-128G40-1T VC2100 Vision Controller, N97, 8GB+128G SSD+ 1THDDMV-VC2140-128G40-1T
LAN ports
3-4 LAN ports
USB 3 ports
2 USB 3 ports
Light outputs
4 built-in channels
Memory
8 GB
$1,679.00View partBuild a system with it

Go-live checklist

Optics and image:

  • Count pixels across the narrowest bar on a real frame: 3 or more at every part position, because 2 is the floor and print spread takes the rest.
  • Focus set at mid-stack height and locked against vibration.
  • Aperture from the depth-of-field sum in Step 1, with any brightness shortfall solved by light.

Acquisition:

  • Hardware trigger proven on 20 parts for exactly 20 frames.
  • Fixed exposure and gain, with the strobe inside the exposure window on every frame.

Decode and link:

  • ROI locked with the positioning tolerance added on each side.
  • Symbology list limited to what is printed on the parts.
  • NOREAD token defined in the same message format and proven with a plug-pull test.

Rates:

  • A 500-part run at 99.9% first-pass reads and zero misreads before the line goes automatic.

From here, size the lens against your own field and sensor in the lens configurator, keep the code-reading topic page for the decoding details this guide could not fit, or reach us through the contact page — free expert support comes with every order. Commit the Step 1 numbers first; every other choice in the stack follows from them.

Questions

How many pixels do I need per barcode module?

Two pixels per module is the minimum that decodes; three to four gives margin against blur, tilt and print spread. At 3 px per module the camera needs 3 ÷ module-width pixels per millimetre: a 0.5 mm module needs 6 px/mm, 0.25 mm needs 12 px/mm and a 3 mil (0.076 mm) module needs about 39 px/mm. Multiply by field width to get the sensor pixels required across.

Can the controller fire the strobe light itself?

Yes. Vision controllers print built-in light channels — four on the MV-VC3301H-128G66, for instance — and fire them in step with the camera exposure. Trigger the strobe slightly before the frame starts, hold the flash for the whole exposure, and lock both widths in software so brightness never drifts between frames.

What should the vision controller send when a code fails to decode?

An explicit no-read token — for example the string NOREAD with a rising counter — sent in the same message format as a good read. The PLC treats it as a reject or a re-trigger, never as silence. Send the image or an image ID alongside when you can, so no-reads can be replayed offline, and test the link by unplugging it mid-shift.

Is a mono camera better for barcode reading than colour?

Usually yes. A mono sensor gives every pixel its full detail, while a colour sensor interpolates half of them from neighbouring pixels, softening the bar edges where decode contrast is decided. Colour earns its place only when hue must separate the code from the packaging, such as a red print on a tinted carton.

Can one vision controller read codes at several stations?

Yes, within a time budget. Give each camera its own acquisition session, stagger the triggers so frames do not collide, and sum exposure, transfer and decode time per camera before its next part falls due. Four GigE cameras on one controller is a common layout; the binding limit is the decode budget, not the port count.

When should I buy a fixed code reader instead of building the stack?

When the station does one job — read one code, send one string — and space is tight. An integrated reader carries its lens and light, so there is no pixel budget to size; set focus and read. Build the controller stack when the same camera must also check print quality, orientation or presence, or when several stations share one controller.