Cameras & sensorsHow-to

Camera demo has no exposure or gain controls: what to do

The demo captures frames but shows no exposure, gain or sensor-ID controls — they live one layer down. Here is the path to them, and when to swap cameras.

LumaSpec Vision12 min read Share on LinkedIn

On this page 9 sections
  1. 01Why does the demo capture images but offer no exposure or gain control?
  2. 02Is a missing configuration file the reason the controls are missing?
  3. 03Where do exposure, gain and the sensor ID live in the stack?
  4. 04How do you set manual exposure and gain from your own code?
  5. 05How short an exposure does the part actually need?
  6. 06Why does the exposure you set snap back to another value?
  7. 07How do you read the sensor ID without the demo?
  8. 08When should you replace the camera instead of patching the demo?
  9. 09Questions

Frames arrive, but the demo that delivers them has no exposure slider, no gain setting and no way to read the sensor ID. That combination — working capture, missing controls — is a wrapper problem, not a camera problem: the sample binds only the handful of functions it demonstrates, and manual exposure, gain and device identification stay in the layer beneath it. This guide is for engineers building an inspection or monitoring machine around a board-level camera or USB camera module who need deterministic control from their own code. You will confirm where the controls live for your device type, set them manually with the auto loops off, prove the write took effect, and finish with a clear keep-or-replace decision. If your camera offers no software control path at all, that different case is covered in Camera has no software exposure control: what to do instead.

Why does the demo capture images but offer no exposure or gain control?

Because the demo is a capture sample: the wrapper binds only what the sample needs, and exposure, gain and sensor-ID readback remain in the native library below it. The vendor's GUI, built on that same library, exposes all three — which is proof the hardware path exists.

The demo exists to show the fastest route to a live image, so its wrapper imports acquisition and little else. Before writing any code, open the GUI tool from the same SDK package and move its exposure and gain controls: if the image brightens and darkens, the sensor answers those writes and your task is purely software. Two related traps sit next door. A capture API can expose properties the wrapper hides from the demo surface — check the source object, not the on-screen control panel, as Camera exposure property not found: check the source object shows. And some capture layers reduce a property to an on/off flag, the case worked through in Camera property shows only on or off in the capture API.

Is a missing configuration file the reason the controls are missing?

No. A wrong or missing sensor configuration file stops the camera earlier in the chain — no image, a corrupt image or the wrong resolution — and your frames prove the register table loaded, so the missing controls are an API-surface gap that no configuration file can close.

USB camera shields and carrier boards take a per-sensor configuration file, published by board revision, interface, sensor and lane count. Loading the wrong sensor's file gives distorted or unreadable output, not missing function calls. Match your exact revision first; where the vendor publishes nothing for a late board revision, the previous revision's file for the same sensor and lane count is the usual working fallback. If your device enumerates as a standard UVC camera, no configuration file is involved at all — that path is described in No config file needed: get a UVC camera streaming over USB. One useful side effect of this exercise: the file that produces a clean image names the sensor you actually own, which helps with the ID question later.

Where do exposure, gain and the sensor ID live in the stack?

One level below the demo, in the device's control layer: the feature tree a GigE Vision or USB3 Vision camera carries on board, the video-control properties of a UVC device, or the controls the sensor driver publishes on Linux.

Device type Where exposure and gain live How your code reaches them
GigE Vision / USB3 Vision the camera's own feature tree any GenICam or GenTL library
UVC device video-control properties the operating system's capture API
Linux module the driver's control set the V4L2 control interface
Proprietary USB shield the vendor's native library the vendor's demo or GUI only

The industrial path is the feature tree. Every GigE Vision and USB3 Vision camera describes its controls in a machine-readable file on the device, and the standard's naming convention fixes the ones you need: Exposure Time, a float in microseconds, and Gain, with auto selectors that hand control to you when set to Off. The same tree carries the device information block — model, serial and version nodes — which is where sensor identification comes from. When only the camera holds that file, your host code can still fetch it, the situation handled in GenTL node maps: when only the remote device has an XML.

The UVC and V4L2 paths trade standard names for reach: the operating system exposes the controls as properties of the capture device. On Linux the writes must also be accepted by the sensor driver — when they are silently ignored, follow V4L2 exposure and gain settings ignored by a sensor driver. The proprietary row of the table is the one that hurts: with no standard layer, no alternative client ever exists.

How do you set manual exposure and gain from your own code?

Open the device through its standard interface instead of the demo's wrapper, switch the exposure and gain auto selectors to Off, write the values, and read them back — in that order, with streaming stopped or freshly started, or the writes can be dropped.

You need the camera reachable in the vendor GUI, a host library for its control layer, and the exposure budget from the next section.

  1. Prove the hardware path in the vendor GUI first: change exposure there and watch the image respond. If the GUI cannot move it either, stop — the fault is below the software, in the sensor module, its wiring or the configuration file.
  2. Open the device from your own process through its standard layer — a GenTL producer for a Vision-standard camera, the capture API for UVC, the device node for V4L2 — and close the GUI first so it does not hold the device.
  3. Set the exposure auto selector to Off, then write Exposure Time as a float in microseconds. Set the gain auto selector to Off, then write Gain.
  4. Read both features back. The read-back must equal what you wrote; anything else means the write landed nowhere.
  5. Run the halving test: drop the exposure from 4000 µs to 2000 µs and the mean gray value, after subtracting black level, must halve. Exposure integrates light linearly, so this is the decisive test.
  6. Lock the sequence into your startup order — manual values before acquisition starts — because initialization order decides whether the first frames carry your settings. The failure mode is dissected in Set manual exposure before streaming: initialization order.
# Illustrative host code against a GenICam-style feature tree.
# Quoted names are the camera's feature names; the set/get calls are ours.
exposure_us = 500.0   # float, microseconds - from the blur budget below
gain_value = 0.0      # float, in the unit the feature declares

cam.open()
cam.set_enum("Exposure Auto", "Off")      # manual control
cam.set_float("Exposure Time", exposure_us)
cam.set_enum("Gain Auto", "Off")
cam.set_float("Gain", gain_value)

assert cam.get_float("Exposure Time") == exposure_us  # the write landed

For the full Python pattern against a GenICam device, including the exposure write and its read-back, see Setting camera exposure time through a GenICam API in Python. On UVC, the same steps map to the capture API's property setters, and the range the device reports there is the truth, demo or no demo.

How short an exposure does the part actually need?

Divide your scale by the part's speed and cap the exposure there: at 0.05 mm per pixel and 100 mm/s the limit is 500 µs for one pixel of blur, and 250 µs for sub-pixel edges.

blur_mm = speed_mm_per_s × exposure_s exposure_max_s = scale_mm_per_pixel / speed_mm_per_s

Worked example. A belt runs at 100 mm/s. The station covers a 64 mm field of view on a sensor 1280 pixels wide, so the scale is 64 mm / 1280 px = 0.05 mm per pixel. The one-pixel budget is 0.05 / 100 = 0.0005 s, or 500 µs; sub-pixel edge fitting wants half a pixel, so 250 µs. Now the timing check: at 30 fps the frame period is 1/30 s = 33,333 µs, so a 500 µs exposure is a 1.5 percent duty cycle (500 / 33,333 = 0.015). Holding the brightness of a 10 ms reference exposure needs 20 times the light (10,000 µs / 500 µs = 20). One lens stop buys a factor of 2 — M12 board lenses opened from F2.8 to F2.0 gather twice the light, the trade explained in M12 lens light gathering: pick a lower f-number, same focal length — so the remaining factor of 10 comes from lighting. The clean escape is a strobe: pulse the light for 50 µs inside a 1,000 µs exposure made in the dark, and blur becomes 100 mm/s × 50 µs = 5 µm, one tenth of a pixel, independent of the exposure value.

Why does the exposure you set snap back to another value?

Because something else still owns the loop: the camera's auto selector was never set to Off, your own framework rewrites exposure every frame, or a second client is attached — fix all three, write once before streaming starts, and the value holds.

Work the causes in order of likelihood. First the camera: an auto selector left unset retunes your value within a few frames, so set both selectors to Off before writing. Second your own stack: many frameworks drive exposure automatically unless you disable that explicitly — where each mode lives is covered in Automatic iris, exposure and gain control in machine vision and Runtime camera parameter control: exposure and white balance live. Third, another client: the vendor GUI left open keeps the device and overwrites you; a Vision-standard camera accepts one controlling client at a time, the conflict behind GigE camera open fails in a second tool: exclusive control. Close every other tool, then re-run the read-back and the halving test.

How do you read the sensor ID without the demo?

Through the same control layer: the device information nodes of the feature tree on a Vision-standard camera, the sensor list in the vendor GUI, or the enumeration strings the device reports to the operating system over USB.

Identification is a register or descriptor read, not an image-pipeline function, which is why the capture demo never had it. On a camera with a feature tree, the device information category exposes model, serial number and firmware version as readable nodes — the same calls as exposure, different names. Over USB, the host reads the manufacturer, product and serial strings at enumeration, and they appear in the operating system's device list, which usually identifies the module family. On a multi-sensor shield, the vendor's enumeration call — the one the GUI uses to list its channels — is the only source of the per-channel sensor ID; if the wrapper does not bind it, the GUI display answers for now, and the replacement decision below answers for the machine's lifetime.

When should you replace the camera instead of patching the demo?

Replace it when the stack has no standard control layer — a proprietary USB shield whose vendor confirms the wrapper will not gain exposure, gain or ID calls — because then no tool you write or buy will ever reach those registers.

The decision, case by case:

  • The GUI moves exposure and a standard control layer exists: keep the camera and write host code as in the steps above.
  • The GUI moves exposure but the stack is proprietary and the vendor will not extend the wrapper: keep it only if fixed auto exposure works for your part; otherwise replace.
  • Nothing moves exposure, even in the GUI: the fault is hardware or configuration, not the demo — fix that before judging the camera.
  • Deterministic exposure and gain are required for the machine: standardize on GigE Vision or USB3 Vision.

Replacement does not mean abandoning the small form factor. Board-level cameras with standard interfaces keep the build compact while giving every client the full feature tree — for example the LS-BCM-0003, a 3.1 MP USB3 board camera with the IMX252 sensor, or the LS-BCM-0020, a 6.3 MP GigE board camera with the IMX178 sensor. For a fixed station with room to spare, full area scan cameras widen the lens and sensor choice.

Three compact replacements that answer the control question:

Board-level cameras3.1 MP USB3 board-level camera, IMX252, 1/1.8" global shutter, 120 fps (LS-BCM-0003)LS-BCM-0003
Sensor format
1/1.8"
Lens mount
C-mount
$690.00View part
Board-level cameras6.3 MP board-level camera, IMX178, 1/1.8" rolling shutter, 18 fps (LS-BCM-0020)LS-BCM-0020
Sensor format
1/1.8"
Lens mount
CS-mount
$290.00View part
Board-level camerasHikrobot MV-CB060-10UM-B 6 MP Board Level Camera, USB3, IMX178, Mono, Bare Board, V4MV-CB060-10UM-B
Sensor format
1/1.8"
Interface
USB3
$239.00View part

Checks before ordering:

  • The data sheet names the control standard — GigE Vision, USB3 Vision or GenICam compliance. If it names none, assume the proprietary row of the table above.
  • A host library exists for your operating system and language: a GenTL producer or a vendor SDK with a documented control API.
  • The printed minimum exposure sits below your blur budget — in the worked example, 500 µs, so look for a camera that goes lower.
  • The gain feature's unit is printed, in dB or raw counts, so your zero-gain baseline means what you think.
  • Global shutter if the part moves; the full trade-off set is in Board level camera selection for embedded vision machines.
  • The mount you need is in the filter list when you narrow the camera finder.
CamerasBoard-level cameras

Compact cameras to build in

120 models · from $179.00

Take your exposure budget and field-of-view numbers into the build and let it narrow the field: configure a camera. If the stack you own is the proprietary one, tell us the module and the target — free expert support comes with every order, and the contact page reaches the applications team. The wider bring-up sequence is in Board camera evaluation checklist for inspection systems, and more camera-side fixes sit under the cameras topic page.

Questions

Can you add exposure and gain to the demo by editing its source code?

Only if the wrapper already binds the underlying calls and simply never calls them; search its imports for the control functions first. If the binding is absent, there is nothing in the demo to call — write your own host code against the camera's standard interface instead. Ten minutes reading the wrapper's module list answers which situation you are in.

Why can the vendor GUI set exposure when the demo cannot?

The GUI links the full native library, not the thin wrapper the sample uses, so it reaches the same register writes and the sensor enumeration your code needs. Run it once, change exposure there, and confirm the image responds — that proves the hardware path is fine and the gap is purely in the demo's API surface.

Is gain an acceptable substitute for a longer exposure?

No. Gain multiplies signal and noise together, while exposure collects more photons. Halving the exposure and adding 6 dB of gain restores brightness but halves the photons, costing about 3 dB of signal-to-noise — a factor of 1.4 — because noise falls only with the square root of collected light. Spend exposure where motion allows, gain where it does not.

What exposure freezes a moving part for sub-pixel measurement?

Divide your scale by the part speed, then halve it. At 0.05 mm per pixel and 100 mm/s, one-pixel blur allows 500 µs; sub-pixel edge fitting wants half of that, 250 µs. If the light budget will not support it, strobe instead: a 50 µs light pulse inside a 1 ms exposure leaves 5 µm of blur regardless of the camera's timing.

Which cameras can every tool control without a vendor demo?

GigE Vision and USB3 Vision cameras. Both carry a machine-readable feature tree on the device, so any GenICam-aware library, commercial vision tool or open-source host lists the same features — exposure, gain, device information — under the same names. A proprietary USB module without that tree is controllable only through the vendor's own software.