### Deferred Camera Initialization Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Initialize the camera driver and hardware manually using `init()` when deferred initialization is needed, for example, after Wi-Fi connection. Always call `deinit()` to free resources. ```python from camera import Camera, FrameSize, PixelFormat # Deferred initialization — useful when Wi-Fi must connect first cam = Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG, init=False) # ... do other setup work here ... cam.init() # now safe to capture img = cam.capture() print("Captured", len(img), "bytes") cam.deinit() # release PSRAM, reset hardware ``` -------------------------------- ### Setup Event Listeners for Camera Controls Source: https://github.com/cnadler86/micropython-camera-api/blob/master/examples/CameraSettings.html Initializes event listeners for all input elements (sliders, checkboxes) and select dropdowns to update camera settings. It also fetches initial values for each control. ```javascript function setupEventListeners() { const inputs = document.querySelectorAll('input'); inputs.forEach(input => { const type = input.type === 'checkbox' ? 'checkbox' : 'range'; input.addEventListener(type === 'checkbox' ? 'change' : 'input', () => { const value = type === 'checkbox' ? (input.checked ? 1 : 0) : input.value; updateValue(input.id, value); }); fetchValue(input.id, type); }); const selects = document.querySelectorAll('select'); selects.forEach(select => { select.addEventListener('change', () => { updateValue(select.id, select.value); }); fetchValue(select.id, 'select'); }); } ``` -------------------------------- ### Get Camera Driver Version Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Import the camera module and retrieve the version of the camera driver. ```python import camera vers = camera.Version() ``` -------------------------------- ### GainCeiling Enum and Camera Capture Example Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Sets the maximum gain multiplier for automatic gain control (AGC) and demonstrates capturing an image with this setting. ```APIDOC ## GainCeiling Enum ### Description Maximum automatic gain multiplier. ### Options - **GainCeiling.X2** (0) - 2× max gain - **GainCeiling.X4** (1) - **GainCeiling.X8** (2) - **GainCeiling.X16** (3) - **GainCeiling.X32** (4) - **GainCeiling.X64** (5) - **GainCeiling.X128** (6) - 128× max gain (brightest but noisiest) ## Camera Capture with Gain Ceiling ### Description This example demonstrates how to initialize the camera, set a gain ceiling, capture an image, and print its size. ### Usage ```python from camera import Camera, FrameSize, PixelFormat, GainCeiling with Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG) as cam: cam.gainceiling = GainCeiling.X8 # Limit AGC to 8x gain img = cam.capture() print("Gain-limited frame:", len(img), "bytes") ``` ``` -------------------------------- ### Poll Frame Readiness with frame_available() Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Illustrates how to poll for frame readiness using `frame_available()` without blocking, enabling manual cooperative multitasking. This example captures a frame, releases the buffer, and then waits for the next frame to be available before capturing it. ```python from camera import Camera, FrameSize, PixelFormat cam = Camera(frame_size=FrameSize.QVGA, pixel_format=PixelFormat.JPEG) img = bytes(cam.capture()) cam.free_buffer() # tell driver to grab the next frame # Do other work while waiting import time deadline = time.ticks_ms() + 2000 while not cam.frame_available(): if time.ticks_ms() > deadline: print("Timeout waiting for frame") break # perform other tasks here if cam.frame_available(): img = bytes(cam.capture()) print("Got frame:", len(img), "bytes") cam.deinit() ``` -------------------------------- ### Enable Color Bar Test Pattern Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Overlays the sensor's built-in color-bar test pattern on the output. This is useful for verifying the camera pipeline when a lens is not attached. The example compares the size of the test image with a real image. ```python from camera import Camera, FrameSize, PixelFormat with Camera(frame_size=FrameSize.QVGA, pixel_format=PixelFormat.JPEG) as cam: cam.colorbar = True test_img = bytes(cam.capture()) cam.free_buffer() cam.colorbar = False real_img = bytes(cam.capture()) print("Color bar test image:", len(test_img), "bytes") print("Real image :", len(real_img), "bytes") ``` -------------------------------- ### Change Camera Resolution at Runtime Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Dynamically updates the sensor output resolution using the `frame_size` property. Setting this after initialization avoids a full `reconfigure()` and preserves other sensor settings. The example iterates through different resolutions and prints the resulting image size. ```python from camera import Camera, FrameSize, PixelFormat with Camera(pixel_format=PixelFormat.JPEG) as cam: sizes = [FrameSize.QQVGA, FrameSize.QVGA, FrameSize.VGA, FrameSize.SVGA] for fs in sizes: cam.frame_size = fs img = bytes(cam.capture()) cam.free_buffer() print(f"{cam.pixel_width}x{cam.pixel_width}: {len(img)} bytes") ``` -------------------------------- ### Camera Initialization using Context Manager Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Utilize the context-manager protocol (`with Camera() as cam:`) for automatic initialization and deinitialization, ensuring resources are properly managed. ```python from camera import Camera, FrameSize, PixelFormat # Context-manager style (deinit called automatically) with Camera(frame_size=FrameSize.QVGA, pixel_format=PixelFormat.JPEG) as cam: img = cam.capture() with open("photo.jpg", "wb") as f: f.write(img) # cam.deinit() was called here automatically ``` -------------------------------- ### Initialize Camera with Board-Specific Firmware Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Construct a Camera instance when using board-specific firmware where pins are pre-defined. This is the simplest initialization method. ```python from camera import Camera, GrabMode, PixelFormat, FrameSize, GainCeiling # --- Board-specific firmware (pins pre-defined at build time) --- cam = Camera() ``` -------------------------------- ### Initialize Camera with Custom Imaging Defaults Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Configure camera settings like pixel format, frame size, JPEG quality, frame buffer count, and grab mode when using board-specific firmware. ```python from camera import Camera, GrabMode, PixelFormat, FrameSize, GainCeiling # --- Board-specific firmware with custom imaging defaults --- cam = Camera( pixel_format=PixelFormat.JPEG, frame_size=FrameSize.QVGA, # 320x240 jpeg_quality=90, # 0–100 %, higher = better quality fb_count=2, # double-buffer for higher FPS grab_mode=GrabMode.LATEST, # always return the freshest frame ) ``` -------------------------------- ### Camera.__init__() Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Constructs and optionally initializes a Camera instance. Pin arguments are optional for board-specific firmware but required for generic firmware. The camera is initialized automatically unless init=False is passed. ```APIDOC ## Camera.__init__() — Construct and optionally initialize a camera object ### Description Creates a `Camera` instance. When using a board-specific precompiled firmware or a firmware built with pin definitions in `mpconfigboard.h`, no pin arguments are required. For generic firmware, all hardware pin numbers must be supplied explicitly. The camera is initialized automatically unless `init=False` is passed. ### Method `Camera(...)` ### Parameters * `data_pins` (list[int]) - Optional - GPIO pin numbers for D0–D7. * `vsync_pin` (int) - Optional - GPIO pin number for VSYNC. * `href_pin` (int) - Optional - GPIO pin number for HREF. * `sda_pin` (int) - Optional - SCCB / I2C data pin number. * `scl_pin` (int) - Optional - SCCB / I2C clock pin number. * `pclk_pin` (int) - Optional - GPIO pin number for PCLK. * `xclk_pin` (int) - Optional - GPIO pin number for XCLK. * `xclk_freq` (int) - Optional - XCLK frequency in Hz (e.g., 10_000_000 or 20_000_000). * `powerdown_pin` (int) - Optional - GPIO pin number for power down, -1 if not connected. * `reset_pin` (int) - Optional - GPIO pin number for reset, -1 if not connected. * `pixel_format` (PixelFormat) - Optional - The desired pixel format (e.g., `PixelFormat.JPEG`). * `frame_size` (FrameSize) - Optional - The desired frame size (e.g., `FrameSize.QVGA`). * `jpeg_quality` (int) - Optional - JPEG quality setting (0-100). * `fb_count` (int) - Optional - Number of frame buffers to use. * `grab_mode` (GrabMode) - Optional - The grab mode (`GrabMode.WHEN_EMPTY` or `GrabMode.LATEST`). * `init` (bool) - Optional - Whether to initialize the camera automatically (default is True). ### Request Example ```python from camera import Camera, GrabMode, PixelFormat, FrameSize, GainCeiling # Board-specific firmware (pins pre-defined at build time) cam = Camera() # Board-specific firmware with custom imaging defaults cam = Camera( pixel_format=PixelFormat.JPEG, frame_size=FrameSize.QVGA, # 320x240 jpeg_quality=90, # 0–100 %, higher = better quality fb_count=2, # double-buffer for higher FPS grab_mode=GrabMode.LATEST, # always return the freshest frame ) # Generic firmware: every pin must be specified cam = Camera( data_pins=[15, 17, 18, 16, 14, 12, 11, 48], # D0–D7 vsync_pin=38, href_pin=47, sda_pin=40, # SCCB / I2C data scl_pin=39, # SCCB / I2C clock pclk_pin=13, xclk_pin=10, xclk_freq=20_000_000, # 10 MHz or 20 MHz depending on sensor powerdown_pin=-1, # -1 = not connected reset_pin=-1, pixel_format=PixelFormat.JPEG, frame_size=FrameSize.VGA, jpeg_quality=85, fb_count=2, grab_mode=GrabMode.LATEST, init=True, # initialize immediately (default) ) print("Sensor:", cam.sensor_name) # e.g. "OV2640" print("Max frame size:", cam.max_frame_size) print("Width x Height:", cam.pixel_width, "x", cam.pixel_height) ``` ``` -------------------------------- ### Camera Constructor Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Demonstrates how to create a Camera object, either with default settings or by specifying various configuration parameters like pixel format, frame size, and pin assignments. ```APIDOC ## Camera Constructor ### Description Instantiates a Camera object. This can be done with default arguments for non-generic firmware or by providing specific keyword arguments for configuration. ### Method `Camera()` ### Parameters #### Keyword Arguments - **data_pins** (List[int]) - Required for generic firmware - List of data pins. - **vsync_pin** (int) - Required for generic firmware - VSYNC pin. - **href_pin** (int) - Required for generic firmware - HREF pin. - **sda_pin** (int) - Required for generic firmware - SDA pin. - **scl_pin** (int) - Required for generic firmware - SCL pin. - **pclk_pin** (int) - Required for generic firmware - Pixel clock pin. - **xclk_pin** (int) - Optional - XCLK pin (set to -1 if external clock source). - **xclk_freq** (int) - Optional - XCLK frequency in Hz (default: 20000000). - **powerdown_pin** (int) - Optional - Powerdown pin (default: -1). - **reset_pin** (int) - Optional - Reset pin (default: -1). - **pixel_format** (PixelFormat) - Optional - Pixel format (default: RGB565). - **frame_size** (FrameSize) - Optional - Frame size (default: QQVGA). - **jpeg_quality** (int) - Optional - JPEG quality (default: 85). - **fb_count** (int) - Optional - Frame buffer count (default: 2 for ESP32S3, 1 otherwise). - **grab_mode** (GrabMode) - Optional - Grab mode (default: LATEST for ESP32S3, WHEN_EMPTY otherwise). - **init** (bool) - Optional - Initialize camera at construction time (default: True). ### Request Example ```python # Using defaults cam = Camera() # With specific arguments cam = Camera(pixel_format=PixelFormat.JPEG, frame_size=FrameSize.QVGA, jpeg_quality=90) # For generic firmware cam = Camera(data_pins=[1,2,3,4,5,6,7,8], vsync_pin=9, href_pin=10, sda_pin=11, scl_pin=12, pclk_pin=13, xclk_pin=14) ``` ``` -------------------------------- ### Initialize Camera with Generic Firmware and Explicit Pins Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt For generic firmware, specify all hardware pin numbers explicitly, along with camera settings. Ensure `xclk_freq` matches your sensor's requirements. ```python from camera import Camera, GrabMode, PixelFormat, FrameSize, GainCeiling # --- Generic firmware: every pin must be specified --- cam = Camera( data_pins=[15, 17, 18, 16, 14, 12, 11, 48], # D0–D7 vsync_pin=38, href_pin=47, sda_pin=40, # SCCB / I2C data scl_pin=39, # SCCB / I2C clock pclk_pin=13, xclk_pin=10, xclk_freq=20_000_000, # 10 MHz or 20 MHz depending on sensor powerdown_pin=-1, # -1 = not connected reset_pin=-1, pixel_format=PixelFormat.JPEG, frame_size=FrameSize.VGA, jpeg_quality=85, fb_count=2, grab_mode=GrabMode.LATEST, init=True, # initialize immediately (default) ) print("Sensor:", cam.sensor_name) # e.g. "OV2640" print("Max frame size:", cam.max_frame_size) print("Width x Height:", cam.pixel_width, "x", cam.pixel_height) ``` -------------------------------- ### Import Camera Module (Standard) Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Import the necessary classes from the standard camera module. This is the general way to use the API. ```python from camera import Camera, GrabMode, PixelFormat, FrameSize, GainCeiling ``` -------------------------------- ### Initialize Camera Stream Page Source: https://github.com/cnadler86/micropython-camera-api/blob/master/examples/CameraSettings.html Sets up the camera stream page by populating the frame size dropdown, setting up event listeners for all controls, and checking for sensor-specific features upon page load. ```javascript document.addEventListener("DOMContentLoaded", () => { populateFrameSizeDropdown(); setupEventListeners(); checkSensorFeatures(); }); ``` -------------------------------- ### Build the MicroPython Camera API Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Use the provided build script to compile the MicroPython camera API. Specify the path to your MicroPython source and the target board. Use the help flag for available options. ```bash ./build.sh -m path/to/micropython -b ESP32_GENERIC_S3 ``` -------------------------------- ### Add ESP32-Camera Driver to Build Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Configuration snippet for idf_component.yml to include the ESP32-Camera driver from a Git repository. ```yaml espressif/esp32-camera: git: https://github.com/cnadler86/esp32-camera.git ``` -------------------------------- ### Camera.init() / Camera.deinit() Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Manually initializes or deinitializes the camera driver and hardware. `init()` should be called if the camera was constructed with `init=False`. `deinit()` should be called to free PSRAM buffers before sleeping or when the camera is no longer needed. The Camera object also supports the context-manager protocol. ```APIDOC ## Camera.init() / Camera.deinit() — Manual initialization and teardown ### Description Explicitly initializes or deinitializes the camera driver and hardware. Call `init()` when the camera was constructed with `init=False`. Always call `deinit()` before sleeping or when the camera is no longer needed to free PSRAM buffers. The `Camera` object also supports the context-manager protocol (`with Camera() as cam:`), which calls `deinit()` automatically on exit. ### Methods * `init()`: Initializes the camera. * `deinit()`: Deinitializes the camera and frees resources. ### Parameters * `init()`: No parameters. * `deinit()`: No parameters. ### Request Example ```python from camera import Camera, FrameSize, PixelFormat # Deferred initialization — useful when Wi-Fi must connect first cam = Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG, init=False) # ... do other setup work here ... cam.init() # now safe to capture img = cam.capture() print("Captured", len(img), "bytes") cam.deinit() # release PSRAM, reset hardware # Context-manager style (deinit called automatically) with Camera(frame_size=FrameSize.QVGA, pixel_format=PixelFormat.JPEG) as cam: img = cam.capture() with open("photo.jpg", "wb") as f: f.write(img) # cam.deinit() was called here automatically ``` ``` -------------------------------- ### Reconfigure Camera Parameters at Runtime Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Demonstrates changing camera settings like pixel format, frame size, grab mode, and buffer count dynamically using `reconfigure()`. Note that this resets sensor register settings such as brightness and contrast. ```python from camera import Camera, FrameSize, PixelFormat, GrabMode cam = Camera(pixel_format=PixelFormat.JPEG, frame_size=FrameSize.QQVGA) # Switch to VGA JPEG with double-buffering for higher throughput cam.reconfigure( pixel_format=PixelFormat.JPEG, frame_size=FrameSize.VGA, grab_mode=GrabMode.LATEST, fb_count=2, ) print("New size:", cam.pixel_width, "x", cam.pixel_height) # 640 x 480 # Reconfigure to raw RGB565 for image processing cam.reconfigure(pixel_format=PixelFormat.RGB565, frame_size=FrameSize.QVGA) print("Format:", cam.pixel_format) # 0 (PixelFormat.RGB565) cam.deinit() ``` -------------------------------- ### Create Camera Object with Defaults Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Construct a camera object using default settings. This is suitable for non-generic firmware or when camera model/pins are defined in mpconfigboard.h. ```python cam = Camera() ``` -------------------------------- ### Configure Camera Settings Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Set image quality and brightness. Vertical flip can also be enabled. ```python cam.quality = 90 # The quality goes from 0% to 100%, meaning 100% is the highest but has probably no compression print("cam.brightness =", cam.brightness) camera.vflip = True #Enable vertical flip ``` -------------------------------- ### Define Camera Model for Wrovr Kit Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Add this line to your board config file to specify the WROVER KIT camera model. ```c #define MICROPY_CAMERA_MODEL_WROVER_KIT 1 ``` -------------------------------- ### Create Camera Object with Keyword Arguments Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Construct a camera object specifying pixel format, frame size, JPEG quality, frame buffer count, and grab mode. Adapt these parameters to your specific needs. ```python cam = Camera(pixel_format=PixelFormat.JPEG, frame_size=FrameSize.QVGA, jpeg_quality=90, fb_count=2, grab_mode=GrabMode.WHEN_EMPTY) ``` -------------------------------- ### Create Camera Object for Generic Firmware Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md When using generic firmware, the camera constructor requires specific pin assignments. Ensure these pins match your board's configuration to avoid errors. ```python cam = Camera( data_pins=[1,2,3,4,5,6,7,8], vsync_pin=9, href_pin=10, sda_pin=11, scl_pin=12, pclk_pin=13, xclk_pin=14, xclk_freq=20000000, powerdown_pin=-1, reset_pin=-1, ) ``` -------------------------------- ### Camera Initialization Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Manually initializes the camera if it was not initialized during construction (i.e., if `init=False` was passed to the constructor). ```APIDOC ## Camera Initialization ### Description Initializes the camera hardware. This method must be called if the camera was constructed with `init=False`. ### Method `cam.init()` ### Parameters None ### Request Example ```python cam.init() ``` ``` -------------------------------- ### Camera I2C Bus Sharing Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Demonstrates how to share the I2C bus between the camera and other peripherals by passing an existing `machine.I2C` object during camera initialization. ```APIDOC ## Shared I2C bus ### Description The camera's SCCB control bus is I2C-compatible. Pass an existing `machine.I2C` object to share the bus with other peripherals (e.g., IMUs, environmental sensors). The `sda_pin`/`scl_pin` parameters are then ignored. **Note:** `SoftI2C` is not supported. ### Usage ```python import machine from camera import Camera, FrameSize, PixelFormat # Create a hardware I2C bus shared between camera and another sensor i2c = machine.I2C(0, scl=machine.Pin(39), sda=machine.Pin(40), freq=400_000) # Find all devices on the bus before camera init devices = i2c.scan() print("I2C devices before camera init:", [hex(d) for d in devices]) # Pass the I2C bus to the camera — no sda_pin/scl_pin needed cam = Camera( i2c=i2c, data_pins=[15, 17, 18, 16, 14, 12, 11, 48], vsync_pin=38, href_pin=47, pclk_pin=13, xclk_pin=10, frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG, ) # Camera and other devices share the same bus devices_after = i2c.scan() print("I2C devices after camera init:", [hex(d) for d in devices_after]) # Write to another device on the shared bus while camera is running i2c.writeto(0x68, b'\x6B\x00') # e.g. wake MPU-6050 img = cam.capture() print("Captured:", len(img), "bytes") cam.deinit() ``` ``` -------------------------------- ### Initialize Camera Manually Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md If the camera was not initialized during construction (init=False), call the init() method manually. Most camera settings are only accessible after initialization. ```python cam.init() ``` -------------------------------- ### camera.Version() Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Queries the version of the underlying esp32-camera driver linked into the firmware. Returns a string identifying the driver version. ```APIDOC ## camera.Version() ### Description Module-level function that returns a string identifying the underlying `esp32-camera` driver version linked into the firmware. ### Usage ```python import camera ver = camera.Version() print("Driver version:", ver) # e.g. "2.0.13-14b2be7" ``` ``` -------------------------------- ### Import Camera Module (AsyncIO) Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Import the necessary classes from the asynchronous camera module for use with asyncio. Ensure you import from the 'acamera' package. ```python from acamera import Camera, GrabMode, PixelFormat, FrameSize, GainCeiling ``` -------------------------------- ### Configure Pins and Parameters for Unsupported Cameras Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Define camera pins and parameters in your board config file for unsupported camera models. Ensure correct pin assignments and adjust frequency, buffer count, JPEG quality, and grab mode as needed. ```c #define MICROPY_CAMERA_PIN_D0 (15) #define MICROPY_CAMERA_PIN_D1 (17) #define MICROPY_CAMERA_PIN_D2 (18) #define MICROPY_CAMERA_PIN_D3 (16) #define MICROPY_CAMERA_PIN_D4 (14) #define MICROPY_CAMERA_PIN_D5 (12) #define MICROPY_CAMERA_PIN_D6 (11) #define MICROPY_CAMERA_PIN_D7 (48) #define MICROPY_CAMERA_PIN_PCLK (13) #define MICROPY_CAMERA_PIN_VSYNC (38) #define MICROPY_CAMERA_PIN_HREF (47) #define MICROPY_CAMERA_PIN_XCLK (10) #define MICROPY_CAMERA_PIN_PWDN (-1) #define MICROPY_CAMERA_PIN_RESET (-1) #define MICROPY_CAMERA_PIN_SIOD (40) // SDA #define MICROPY_CAMERA_PIN_SIOC (39) // SCL #define MICROPY_CAMERA_XCLK_FREQ (20000000) // Frequencies are normally either 10 MHz or 20 MHz #define MICROPY_CAMERA_FB_COUNT (2) // The value is between 1 (slow) and 2 (fast, but more load on CPU and more ram usage) #define MICROPY_CAMERA_JPEG_QUALITY (85) // Quality of JPEG output in percent. Higher means higher quality. #define MICROPY_CAMERA_GRAB_MODE (1) // 0=WHEN_EMPTY (might have old data, but less resources), 1=LATEST (best, but more resources) ``` -------------------------------- ### Capture Single Frame with Camera API Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Demonstrates basic frame capture, copying to bytes, and releasing the driver buffer. Also shows on-the-fly format conversion when the camera is in JPEG mode. ```python from camera import Camera, FrameSize, PixelFormat with Camera(frame_size=FrameSize.QVGA, pixel_format=PixelFormat.JPEG, fb_count=2) as cam: # --- Basic capture --- frame = cam.capture() print("Frame size (bytes):", len(frame)) # e.g. 8432 # --- Copy to bytes and release driver buffer immediately --- img_bytes = bytes(cam.capture()) cam.free_buffer() # driver can now refill the slot # Save to file with open("snap.jpg", "wb") as f: f.write(img_bytes) # --- On-the-fly format conversion (JPEG camera → grayscale output) --- gray = cam.capture(PixelFormat.GRAYSCALE) print("Grayscale frame:", len(gray), "bytes") ``` -------------------------------- ### Asynchronous Frame Capture with acamera Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Shows how to use the `acamera` module for non-blocking frame capture within an asyncio event loop, suitable for running alongside network coroutines. It initializes the camera, streams JPEG frames over HTTP, and handles cleanup. ```python import asyncio import network from acamera import Camera, FrameSize, PixelFormat cam = Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG, fb_count=2, init=False) async def stream_handler(reader, writer): cam.init() writer.write(b'HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n') await writer.drain() try: while True: frame = await cam.acapture() # non-blocking wait for next frame if not frame: break writer.write(b'--frame\r\nContent-Type: image/jpeg\r\n\r\n') writer.write(bytes(frame)) await writer.drain() finally: cam.deinit() writer.close() await writer.wait_closed() async def main(): server = await asyncio.start_server(stream_handler, "0.0.0.0", 80) print("Streaming on port 80") await asyncio.sleep(3600) asyncio.run(main()) ``` -------------------------------- ### Populate Frame Size Dropdown Dynamically Source: https://github.com/cnadler86/micropython-camera-api/blob/master/examples/CameraSettings.html Fetches the maximum supported frame size from the camera and populates a dropdown menu with available frame size options up to the maximum. ```javascript function populateFrameSizeDropdown() { const frameSizes = ["R96x96", "QQVGA", "128X128", "CIF", "HQVGA", "R240x240", "QVGA", "320X320","CIF", "HVGA", "VGA", "SVGA", "XGA", "HD", "SXGA", "UXGA", "FHD", "P_HD", "P_3MP", "QXGA", "QHD", "WQXGA", "P_FHD", "QSXGA"]; const frameSizeDropdown = document.getElementById('frame_size'); fetch('/get_max_frame_size') .then(response => response.text()) .then(maxFrameSize => { const maxSizeIndex = parseInt(maxFrameSize, 10); frameSizeDropdown.innerHTML = ''; frameSizes.forEach((size, index) => { if (index <= maxSizeIndex) { const option = document.createElement('option'); option.value = index; option.textContent = size; frameSizeDropdown.appendChild(option); } }); }) .catch(error => { console.error('Error fetching max frame size:', error); }); } ``` -------------------------------- ### Configure Exposure and Gain Properties Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Control automatic and manual exposure/gain settings. Disable exposure_ctrl and gain_ctrl for fully manual control. ```python from camera import Camera, FrameSize, PixelFormat, GainCeiling with Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG) as cam: # Automatic exposure + gain (default) cam.exposure_ctrl = True cam.gain_ctrl = True cam.aec2 = True # AEC DSP for better auto-exposure cam.ae_level = 0 # exposure compensation –2 to +2 cam.gainceiling = GainCeiling.X4 # max auto-gain: X2/X4/X8/X16/X32/X64/X128 img_auto = cam.capture() print("Auto exposure frame:", len(img_auto)) # Manual exposure + gain cam.exposure_ctrl = False cam.gain_ctrl = False cam.aec_value = 300 # manual shutter speed (sensor-specific range) cam.agc_gain = 5 # manual gain value img_manual = cam.capture() print("Manual exposure frame:", len(img_manual)) ``` -------------------------------- ### Camera.reconfigure() Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Changes camera parameters like pixel format, frame size, grab mode, or frame buffer count at runtime without object re-creation. ```APIDOC ## Camera.reconfigure() ### Description Reconfigures the camera driver with new imaging parameters such as pixel format, frame size, grab mode, or frame buffer count. This can be done at runtime without destroying and recreating the `Camera` object. Any parameter not explicitly provided will retain its current value. Note that calling `reconfigure()` resets all previous sensor register settings (e.g., brightness, contrast). ### Method `reconfigure(pixel_format=None, frame_size=None, grab_mode=None, fb_count=None)` ### Parameters #### Optional Parameters - **pixel_format** (PixelFormat) - The new pixel format for the camera. - **frame_size** (FrameSize) - The new frame size for the camera. - **grab_mode** (GrabMode) - The new grab mode for the camera. - **fb_count** (int) - The new number of frame buffers to use. ### Request Example ```python from camera import Camera, FrameSize, PixelFormat, GrabMode cam = Camera(pixel_format=PixelFormat.JPEG, frame_size=FrameSize.QQVGA) # Switch to VGA JPEG with double-buffering cam.reconfigure( pixel_format=PixelFormat.JPEG, frame_size=FrameSize.VGA, grab_mode=GrabMode.LATEST, fb_count=2, ) print("New size:", cam.pixel_width, "x", cam.pixel_height) # 640 x 480 # Reconfigure to raw RGB565 for image processing cam.reconfigure(pixel_format=PixelFormat.RGB565, frame_size=FrameSize.QVGA) print("Format:", cam.pixel_format) # 0 (PixelFormat.RGB565) cam.deinit() ``` ### Response This method does not return a value. Configuration changes are applied directly to the camera driver. ``` -------------------------------- ### Share I2C Bus with Other Peripherals Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Allows sharing the camera's I2C control bus with other peripherals by passing an existing `machine.I2C` object to the `Camera` constructor. The `sda_pin` and `scl_pin` parameters are ignored when an I2C object is provided. SoftI2C is not supported. ```python import machine from camera import Camera, FrameSize, PixelFormat # Create a hardware I2C bus shared between camera and another sensor i2c = machine.I2C(0, scl=machine.Pin(39), sda=machine.Pin(40), freq=400_000) # Find all devices on the bus before camera init devices = i2c.scan() print("I2C devices before camera init:", [hex(d) for d in devices]) # Pass the I2C bus to the camera — no sda_pin/scl_pin needed cam = Camera( i2c=i2c, data_pins=[15, 17, 18, 16, 14, 12, 11, 48], vsync_pin=38, href_pin=47, pclk_pin=13, xclk_pin=10, frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG, ) # Camera and other devices share the same bus devices_after = i2c.scan() print("I2C devices after camera init:", [hex(d) for d in devices_after]) # Write to another device on the shared bus while camera is running i2c.writeto(0x68, b'\x6B\x00') # e.g. wake MPU-6050 img = cam.capture() print("Captured:", len(img), "bytes") cam.deinit() ``` -------------------------------- ### Camera Creates Its Own I2C (Default) Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Configure the camera to create and manage its own I2C bus internally. Note that in this mode, the I2C bus cannot be shared with other devices. ```python # Camera creates and manages its own I2C internally cam = camera.Camera(sda_pin=21, scl_pin=22, ...) # In this mode, you cannot share I2C with other devices # Use the first method if you need to share I2C ``` -------------------------------- ### Query esp32-camera Driver Version Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Retrieves a string identifying the version of the underlying `esp32-camera` driver linked into the firmware. This can be useful for debugging or compatibility checks. ```python import camera ver = camera.Version() print("Driver version:", ver) # e.g. "2.0.13-14b2be7" ``` -------------------------------- ### Adjust Image Quality Properties (Brightness, Contrast, Saturation) Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Read and write integer properties to control the sensor's image processing pipeline. Setting these properties sends commands over the I2C/SCCB bus. ```python from camera import Camera, FrameSize, PixelFormat with Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG) as cam: # Read current values print("brightness:", cam.brightness) # e.g. 0 print("contrast: ", cam.contrast) print("saturation:", cam.saturation) # Adjust for a dark scene cam.brightness = 2 # –2 (dark) to +2 (bright) cam.contrast = 1 cam.saturation = -1 # desaturate slightly cam.sharpness = 2 cam.denoise = 1 img = cam.capture() with open("adjusted.jpg", "wb") as f: f.write(img) ``` -------------------------------- ### Available Pixel Formats Enum Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Lists the available output pixel formats for the camera, represented by the `PixelFormat` enum. Each format has an associated integer value and a description of its properties (e.g., bytes per pixel, compression). ```python from camera import PixelFormat # Available constants: # PixelFormat.RGB565 = 0 (2 bytes/pixel, standard colour) # PixelFormat.YUV422 = 1 (2 bytes/pixel, chroma-subsampled) # PixelFormat.YUV420 = 2 # PixelFormat.GRAYSCALE = 3 (1 byte/pixel) # PixelFormat.JPEG = 4 (variable length, compressed) # PixelFormat.RGB888 = 5 (3 bytes/pixel, not supported on OV2640) # PixelFormat.RAW = 6 # PixelFormat.RGB444 = 7 # PixelFormat.RGB555 = 8 print(PixelFormat.JPEG) # 4 print(PixelFormat.RGB565) # 0 print(PixelFormat.GRAYSCALE) # 3 ``` -------------------------------- ### Control White Balance Properties Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Manage automatic white balance and white balance modes (Auto, Sunny, Cloudy, Office, Home). ```python from camera import Camera, FrameSize, PixelFormat with Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG) as cam: cam.whitebal = True # enable auto white balance cam.awb_gain = True # enable AWB gain adjustment cam.wb_mode = 0 # 0=Auto, 1=Sunny, 2=Cloudy, 3=Office, 4=Home img = cam.capture() print("White-balanced frame:", len(img)) # Force indoor (office) white balance cam.wb_mode = 3 img_office = cam.capture() print("Office WB frame:", len(img_office)) ``` -------------------------------- ### White balance properties Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Configures white balance settings, including automatic white balance control and different white balance modes. ```APIDOC ## White balance properties ### Description Control the sensor's automatic white balance and white balance mode (auto, sunny, cloudy, office, home). ### Properties - `whitebal` (bool): Enable/disable automatic white balance. - `awb_gain` (bool): Enable/disable AWB gain adjustment. - `wb_mode` (int): White balance mode. 0=Auto, 1=Sunny, 2=Cloudy, 3=Office, 4=Home. ### Example ```python from camera import Camera, FrameSize, PixelFormat with Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG) as cam: cam.whitebal = True # enable auto white balance cam.awb_gain = True # enable AWB gain adjustment cam.wb_mode = 0 # 0=Auto, 1=Sunny, 2=Cloudy, 3=Office, 4=Home img = cam.capture() print("White-balanced frame:", len(img)) # Force indoor (office) white balance cam.wb_mode = 3 img_office = cam.capture() print("Office WB frame:", len(img_office)) ``` ``` -------------------------------- ### Camera Reconfiguration Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Reconfigures the camera's settings after initialization. Allows changing parameters like frame size, pixel format, grab mode, and frame buffer count. ```APIDOC ## Camera Reconfiguration ### Description Reconfigures the camera with new settings. Only the specified parameters will be updated. ### Method `cam.reconfigure()` ### Parameters #### Keyword Arguments - **frame_size** (FrameSize) - Optional - The desired frame size. - **pixel_format** (PixelFormat) - Optional - The desired pixel format. - **grab_mode** (GrabMode) - Optional - The desired grab mode. - **fb_count** (int) - Optional - The desired frame buffer count. ### Request Example ```python cam.reconfigure(pixel_format=PixelFormat.JPEG, frame_size=FrameSize.QVGA, grab_mode=GrabMode.LATEST, fb_count=2) ``` ``` -------------------------------- ### Apply Pixel Correction Properties Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Fine-tune sensor output quality with bad-pixel correction, white-pixel correction, gamma correction, lens correction, and downsize enable. ```python from camera import Camera, FrameSize, PixelFormat with Camera(frame_size=FrameSize.VGA, pixel_format=PixelFormat.JPEG) as cam: cam.bpc = True # Bad Pixel Correction — fix stuck pixels cam.wpc = True # White Pixel Correction cam.raw_gma = True # Gamma correction for natural-looking images cam.lenc = True # Lens shading correction (even brightness edge-to-edge) cam.dcw = True # Downsize EN print("bpc:", cam.bpc, "wpc:", cam.wpc, "lenc:", cam.lenc) img = cam.capture() with open("corrected.jpg", "wb") as f: f.write(img) ``` -------------------------------- ### Share I2C Bus with Camera Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Create a custom I2C object and pass it to the camera to share the I2C bus with other devices. This allows communication with other I2C devices on the same bus while the camera is operational. ```python import machine # Create your own I2C object first i2c = machine.I2C(0, scl=22, sda=21, freq=400000) # Pass it to the camera (no need for sda_pin/scl_pin) cam = camera.Camera(i2c=i2c, data_pins=..., pclk_pin=..., ...) # The same I2C object can be used for other devices on the same bus! devices = i2c.scan() print(f"I2C devices found: {devices}") # You can communicate with other I2C devices while camera is running i2c.writeto(0x42, b'\x00\x01') # Write to another device # Camera sensor communication works too cam.saturation = 1 # Uses the shared I2C bus ``` -------------------------------- ### GrabMode Enum - Frame Buffer Grab Strategy Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Configure the frame buffer grab strategy using the GrabMode enum. WHEN_EMPTY is suitable for lower CPU load, while LATEST provides the lowest latency. ```python from camera import GrabMode # GrabMode.WHEN_EMPTY = 0 # Fill frame buffer only when empty; may return slightly older frames. # Lower CPU load; recommended for ESP32 (non-S series). # # GrabMode.LATEST = 1 # Always overwrite with the most recent frame; lowest latency. # Higher CPU load; recommended for ESP32-S3 with fb_count=2. print(GrabMode.WHEN_EMPTY) # 0 print(GrabMode.LATEST) # 1 ``` -------------------------------- ### Reconfigure Camera Settings Source: https://github.com/cnadler86/micropython-camera-api/blob/master/README.md Modify camera settings such as pixel format, frame size, grab mode, and frame buffer count after initialization using the reconfigure() method. ```python cam.reconfigure(pixel_format=PixelFormat.JPEG,frame_size=FrameSize.QVGA,grab_mode=GrabMode.LATEST, fb_count=2) ``` -------------------------------- ### Camera.frame_available() Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Checks if a new frame is ready for retrieval without blocking. Useful for manual polling in cooperative multitasking environments. ```APIDOC ## Camera.frame_available() ### Description Polls for frame readiness without blocking the execution. Returns `True` when a new frame is available to be retrieved using `capture()`. This method is useful for implementing manual asynchronous-style polling in simple cooperative multitasking loops. ### Method `frame_available()` ### Request Example ```python from camera import Camera, FrameSize, PixelFormat import time cam = Camera(frame_size=FrameSize.QVGA, pixel_format=PixelFormat.JPEG) img = bytes(cam.capture()) cam.free_buffer() # tell driver to grab the next frame # Do other work while waiting deadline = time.ticks_ms() + 2000 while not cam.frame_available(): if time.ticks_ms() > deadline: print("Timeout waiting for frame") break # perform other tasks here if cam.frame_available(): img = bytes(cam.capture()) print("Got frame:", len(img), "bytes") cam.deinit() ``` ### Response Returns `True` if a new frame is available, `False` otherwise. ``` -------------------------------- ### Register IDF Component Source: https://github.com/cnadler86/micropython-camera-api/blob/master/CMakeLists.txt Registers the current directory as an IDF component and specifies its dependencies. Use this to make the component discoverable by the IDF component manager. ```cmake idf_component_register( REQUIRES esp32-camera ) ``` -------------------------------- ### Update Camera Setting via Fetch API Source: https://github.com/cnadler86/micropython-camera-api/blob/master/examples/CameraSettings.html Updates a specific camera setting by sending a request to the server. Use this for real-time adjustments. ```javascript function updateValue(method, value) { console.log(`Updating ${method} to ${value}`); fetch(`/set_${method}?value=${value}`) .then(response => { if (!response.ok) { console.error(`Error setting ${method}`); } }) .catch(error => { console.error(`Fetch error: `, error); }); } ``` -------------------------------- ### Camera.capture() Source: https://context7.com/cnadler86/micropython-camera-api/llms.txt Captures a single video frame as a memoryview. Supports optional output pixel format conversion for JPEG cameras. ```APIDOC ## Camera.capture() ### Description Capture a single frame and return it as a `memoryview`. Each call provides a new frame. The buffer is managed by the driver. Optionally, an output pixel format can be specified for on-the-fly conversion when the camera is in JPEG mode. ### Method `capture(output_pixel_format=None)` ### Parameters #### Optional Parameters - **output_pixel_format** (PixelFormat) - The desired pixel format for the output frame. If specified, the camera will convert the captured frame to this format if it's in JPEG mode. ### Request Example ```python from camera import Camera, FrameSize, PixelFormat with Camera(frame_size=FrameSize.QVGA, pixel_format=PixelFormat.JPEG, fb_count=2) as cam: # Basic capture frame = cam.capture() print("Frame size (bytes):", len(frame)) # Copy to bytes and release driver buffer img_bytes = bytes(cam.capture()) cam.free_buffer() # On-the-fly format conversion gray = cam.capture(PixelFormat.GRAYSCALE) print("Grayscale frame:", len(gray), "bytes") ``` ### Response Returns a `memoryview` object representing the captured frame. ```