A decode engine that keeps decoding after your imager-mode command is not refusing the switch — it is rejecting the frame. In engines of this class the failure comes down to four things: the wrong opcode, a buffer that drops the checksum, a handshake that gives up too early, or wiring. The mode switch itself is a single command. This guide walks the whole path: the opcode to send, the seven bytes that carry it, the RTS/CTS exchange that earns permission to send, the trigger, and the IMAGE_DATA packet stream you reassemble until the Status Byte ends it. It closes with the transfer-time arithmetic that tells you when UART is the wrong transport altogether.
Which opcode switches the imager to image capture mode?
The Imager_Mode opcode is 0xF7, sent as a framed host command; 0xB1 is the IMAGE_DATA opcode the engine transmits during a capture, so a mode frame built around 0xB1 asks for a message the engine only ever sends — and the engine stays in decode mode.
The symptom is silence: no error frame, no response, the engine decoding barcodes as if nothing had arrived. The reason is that opcodes have a direction. 0xF7 belongs to the host-to-engine direction. 0xB1 belongs to engine-to-host: it appears in the packets you receive after a capture, never in a command you send. A mode frame built around the receive opcode is not a mode frame, and the engine discards it.
The switch is sticky. The engine stays in image capture mode until another operation completes, so you switch once and then capture repeatedly — trigger after trigger — before returning it to decoding. The same mode decision on finished readers, continuous decoding versus one-shot image capture, is covered in fixed reader operating modes: decode mode versus snapshot mode.
How do you frame the command so the engine accepts it?
Frame it as length byte, payload, checksum — the length byte counts every byte after it except the checksum, so the mode command with length 0x05 puts 7 bytes on the wire, and a 6-byte buffer quietly drops the checksum, so the frame dies half-read.
Engines across this class share an SSI-style command set: same frame shape, same handshake lines, opcodes in the same direction. The mode frame field by field:
-
Byte 0 — 0x05, length:counts the opcode through the last parameter. It never counts itself and never counts the checksum. -
Byte 1 — 0xF7, opcode:Imager_Mode. -
Byte 2 — source byte:says who sent the command. Engines that filter on source drop frames carrying the wrong value; the host value sits in the engine's command reference. -
Bytes 3-5 — parameters:the target mode plus reserved values. -
Byte 6 — checksum:one byte computed over the five bytes the length byte counts.
Total on the wire: 1 + 5 + 1 = 7 bytes. Engines in this family differ on one point: some carry a two-byte checksum instead. The exclusion rule is identical — the length byte never counts it — and the buffer grows to 1 + 5 + 2 = 8 bytes.
/* Host-side C. Variable and function names are ours; opcode values are the protocol's. */
uint8_t frame[7] = {0}; /* 1 length + 5 payload + 1 checksum byte */
frame[0] = 0x05; /* payload length: opcode .. last parameter */
frame[1] = 0xF7; /* Imager_Mode opcode */
frame[2] = 0x04; /* message source byte, host */
frame[3] = 0x01; /* parameter: image capture mode */
frame[4] = 0x00; /* parameter, reserved */
frame[5] = 0x00; /* parameter, reserved */
frame[6] = checksum8(&frame[1], 5); /* over the bytes the length counts */
uart_write(frame, 7);
The parameter values above stand in for the mode numbers in your engine's command reference; the frame shape, the length byte and the opcode are the parts that must be exact.
How does the RTS/CTS handshake work before you send?
Raise RTS, wait for the engine to raise CTS, send the frame, drop RTS — and give CTS a real 100 ms budget, because a bare 100-iteration loop can expire in microseconds and abort the send before the engine has even seen the request.
uint32_t t0 = now_ms(); /* our millisecond timer, 0 at boot */
gpio_write(RTS, 1); /* request to send */
while (gpio_read(CTS) != 1) {
if (now_ms() - t0 > 100) { /* 100 ms budget for the answer */
gpio_write(RTS, 0);
return ERR_HANDSHAKE; /* our own error code */
}
}
status = uart_write(frame, 7);
gpio_write(RTS, 0); /* release the line */
The handshake is symmetric, and the receive half matters more than the send half. While the image streams, the engine is the transmitter: it asks on its RTS and waits for your CTS. A host that never grants CTS — or an adapter that ties the engine's send-permission input low — receives the first packets and then nothing. Wire both directions, and during a capture never take your CTS output away.
Failing loudly is part of the design. For the discipline of giving up cleanly and telling the rest of your program why, see abort a serial barcode read when the scanner reads nothing.
How do you trigger the capture and receive the image stream?
Trigger with START_SESSION (opcode 0xE4) over the serial link or by pulling the TRIGGER line; the engine captures and immediately streams many IMAGE_DATA packets (0xB1), and the Status Byte in each packet flags the last one — end on that flag, never on silence.
- Send the framed Imager_Mode command. If your engine answers with a response frame, the command reference defines it; many in this class stay silent, so treat the loopback test as your acceptance test.
- Trigger: send the framed START_SESSION command (0xE4), or pull the TRIGGER line. Both do the same job; the hardware line is faster and survives serial-link faults.
- Read packets. Each carries the IMAGE_DATA opcode 0xB1, a chunk of image bytes and a Status Byte.
- Append each chunk to a linear image buffer of width × height × bytes per pixel.
- Count packets and bytes as they arrive.
- Stop when the Status Byte flags the final packet, then cross-check the total byte count before you decode.
- Return the engine to decoding — in this family, any other operation ends image mode.
The Status Byte does for this stream what the IEND chunk does for a PNG file: an end marker carried inside the data itself, so the receiver never guesses from silence.
Size the receive path for the line, not the average. At 921600 baud with 8N1 a byte lands every 10 bits ÷ 921,600 baud = 10.9 µs; a ring buffer holding at least two packets, drained by DMA or an interrupt handler that only copies, keeps pace. A buffer sized by feel loses the middle of the image, and the loss shows up later as a decoder bug — barcode decoder image compatibility: fix input type errors covers the input mismatches that follow. For how production readers choose between sensor, serial and free-run triggering, see fixed barcode reader trigger modes: sensor, serial or free-run.
How long does one image take to arrive over UART?
A 1.2 MP mono frame — 1280 × 960 pixels at one byte per pixel — is 1,228,800 bytes, which at 115200 baud and 8N1 is 12,288,000 wire bits and about 107 seconds of line time, before packet headers.
The arithmetic, step by step:
- Pixels: 1280 × 960 = 1,228,800 pixels.
- Bytes: 1,228,800 pixels × 1 byte/pixel = 1,228,800 bytes.
- Wire bits: 1,228,800 × 10 bits/byte = 12,288,000 bits.
- Line time: 12,288,000 ÷ 115,200 baud = 106.7 s ≈ 107 s.
| Link | Throughput at 8N1 | Time for 1,228,800 bytes |
|---|---|---|
| UART 115200 baud | 11,520 B/s | 106.7 s |
| UART 921600 baud | 92,160 B/s | 13.3 s |
| UART 3,000,000 baud | 300,000 B/s | 4.1 s |
| Fast Ethernet, sustained TCP | roughly 5-10 MB/s | 0.12-0.25 s |
One frame per second needs the wire to carry 12,288,000 bits inside a second — more than 12 Mbaud — and no engine in this class offers a UART that fast. That single line is the transport decision.
Packet count follows from payload size. As an example packet size, 1,024 bytes of image data per packet gives 1,228,800 ÷ 1,024 = 1,200 packets per frame; count them as they arrive and compare against the Status Byte's end flag. Headers add a few percent to the total, and any image timeout shorter than the transfer time aborts every capture — software trigger image timeout: why one-shot capture misses frames covers sizing that timeout.
When is UART image mode the wrong tool?
Move off UART the moment you need more than one occasional still per cycle, a live view, or archived images: anything above roughly one image every 15 s at 921600 baud, or a live preview, belongs on a Fast Ethernet, GigE or USB reader.
Occasional still, host-side decode, existing serial link. Keep the engine. UART image mode earns its place when you need one image per audit event, not per cycle: switch, capture, return, and budget the line time from the table above. If you decode on the host anyway, software barcode decode in your own camera app: build or buy a reader is the decision that comes next.
One image per cycle, trace or archiving. Use a fixed reader with a network interface and skip the protocol work. The LS-CRD-0052 is an Ethernet reader with a 12 mm focal length in a dual aviation plug housing, built for fixed stations.
- Resolution
- Up to 3 MP
- Shutter
- Global
- Interface
- Ethernet
For glare on the archived frames, polarization belongs at the lens. The MV-IDB005EXI-05NRP is a Fast Ethernet reader with a 1.3 MP sensor, a 4.63 mm focal length, a 70 mm focus distance and a polarized light path — glare that never reaches the sensor never reaches your archive.
- Interface
- Fast Ethernet
- Resolution
- Up to 3 MP
- Shutter
- Global
- Lens mount
- M5.8
Image and decode at rate. The LS-CRD-0028 grabs 2560 x 2048 frames at 30 fps, decodes at up to 60 codes/s and hands images over Fast Ethernet — both outputs, no mode switching.
- Interface
- Fast Ethernet
- Resolution
- 5 MP
- Sensor format
- 1/1.7"
- Shutter
- Global
Engines that stream video and decode barcodes at the same time exist; choose that architecture at selection time rather than bridging it later. For an operator-facing preview, decode barcodes from a live RTSP or MJPEG video stream keeps the display traffic off your control link.
Inspection on the device. Smart cameras run the inspection on board and hand you results, with full frames over the network when you need them: the MV-SC5060XM-08M-WBN is a 6 MP mono model with an 8 mm focal length, M12-mount, on GigE.
Bench or line-side station on USB. The LS-CRD-0047 is a 1.2 MP reader with a 60-120 mm reading distance on USB 2.0 — the image arrives as a device read, not a protocol.
- Resolution
- Up to 3 MP
- Shutter
- Global
- Interface
- USB
More code reading set-ups are collected under that topic. To size a whole station — reader, lens, light, controller — start here:
The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.
What should you check before you commit to the design?
Check five things before you freeze the design: the byte count on the wire, the CTS timeout path, transfer time against your cycle time, receive buffering against the packet rate, and polarization if glare will be in the images — in that order, because physical-layer faults outnumber protocol faults.
- Seven bytes on the wire, seen on a scope or logic analyzer. If the trace shows six, the checksum is still missing from your buffer.
- A passed loopback test. Exactly 7 bytes returned, checksum stable across sends.
- A 100 ms CTS timeout with a defined error path. The send function must fail loudly, not silently skip the frame.
- Transfer time against cycle time. Take the row for your baud rate from the table above and add a few percent for packet headers.
- A receive ring buffer of at least two packets, drained by DMA or a copy-only interrupt. The timing section gives the per-byte deadline at your baud rate.
- Field of view at the capture distance. Image mode inherits the engine's optics; fixed focus code reader field of view: match focal length to sensor gives the arithmetic.
- Polarization if the target shines. Code reader accessories include lens covers that remove specular glare before it becomes pixels; for smart cameras, the MV-SC3000-C-HP is a square semi-polarizing lens cover.
Why does the engine still ignore a correctly framed command?
When the frame is right and the engine still decodes, look at the physical link first: TX and RX swapped, no common ground, a baud mismatch against the engine's default, or a handshake line whose idle polarity you have backwards — in that order of likelihood.
Swap TX and RX and try once; it is the fastest test on the list and the most common fault. Then, in order: confirm a common ground between host and engine; confirm your UART matches the engine's default settings, typically 115200 baud, 8 data bits, no parity, one stop bit; check handshake polarity, because a line that idles high makes your assert indistinguishable from idle; then revisit the source byte and the one-versus-two-byte checksum from the framing section.
If all of that passes, capture the exact bytes with the logic analyzer and compare them against the command reference for your engine's firmware revision — opcode sets do change between engine generations, and the trace settles it in minutes. If you are selecting hardware rather than debugging it, walk the fixed code readers category or the camera and reader finder, or start a configuration with your cycle-time number in hand. Bring the trace to the contact page and we will read it with you.
Questions
Why does the engine stay in decode mode after my mode command?
Three silent failures look identical: the frame never left (your CTS wait timed out and returned before a single byte was sent), the checksum byte is missing from the buffer, or the opcode is one the engine only ever transmits, like the image-data opcode. Prove the link first with a command that produces a visible or audible response — an aiming-pattern or beep command from the same reference — then send the mode frame and confirm 7 bytes on the wire with a scope.
How do I detect the last image packet without relying on a timeout?
Read the Status Byte in every IMAGE_DATA packet and stop when it flags the final one, then cross-check the byte count: pixels wide × pixels high × bytes per pixel must equal the bytes you reassembled. Do not infer the end from silence on the line — the engine pauses between packets while it fills its buffer, and gaps of a few hundred milliseconds mid-image are normal. A timeout is a fault detector, not an end-of-image detector.
What baud rate would move a 1.2 MP frame in under one second?
None that a UART delivers: 1,228,800 bytes at 8 bits per pixel is 9,830,400 payload bits, and with 8N1 start and stop bits the wire carries 12,288,000 bits — so a one-second transfer needs more than 12 Mbaud. Practical UART rates top out near 3 Mbaud, which moves the frame in about 4.1 s. For one frame per second or faster, use a reader with Fast Ethernet, GigE or USB, where the same image is a fraction of a second.
Can the engine decode barcodes while it is in image capture mode?
Not in this protocol family: the engine stays in image capture mode until another operation completes, and decoding counts as one of those operations. Sequence each cycle as decode, switch to image mode, capture, then return — or run the image through your own software decoder on the host, which removes the mode switching from the cycle. Engines that stream video and decode at the same time exist; choose that architecture up front if you need both continuously.
My CTS never asserts — what do I check first?
Check the physical link before the protocol: the engine's TX must go to your RX and vice versa, both sides share a common ground, and your UART settings match the engine's default — typically 115200 baud, 8 data bits, no parity, one stop bit. Then check handshake polarity: if the line idles high, driving it high is not a request at all. An engine that never raises CTS with RTS asserted, wiring proven and settings matched, is one that is not powered or is asleep.




