Back to Sensors & Actuators Series

Camera Modules: OV7670 & OV2640

April 10, 2026 Wasil Zafar 10 min read

OV7670 & OV2640 deep dive — CMOS image sensing, SCCB registers, ESP32-CAM JPEG capture, and IoT surveillance applications.

Contents

  1. Working Principle
  2. Electrical Characteristics
  3. Interfacing with MCU
  4. Calibration
  5. Code Example
  6. Real-World Applications
  7. Limitations

Working Principle

The OV7670 (VGA 640×480) and OV2640 (2 MP 1600×1200) are CMOS image sensor modules from OmniVision. A grid of photodiodes (pixels) converts incoming light to electrical charge proportional to intensity. Each pixel has a colour filter (Bayer pattern: RGGB) and a row/column address circuit. The sensor outputs pixel data frame-by-frame over a parallel interface (OV7670) or via an integrated JPEG engine (OV2640).

Key difference: The OV7670 outputs raw pixel data requiring significant bus bandwidth, while the OV2640 can compress to JPEG internally, drastically reducing data transfer requirements.

Electrical Characteristics

ParameterOV7670OV2640
ResolutionVGA (640×480)2 MP (1600×1200)
Supply Voltage3.3 V2.5–3.0 V (core), 1.7–3.0 V (I/O)
Output FormatRaw Bayer, RGB565, YUV422Raw, RGB565, YUV422, JPEG
Interface8-bit parallel + SCCB (I2C-like)8-bit parallel / DVP + SCCB
Frame Rate30 fps (VGA)15 fps (UXGA), 30 fps (SVGA)
Control BusSCCB (≈ I2C, addr 0x21)SCCB (addr 0x30)
Current Draw~20 mA (active)~30 mA (active)
LensBuilt-in M12 lensBuilt-in lens (swappable)

Interfacing with an MCU

Camera modules require significant resources: 8 data lines (D0–D7), PCLK (pixel clock), VSYNC, HREF, XCLK (master clock input), SDA, SCL. The OV7670 needs an external 8–24 MHz clock (XCLK).

Not suitable for basic Arduino: The OV7670 requires ~300 KB RAM for a single VGA frame — far beyond Arduino Uno’s 2 KB. Use ESP32-CAM, STM32, or Raspberry Pi. The OV2640 is pre-integrated on the popular ESP32-CAM board.
ESP32-CAM: The most popular hobbyist camera platform uses an OV2640 with JPEG compression, Wi-Fi streaming, and micro-SD recording — all on a $5 board.

Calibration

  • White balance: Configure SCCB registers for AWB (auto white balance) or manual WB for consistent colour
  • Exposure: AEC (automatic exposure control) handles most scenarios; override with manual exposure for specific lighting
  • Focus: The OV7670 has a fixed-focus lens; the OV2640 may support auto-focus on some modules
  • XCLK frequency: Higher XCLK gives faster frame rates but may introduce noise; 12–20 MHz is typical

Code Example

/*
 * ESP32-CAM (OV2640) JPEG Capture — Arduino IDE
 * Board: AI Thinker ESP32-CAM
 * Captures a JPEG frame and prints size
 */
#include "esp_camera.h"

/* AI Thinker ESP32-CAM pin definitions */
#define PWDN_GPIO    32
#define RESET_GPIO   -1
#define XCLK_GPIO     0
#define SIOD_GPIO    26
#define SIOC_GPIO    27
#define Y9_GPIO      35
#define Y8_GPIO      34
#define Y7_GPIO      39
#define Y6_GPIO      36
#define Y5_GPIO      21
#define Y4_GPIO      19
#define Y3_GPIO      18
#define Y2_GPIO       5
#define VSYNC_GPIO   25
#define HREF_GPIO    23
#define PCLK_GPIO    22

void setup() {
    Serial.begin(115200);

    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer   = LEDC_TIMER_0;
    config.pin_d0       = Y2_GPIO;
    config.pin_d1       = Y3_GPIO;
    config.pin_d2       = Y4_GPIO;
    config.pin_d3       = Y5_GPIO;
    config.pin_d4       = Y6_GPIO;
    config.pin_d5       = Y7_GPIO;
    config.pin_d6       = Y8_GPIO;
    config.pin_d7       = Y9_GPIO;
    config.pin_xclk     = XCLK_GPIO;
    config.pin_pclk     = PCLK_GPIO;
    config.pin_vsync    = VSYNC_GPIO;
    config.pin_href     = HREF_GPIO;
    config.pin_sscb_sda = SIOD_GPIO;
    config.pin_sscb_scl = SIOC_GPIO;
    config.pin_pwdn     = PWDN_GPIO;
    config.pin_reset    = RESET_GPIO;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;
    config.frame_size   = FRAMESIZE_VGA;
    config.jpeg_quality = 12;
    config.fb_count     = 1;

    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
        Serial.printf("Camera init failed: 0x%x
", err);
        return;
    }
    Serial.println("ESP32-CAM (OV2640) Ready");
}

void loop() {
    camera_fb_t *fb = esp_camera_fb_get();
    if (fb) {
        Serial.printf("JPEG: %d bytes (%dx%d)
",
                       fb->len, fb->width, fb->height);
        esp_camera_fb_return(fb);
    }
    delay(2000);
}

Real-World Applications

IoT Surveillance, Machine Vision & Edge AI

The OV2640 on ESP32-CAM powers DIY security cameras, wildlife trail cameras, time-lapse rigs, and doorbell cameras with Wi-Fi streaming. In machine vision, it’s used for barcode/QR scanning, colour sorting, and TensorFlow Lite person detection. The OV7670 is popular in academic computer vision courses as a low-level camera interface exercise.

SurveillanceMachine VisionEdge AIESP32-CAM

Limitations

  • OV7670 resource demands: Needs 300+ KB RAM, fast GPIO, and DMA — not feasible on basic Arduino.
  • Low light performance: Small pixel pitch means poor sensitivity in dim conditions. No night vision without IR illuminator.
  • Fixed focus: Neither sensor has hardware autofocus; depth of field is fixed by the lens.
  • Parallel interface: Uses 8 GPIO pins for data alone; consumes most available pins on smaller MCUs.
  • SCCB register complexity: Register configuration for OV7670 is notoriously complex with undocumented registers.