Your auto exposure limit call returns success, and the exposure keeps riding past it anyway. The value you wrote is rarely the problem — the destination and the units are. On a depth or stereo camera the auto exposure limit is an option that lives on one specific sensor node and is denominated in microseconds, and an SDK will happily write 8000 to a sensor that either ignores the option or clamps it without telling you. The sections below walk the failure in the order you meet it: find the sensor that owns the option, confirm the unit, query the range the firmware accepts, clamp your value to that range, then prove the result on captured frames. The same query-first habit applies to 2D area scan cameras that speak GenICam.
Why does a set call on the auto exposure limit change nothing?
Most silent failures come from the write landing on the wrong sensor node or carrying a value the firmware rejects, because the auto exposure limit is a per-sensor option denominated in microseconds, and an SDK can report success while the sensor quietly ignores the write.
The signature is easy to recognise: a dim scene where exposure stretches until frames smear, exactly as if no limit existed. The call does not raise an error, the viewer may even show your value, and the frames disagree with both. Rank the causes by how often each one turns up:
- Wrong node. The write went to the device root, or to a sensor that does not meter light, instead of the sensor that owns the option.
- Out-of-range value. The number exceeded the sensor's own maximum, was accepted, then clamped or dropped — one range query settles causes one and two in a single pass (query a 3D camera exposure range from the API before you set it).
- Firmware without the feature. No sensor on the device reports the option, so nothing you write can take effect.
- A startup profile runs after your write and reapplies old settings — a distinct ordering failure covered in auto exposure upper limit not applied: check startup settings.
Which sensor owns the auto exposure limit option?
The option is owned by one sensor node, usually the imager whose auto exposure you are actually watching, so the fix is to enumerate the sensors, ask each one whether it supports the option, and keep the node that answers yes.
A depth head is several cameras in one enclosure — a stereo pair, a projector, sometimes an RGB imager — and the SDK maps each to its own sensor object. Auto exposure meters light per sensor, so the option is registered on whichever node does the metering. If your rig meters each imager separately, one limit per node is the honest model, which is exactly how you set auto exposure per stereo camera in a depth rig.
The scoping trap is most common on depth hardware, where one head carries several nodes:
- Type
- Depth / ToF camera
- Type
- Stereo / structured light
- Type
- Stereo / structured light
Write to the device root and the call may succeed against nothing; write to a projector node and there is no exposure to limit. One pass through the sensor list, asking each node whether it supports the option, removes the guesswork in under a minute — and it doubles as the test for cause one in the list above.
What units is the limit written in?
The limit is in microseconds: writing 8000 caps auto exposure at 8000 µs, which is 8 ms, and if you meant an 8 s ceiling the value to write is 8,000,000.
The GenICam standard is the anchor. Its Standard Feature Naming Convention recommends the names and types that cameras use for common features, and its exposure-time feature is denominated in microseconds, so SDK options that mirror it — limits included — inherit the same unit (GenICam overview). Read the unit where the API prints it: most GenICam nodes carry a unit attribute next to the value, and a set helper usually logs or returns it. If an option is ever described in milliseconds, multiply by 1000 before writing — an 8 ms target becomes 8000 µs.
The same convention governs plain exposure writes, which is why setting camera exposure time through a GenICam API in Python also lands in microseconds. The convention covers 2D cameras just as much as depth heads:
- Sensor format
- 1"
- Lens mount
- C-mount
- Interface
- USB3
- Resolution
- 16-25 MP
How do you query the range before writing the value?
Read the minimum, maximum, step increment and current value from the owning sensor before every write; the query costs one call and turns an unknown firmware boundary into two numbers you can clamp against.
- Enumerate the device's sensor list and keep the nodes that report the auto exposure limit as supported.
- On the owning node, read minimum, maximum, step and current value in one pass.
- Clamp the target: below the minimum, use the minimum; above the maximum, use the maximum; inside the range, write it unchanged.
- Respect the step: firmware snaps values to the increment, and camera float values are silently snapped to the nearest increment shows what that does to a write that looked correct.
- Read the value back and treat the returned number as the effective limit.
Illustrative numbers, not a specification: suppose the query on a depth imager returns a minimum of 35 µs, a maximum of 33,333 µs, a step of 1 µs and a current value of 10,000 µs. A request of 8000 µs sits inside the range, so it is written unchanged. A request of 50,000 µs exceeds the maximum by 50,000 − 33,333 = 16,667 µs, so you write 33,333 µs — or 30,000 µs if you want margin, for a reason the next section works out.
How large can the limit get before the frame rate pays for it?
The physical ceiling is one frame period: at 30 fps the period is 33,333 µs, so a 100,000 µs request is three times the ceiling and would drag the stream to about 10 fps even if the firmware accepted it.
Worked example: the station must hold 30 fps in a dim scene, and you are tempted to allow 100,000 µs. One frame at 100,000 µs takes 0.1 s, so the stream tops out at 1 s / 0.1 s = 10 fps — a third of the rate the cell was built for. Clamping to the queried maximum of 33,333 µs keeps the exposure at exactly one period but leaves no room for readout, so the honest setting is 0.9 × 33,333 ≈ 30,000 µs: auto exposure capped just under the period, 30 fps intact. The same arithmetic at 60 fps gives 1,000,000 / 60 = 16,667 µs and a limit of 15,000 µs.
The 90% margin is a rule of thumb for readout overhead; measure the real ceiling by stepping the exposure up and watching the delivered frame rate fall. And if the scene genuinely needs 100,000 µs, no API call will save the frame rate — the fix is more light, and the camera finder filters sensors by the rate and resolution they deliver.
Decision: query the period from the frame rate you must hold, multiply by 0.9, and clamp the limit to that value.
When is the firmware the real reason the option does nothing?
If the option is missing from every sensor, or the range query returns an empty or zero-width range, the installed firmware build probably does not implement the feature, and re-sending the write will never help.
Support for the limit has been firmware-dependent on some depth camera lines: the option can appear, disappear or change range between builds, so a cell that worked before an update can lose the feature. Two checks settle it. First, the option list: re-query every sensor after any firmware change and record whether the option is still reported. Second, the release notes: the manufacturer documents which build added or changed the feature, and firmware comes only from the manufacturer or its distributor, loaded with their documented update tool. After an update, re-query the range instead of reusing old constants — the maximum is often tied to the sensor's readout mode, and a build that changes readout changes the ceiling.
Decision: a returned option with a sane range means the firmware supports it and your bug is scoping or units; an absent option means stop writing values, and control brightness with lighting or manual exposure until a supported build is on the device. If the release notes are silent for your build, ask the vendor with your firmware version and sensor list in hand.
How do you prove the limit is applied before the line runs?
Verification is read-back plus pixels: read the value after writing, dim the scene so auto exposure drives to the ceiling, and check each frame's exposure metadata against the limit you set.
Three checks, in order:
- Read-back assert. After the set, read the option and compare with your clamped target; fail commissioning on any mismatch.
- Force the ceiling. Dim the light or slow the belt until auto exposure wants more than the limit, then confirm the per-frame exposure and gain metadata stops at your value instead of climbing past it.
- Pixel check. In that same dim scene, confirm the smear the limit exists to prevent is actually gone at the cap.
Prevention is a four-line pre-flight: query before every write and never carry a range over from another camera; store the unit with the value, as 30000 µs rather than a bare 30000; re-apply camera settings in a fixed order after startup, because both manual exposure before streaming and the limit-instead-of-a-tuning-file approach fail on ordering; and re-query after every firmware update.
If you are choosing hardware rather than debugging it, match the sensor to the exposure and frame rate you actually need: start at the 3D sensors for depth work or the area scan cameras for 2D, step through the camera configurator, or reach us through the contact page. The 3D camera topic page collects the rest of the depth-camera material.
Questions
Is the auto exposure limit the same as a manual exposure time?
No. A manual exposure time fixes the integration and turns auto exposure off, while the limit only caps what the auto algorithm may choose — the camera still adapts inside that ceiling. Under the GenICam naming convention both quantities are denominated in microseconds, so an 8000 exposure and an 8000 limit describe the same 8 ms either way.
What limit keeps motion blur under one pixel on a moving part?
Work backwards from the blur budget. A part moving at 100 mm/s past pixels of 0.05 mm sweeps one pixel in 0.05 / 100 = 0.0005 s, so the limit must be 500 µs or less; anything longer smears edges by more than one pixel. Set the limit to that value and confirm it on a captured frame of the moving part.
Why did the camera store a different value than the one I wrote?
Most devices round writes to the option's step increment, and some clamp silently to the current maximum. Read the value back immediately after setting; if it differs from your request, the firmware snapped or clamped it, and your code should accept the returned value as the effective limit rather than assuming the write took verbatim.
Does every camera support an auto exposure limit option?
No. The option is optional in the standard feature naming convention, so support varies by sensor, series and firmware build. The reliable test is the same query you run before setting: if no sensor on the device reports the option, treat the feature as unavailable and control brightness through lighting or manual exposure instead.
Can I change the limit while the camera is streaming?
On many devices yes, and the new value applies from the next frame. Some firmwares only accept exposure writes between acquisitions; if your live change does not take, stop the stream, write the limit, then restart. Re-check the value after any restart, because startup profiles can reload settings that run after your write.



