> ## Documentation Index
> Fetch the complete documentation index at: https://docs.protonverse.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Capturing Images with OV2640 and OV3660 on ESP32-S3

> Initialize the OV2640 or OV3660 camera on Proton AI Core and capture JPEG images using the esp32-camera library in Arduino or PlatformIO.

Proton AI Core supports both the OV2640 and OV3660 camera modules, making it straightforward to capture images and video frames at the edge. This guide walks you through installing the required library, configuring the camera driver, and capturing JPEG frames in your firmware.

## Prerequisites

* Camera module physically connected to Proton AI Core (see [Camera Hardware](/hardware/cameras))
* `esp32-camera` library installed (instructions below)
* Arduino IDE with the ESP32 board package, or a PlatformIO project configured for ESP32-S3

## Installing the Camera Library

<Tabs>
  <Tab title="Arduino IDE">
    The `esp32-camera` driver is bundled with Espressif's official **ESP32 Arduino board package**. If you have already installed the `esp32` board package via **Boards Manager**, no additional library installation is needed.

    To confirm, go to **Tools → Board → Boards Manager**, search for `esp32` by Espressif Systems, and ensure it is installed at version 2.x or later.
  </Tab>

  <Tab title="PlatformIO">
    Add the library to your `platformio.ini` file:

    ```ini theme={null}
    lib_deps =
        espressif/esp32-camera @ ^2.0.0
    ```

    Run `pio lib install` or let PlatformIO resolve dependencies automatically on the next build.
  </Tab>
</Tabs>

## Camera Configuration

The `esp32-camera` driver is configured through the `camera_config_t` struct before calling `esp_camera_init()`. You assign GPIO pin numbers, clock frequency, pixel format, and frame buffer settings here. The example below shows a full configuration for the OV2640 sensor.

```cpp camera_config.cpp theme={null}
#include "esp_camera.h"

// Camera pin definitions — verify with your board schematic
#define CAM_PIN_PWDN    -1  // Power down pin (To be confirmed)
#define CAM_PIN_RESET   -1  // Hardware reset (To be confirmed)
#define CAM_PIN_XCLK    15  // To be confirmed
#define CAM_PIN_SIOD    4   // I2C SDA (To be confirmed)
#define CAM_PIN_SIOC    5   // I2C SCL (To be confirmed)
#define CAM_PIN_D7      16  // To be confirmed
#define CAM_PIN_D6      17  // To be confirmed
#define CAM_PIN_D5      18  // To be confirmed
#define CAM_PIN_D4      12  // To be confirmed
#define CAM_PIN_D3      10  // To be confirmed
#define CAM_PIN_D2      8   // To be confirmed
#define CAM_PIN_D1      9   // To be confirmed
#define CAM_PIN_D0      11  // To be confirmed
#define CAM_PIN_VSYNC   6   // To be confirmed
#define CAM_PIN_HREF    7   // To be confirmed
#define CAM_PIN_PCLK    13  // To be confirmed

camera_config_t config;

esp_err_t initCamera() {
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer   = LEDC_TIMER_0;
  config.pin_d0       = CAM_PIN_D0;
  config.pin_d1       = CAM_PIN_D1;
  config.pin_d2       = CAM_PIN_D2;
  config.pin_d3       = CAM_PIN_D3;
  config.pin_d4       = CAM_PIN_D4;
  config.pin_d5       = CAM_PIN_D5;
  config.pin_d6       = CAM_PIN_D6;
  config.pin_d7       = CAM_PIN_D7;
  config.pin_xclk     = CAM_PIN_XCLK;
  config.pin_pclk     = CAM_PIN_PCLK;
  config.pin_vsync    = CAM_PIN_VSYNC;
  config.pin_href     = CAM_PIN_HREF;
  config.pin_sscb_sda = CAM_PIN_SIOD;
  config.pin_sscb_scl = CAM_PIN_SIOC;
  config.pin_pwdn     = CAM_PIN_PWDN;
  config.pin_reset    = CAM_PIN_RESET;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  config.frame_size   = FRAMESIZE_QVGA;  // 320x240
  config.jpeg_quality = 12;  // 0-63, lower = better quality
  config.fb_count     = 1;
  config.fb_location  = CAMERA_FB_IN_PSRAM;

  return esp_camera_init(&config);
}
```

<Warning>
  Pin definitions above are placeholders marked "To be confirmed". Check the official pinout diagram at [/hardware/pinout](/hardware/pinout) or the Downloads page before using in production.
</Warning>

## Capturing a Frame

Once the camera is initialised, call `esp_camera_fb_get()` to grab a frame buffer from the driver. Always return the buffer with `esp_camera_fb_return()` after you are done — failing to do so exhausts the frame buffer pool.

```cpp capture.cpp theme={null}
void captureAndPrint() {
  camera_fb_t *fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }
  Serial.printf("Captured image: %d bytes\n", fb->len);
  // Process fb->buf here...
  esp_camera_fb_return(fb);
}
```

## Frame Sizes

The `frame_size` field of `camera_config_t` controls the output resolution. The OV2640 supports resolutions up to 1600×1200; the OV3660 supports higher resolutions. Choose a frame size that balances image quality with your application's memory and processing requirements.

| Constant          | Resolution             |
| ----------------- | ---------------------- |
| `FRAMESIZE_QQVGA` | 160×120                |
| `FRAMESIZE_QVGA`  | 320×240                |
| `FRAMESIZE_VGA`   | 640×480                |
| `FRAMESIZE_SVGA`  | 800×600                |
| `FRAMESIZE_XGA`   | 1024×768               |
| `FRAMESIZE_UXGA`  | 1600×1200 (OV2640 max) |

<Tip>
  Use `FRAMESIZE_QVGA` for AI inference tasks — smaller frames mean faster processing and lower memory usage on the tensor arena.
</Tip>
