7.17. Sensor knobs¶
Beyond pixformat() and
framesize(), the CSI class
exposes a handful of per-sensor controls that almost every
application reaches for sooner or later – mounting
orientation, exposure, gain, white balance, and a few
debugging aids. Each one maps directly onto a sensor concept
covered earlier; the API just provides a Python handle for
the register write the driver makes underneath.
All of the methods below act on the underlying sensor. They
all push register writes over the sensor’s I2C control
bus, so the cost is microseconds and
the new setting takes effect on the next exposure –
typically the next snapshot().
7.17.1. Orientation¶
The camera does not know which way up it has been mounted. Two flip flags applied at the sensor turn the picture the right way around before any pixel leaves the chip:
csi0.hmirror(True)
csi0.vflip(True)
hmirror() flips left-to-right and
vflip() flips top-to-bottom. Together they
cover the cases that come up in practice: a board mounted
upside down (both flags True), a board behind a
front-silvered mirror (hmirror only), or one looking at a
reflected scene from below (vflip only).
Because the flip happens in the sensor’s read-out logic, there is no CPU cost and no memory overhead – the frame lands in the framebuffer already oriented.
7.17.2. Exposure¶
Exposure is the integration time – how long the photodiode in each pixel collects charge before the row is read out, in microseconds. The driver starts with the sensor’s auto-exposure loop running, so the camera tries to keep the average pixel value near a target. Disabling the loop pins the exposure to a value the application chooses:
csi0.auto_exposure(False, exposure_us=8000)
A fixed exposure is the right choice when the scene brightness is stable and the application needs predictable motion blur or consistent frame-to-frame intensity for thresholding. Reading the current exposure back – whether the loop set it or the application did – is a separate call:
us = csi0.exposure_us()
Calling auto_exposure() with True and no
exposure value hands control back to the loop.
7.17.3. Gain¶
Gain is the amplifier applied to the pixel voltage before it reaches the ADC, in decibels. Like exposure, the driver starts with the auto-gain loop on. Two patterns come up often. Capping the ceiling lets the loop adapt to lighting but stops it from amplifying noise indefinitely in dim scenes:
csi0.auto_gain(True, gain_db_ceiling=16)
Pinning a fixed gain is the right move when the application also pins the exposure – gain stability matters for applications that compare pixel values frame to frame, like colour tracking:
csi0.auto_gain(False, gain_db=0)
The current gain reads back through gain_db().
Whenever the application disables auto-gain it should also
disable auto-white-balance and auto-exposure – otherwise the
control loops still in play will pull the image around in
ways that defeat the fixed gain.
7.17.4. White balance¶
White balance is the per-channel gain the ISP applies to the red, green, and blue channels coming out of the debayer stage so a white object looks white under any colour of light. The auto-white-balance loop computes those three gains from the per-region statistics the ISP collects on every frame and applies them on the next frame.
Most applications leave the loop running. Colour tracking is the common exception – the gains are also what the loop will push around to chase a coloured object, so if the application is trying to find a red blob, the loop will quietly dim the red channel and the blob will stop matching. Locking the loop fixes that:
csi0.auto_whitebal(False)
Pass an explicit (r, g, b) tuple in decibels for repeatable
colour calibration – the same gains across boards and
sessions:
csi0.auto_whitebal(False, rgb_gain_db=(0.0, 0.0, 0.0))
The current gains read back as a tuple through
rgb_gain_db().
7.17.5. Frame rate cap¶
Sensors run at their native frame rate by default – 30 to 60 frames per second on most parts, much higher on the high-speed sensors when the framesize is small enough. Capping the rate lets the application throttle the camera to whatever the downstream processing can keep up with:
csi0.framerate(15)
On sensors that support a hardware rate control the call also lengthens the per-frame exposure budget, which can help in low light; on the others the driver simply skips the extra frames at the framebuffer level.
7.17.6. Test pattern¶
The colour-bar test pattern is built into most sensors and useful for separating an imaging problem from an output problem. Turning it on bypasses the photodiode array and sends a fixed pattern down the same pixel data path:
csi0.colorbar(True)
If the test pattern looks right but the live image does
not, the fault is in the optics or the sensor’s analog
front-end; if even the test pattern is corrupted, the
problem is somewhere on the pixel-data bus or in the
pixformat() / framesize()
configuration. Pass False to return to the live image.
See csi.CSI for the full API, including the
sensor-specific ioctl() commands that expose
controls unique to particular sensor families.