System designHow-to

Detect a USB camera disconnected during acquisition from stale frames

How to detect a USB camera that disconnected during acquisition: watch the frame ID, time out on stale frames, and poll the device list.

LumaSpec Vision12 min read Share on LinkedIn

On this page 10 sections
  1. 01Why the grab call keeps succeeding
  2. 02The rule: warn at three frame periods, fail at ten
  3. 03The watchdog in code
  4. 04Five steps to a self-diagnosing loop
  5. 05Telling dropout, death and reboot apart
  6. 06Why USB links drop mid-run
  7. 07When the usual answer is wrong
  8. 08When to move the camera to GigE
  9. 09Checks before you ship
  10. 10Questions

Continuous acquisition from a USB camera has one treacherous failure mode: when the camera disconnects or dies, the grab call keeps succeeding and hands you the last buffered frame — complete, sharp, no error attached. The inspection then runs on a frozen image until someone notices the line making scrap. The fix is not a different grab call. It is a watchdog that reads the frame ID on every frame you accept, times how long that ID has gone without advancing, and polls the device list when it stalls. Below you get the thresholds, the code shape, the recovery ladder, and the hardware changes that stop the drops from happening at all. The pattern applies to any USB3 machine-vision camera in continuous mode, and it transfers to GigE, where the transport layer's heartbeat does part of the work for you.

Why the grab call keeps succeeding

When the link dies, nothing announces it to your application. The host driver still holds the last complete buffer in its acquisition queue, and a grab call that dequeues buffers returns that frame as a perfectly valid image. Some stacks block on the next call; others keep re-serving the newest frame indefinitely. Either way, the error you hoped for never arrives. The visible symptom is always the same: a sharp, stationary image and a delivered-frames-per-second counter that falls to zero.

The root of the problem is that the grab call reports on the host queue, not on the camera. Only the frame pipeline can prove that frames are still being produced, and the per-frame identifier is how you watch it. A deep queue masks a dropout for as long as its buffered frames last, so keep it shallow. The trap has a startup cousin: before the first frame ever arrives, a status poll is the only reliable readout, as last valid buffer before first trigger: poll the status call shows. If you are still choosing the mode, continuous camera acquisition mode for live image loops covers the setup.

The rule: warn at three frame periods, fail at ten

Set both thresholds as multiples of the measured frame interval, not the datasheet maximum. Warn when no new frame ID has arrived for 3 frame periods. Declare the link failed at 10 frame periods.

T_frame = 1 / f_measured T_warn = 3 × T_frame T_fail = 10 × T_frame

The multiples carry the logic. With a host queue two buffers deep, a dropout stops new IDs within two periods, so 3 periods catches it with margin. Host-side pauses of 100–200 ms from garbage collection or driver stalls deliver frames late but with new IDs, which the ID check reads as a slowdown, not a fault. The 10-period fail threshold clears that jitter before you act on it.

Worked example. The LS-CMR-0166 is a 12 MP USB3 camera that streams 4000 × 3000 pixels at 30 fps. Work the numbers at a 2 ms exposure, well inside the frame period. One frame takes 1 / 30 = 33.3 ms. The warn threshold is 3 × 33.3 ms ≈ 100 ms, and the fail threshold is 10 × 33.3 ms ≈ 333 ms, so set the fail timer to 350 ms. The payload explains why gaps are unambiguous: 4000 × 3000 pixels × 1 byte of 8-bit mono data is 12 MB per frame, and 12 MB × 30 fps = 360 MB/s, or 2.88 Gbit/s. That is most of what a 5 Gbit/s USB3 link sustains in practice, so a link-level retry shows up at once as a missing frame ID.

Raise the exposure to 50 ms and the frame period stretches past 50 ms; a fixed 100 ms warn threshold would false-alarm. Recompute the median interval over the last few seconds of frames and the thresholds follow the camera.

The watchdog in code

The timer is deliberately small. In Python-shaped pseudocode, not tied to any SDK:

# Illustrative watchdog - adapt the two calls to your SDK
last_id: int = -1          # frame ID of the newest accepted frame
last_new_ms: float = 0.0   # monotonic clock when that ID first appeared
interval_ms: float = 33.3  # measured median frame interval

def check(frame_id: int, now_ms: float) -> str:
    global last_id, last_new_ms
    if frame_id != last_id:
        if frame_id < last_id:
            return "reboot"   # counter ran backwards: the camera restarted
        last_id = frame_id
        last_new_ms = now_ms
        return "ok"
    age_ms = now_ms - last_new_ms
    if age_ms > 10 * interval_ms:
        return "fail"
    if age_ms > 3 * interval_ms:
        return "warn"
    return "ok"

Prove it before you trust it. Feed the test frames with IDs 100, 101 and 102 arriving at 0, 33 and 67 ms on a monotonic clock, then keep calling check(102, now) with the clock running: it returns ok at 67 ms, warn at 170 ms (103 ms of staleness against a 100 ms threshold), and fail at 403 ms (336 ms against 333 ms). One more setting completes it: give the grab call itself a timeout equal to the fail threshold, so a stack that blocks instead of re-serving raises a timeout error you can branch on.

Five steps to a self-diagnosing loop

  1. Enable per-frame metadata. In your SDK this is the chunk-data or buffer-information toggle; every delivered frame must carry its frame ID and timestamp. Without them you are watching the queue, not the camera.
  2. Set the host queue to two buffers. A deep queue hides a dropout behind stale-but-valid frames; two buffers bound the mask to two frame periods.
  3. Run the watchdog on every frame and on a timer tick, and latch every inspection result invalid while the state is warn. A stationary frame must never produce a pass.
  4. On fail, poll the device list at 1 Hz and compare the camera's identifier, then classify with the table below.
  5. Recover by identifier: close the handle, rescan, reopen the same unit, restart acquisition, and reset the ID baseline. Retry at 1 s, 5 s and 15 s; if the third attempt fails, alarm for a human.

Recovery deserves its own reading: acquisition timeout after power cycle: enable continuous transfer covers how the stream restarts, and camera has power but not detected: USB link checks after a cable swap walks the physical checks that follow.

Telling dropout, death and reboot apart

Observation at fail Meaning Action
Frame ID frozen, camera still listed, same identifier Host or driver stall Stop and restart acquisition on the open handle
Frame ID frozen, camera gone from the list Cable, connector or power lost Rescan and reopen by identifier
Camera listed with a different identifier Camera was swapped Halt the station, re-verify the setup
Frame ID jumped backwards Camera rebooted or re-enumerated Reopen and reset the baseline

A USB device without a programmed serial number is identified by the operating system from its physical port: a second camera of the same model plugged into that port inherits the old name and the old driver binding, which is why unmanaged stations accumulate renamed instances. Industrial cameras built to the USB3 Vision standard publish a unique device identifier the transport layer can read. The MV-CU020-90GC is a 2.5 MP GigE camera with a 1/1.7" sensor and a C-mount. Make a programmed identifier a purchase requirement for any unattended station. A station that keeps inspecting after a swap is a calibration incident, not an inconvenience: vision tools that stop detecting parts after a camera swap documents that failure.

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
Up to 3 MP
$309.00View partBuild a system with it

When the poll returns an enumeration error instead of a device, the camera has failed electrically — device descriptor request failed: a USB camera that died electrically is that case. On Linux the same fault surfaces as VIDIOC_DQBUF error 19: diagnose USB camera drops, and enumeration that succeeds while the SDK stays blind is covered by USB camera in lsusb but not detected by the vision SDK on Linux. The watchdog discipline governs industrial networks too — how a TCP/IP controller stack detects a disconnected cable is built on timeouts against expected traffic, exactly like your frame-ID timer.

Most drops are mechanical. A connector carrying a stiff, unclamped cable on a moving arm works loose in weeks, and a USB3 link does not tolerate partial contact: it trains, retrains, then vanishes. Use a drag-chain-rated cable with locked connectors: the LS-CBL-0219 is a 3 m USB3.0 camera cable built for drag-chain duty. Clamp the cable to the camera stand within 100 mm of the connector so the connector never carries the cable's weight.

Cables3 m USB3.0 camera cable, high-flex (drag chain) (LS-CBL-0219)LS-CBL-0219$62.00View partBuild a system with it

Do not put the camera behind a hub. A hub adds a repeater, two more connector pairs and a shared 5 V budget; a bus-powered hub browns out exactly when the camera draws peak current, and no watchdog fixes a hub that power-cycles every few minutes.

Power domains cause the drops that look random. When a bus-powered camera shares a USB ground with a machine whose drives sit on another supply, the shield closes a ground loop, and the dropouts start correlating with motor starts and weld cycles. Break the loop with a galvanic USB isolator in the link, or power the camera from the machine side — machine vision camera for continuous shooting, external power covers the supply design, and depth camera detected but no image: check USB power budget first covers the starvation symptom. The control side of a plant shows the same physics: a CNC that stops mid-run on USB dropouts traces to the same three causes — connector, power, ground.

One host quirk remains: some machines latch a failed USB port in the host controller until the machine is powered down completely, and a warm reboot does not clear it. If recovery only works after a full power-down, move the camera to an add-in controller card.

When the usual answer is wrong

Three cases break the default watchdog, and each has a committed fix. Long exposure: at 50 ms exposure the frame period grows past 50 ms and any fixed 100 ms threshold false-alarms, so always threshold on the measured median interval. Triggered acquisition: no free-running frames exist, so arm on the trigger instead — alarm when a pulse goes unanswered for two trigger periods plus 500 ms, and confirm each answer carries a new frame ID; the mode pitfalls are collected in hardware trigger stops after one frame: check acquisition mode. Late frames with new IDs: that is a host stall from display redraw, garbage collection or a saturated disk, not a camera fault — the camera produced the frame, so fix the host and leave the camera open.

When to move the camera to GigE

Fix detection first, then choose the transport on reach, camera count and grounding. USB3 gives you 5 Gbit/s over 3–5 m of passive cable and is right for one or two cameras per host at short range. GigE gives 1 Gbit/s per link over 100 m, power on the same cable, and a standardized heartbeat between client and camera, so a silent peer is detected by design rather than by your own timer. Leave the heartbeat enabled in production — disabling it is a debugging convenience, and why the GigE Vision heartbeat timeout stops your stream after a pause explains what happens when it trips.

The MV-CU020-90GC and LS-CMR-0166 sit on opposite sides of that choice: the first is a 2.5 MP GigE camera, the second a 12 MP USB3 camera, both with a 1/1.7" rolling-shutter sensor and a C-mount.

Specification MV-CU020-90GC LS-CMR-0166
Sensor model GMAX4002 Sony IMX226
Pixel size 4 μm × 4 μm 1.85 μm
Resolution 2048 × 1200 4000 × 3000 (12MP)
Max. frame rate 49 fps @ 2048 × 1200 Bayer GB 8 30 fps
Data interface Gigabit Ethernet (1000 Mbit/s), compatible with Fast Ethernet (100 Mbit/s) USB 3.0
Price $309.00 $560.00

All 2 share: Sensor size 1/1.7". Values as printed in each product's data sheet; open a part for its drawing and full specifications.

On the GigE side, the LS-CBL-0199 is a 3 m high-flex camera cable with screw locks.

Cables3 m GigE camera cable, high-flex (drag chain), screw locks (LS-CBL-0199)LS-CBL-0199$54.00View partBuild a system with it

Checks before you ship

  • Grab timeout set to the fail threshold — 350 ms in the worked example.
  • Host queue two buffers deep; thresholds computed from the measured frame interval.
  • Every inspection result gated on watchdog state, frame ID logged with each result.
  • Recovery reopens by identifier, retrying at 1 s, 5 s and 15 s before alarming.
  • Cable drag-chain rated, screw-locked, clamped within 100 mm of the connector; camera on a root port, never a hub.
  • Isolator fitted wherever camera and machine share no ground domain.
  • Acceptance test: pull the cable mid-run and the station alarms within 1.5 s; replug and production resumes within 20 s; swap in a same-model camera and the station halts.

When you are ready to specify hardware, the camera finder filters by interface and mount, cables and stands and stages complete the bill of materials, or start at the camera step of the configurator. Bring your frame rate and exposure to our support team and we will size the watchdog thresholds with you.

Questions

How quickly can I detect a disconnected USB camera?

Within ten frame periods. Measure the median frame interval, warn at three times it and fail at ten: at 30 fps that is 100 ms to warn and 333 ms to fail, plus up to one second for the 1 Hz device-list poll that classifies the fault. The acceptance test is pulling the plug mid-run: the station must alarm within about 1.5 s. Host pauses of 100-200 ms deliver frames late but with new IDs, which the watchdog correctly treats as a slowdown, not a fault.

Why does the acquisition return the last image with no error?

Because the grab call only reports on the host-side queue, and the queue still holds the last complete frame. The transport layer knows the device is gone; the frame API does not. Two changes surface it: set the grab timeout to your fail threshold so a blocking stack raises a timeout you can branch on, and gate every inspection result on the frame-ID watchdog. A dequeuing stack never raises anything on its own.

How do I tell a disconnected camera from a swapped one?

Compare device identifiers, not friendly names. A USB device without a programmed serial number is identified by its physical port, so a same-model replacement inherits the old name and even the old driver binding. Industrial cameras built to the USB3 Vision standard publish a unique device identifier through the transport layer: record it when you open the camera, and compare it on every fault and rescan. A changed identifier means a swap, so halt the station before it inspects with the wrong calibration.

Can a frozen frame pass my inspection?

Yes, and that is the real danger. The last buffered frame is a valid, in-focus image of a part that may no longer be in front of the lens; presence checks, edge finds and code reads all succeed on it. The only defense is gating: a result computed while the watchdog is in warn or fail state must fail the part and stop the station. Log the frame ID with every result so you can reconstruct exactly when the stream froze.

Should I switch from USB3 to GigE to avoid disconnects?

Decide on reach, camera count and grounding, not on fear of drops. Below about 5 m with one or two cameras per host, USB3 moves 5 Gbit/s and the watchdog covers the silent-failure mode. For longer runs, many cameras on one host, power over the data cable and a standardized heartbeat, choose GigE at 1 Gbit/s per link. A silent dead peer is possible on both transports, and detection stays your job on both.

Do USB hubs cause camera dropouts?

Frequently. A hub inserts a repeater, two extra connector pairs and a shared 5 V budget between camera and host; a bus-powered hub browns out when the camera draws inrush at enumeration or peak current during capture. Give every camera a root port on the host. If ports run out, a self-powered industrial hub is acceptable: check that its per-port supply covers the camera's stated current, and keep the watchdog running, because hubs fail too.