🛠 Caméra OV2640 : capture et serveur MJPEG
Objectives
Use the ESP32-S3 DVP camera interface with an OV2640 module (2 MP, 8-bit parallel interface) to capture JPEG images and stream them as MJPEG to a browser via Wi-Fi. This capability made the S3 the reference chip for "smart displays" and next-generation ESP32-CAM projects. You will learn to choose the right variant (the camera bus occupies many pins, hence the interest in boards with an integrated camera connector or PSRAM for high resolutions).
Hardware
- 1 ESP32-S3 board with camera connector (DevKitC-1 with extension, XIAO ESP32S3 Sense, or ESP32-S3-CAM type module)
- 1 OV2640 camera module (DCW or standard)
- Preferably a variant with PSRAM (N8R8/N16R8) for JPEG at SVGA/XGA
- A 2.4 GHz Wi-Fi network
Complete code
// Serveur MJPEG minimal — exemple pour XIAO ESP32S3 Sense (broches ESP32S3_CAM_XIAO)
#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 10
#define SIOD_GPIO_NUM 40
#define SIOC_GPIO_NUM 39
#define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 11
#define Y7_GPIO_NUM 12
#define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 16
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 17
#define Y2_GPIO_NUM 15
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 47
#define PCLK_GPIO_NUM 13
const char* WIFI_SSID = "votre-ssid";
const char* WIFI_PASS = "votre-mot-de-passe";
WebServer server(80);
void handleStream {
static const char* part =
"--frame\r\nContent-Type: image/jpeg\r\n\r\n";
camera_fb_t* fb;
do {
fb = esp_camera_fb_get;
if (!fb) { server.send(500, "text/plain", "capture KO"); return; }
server.setContentLength(strlen(part) + fb->len + 2, true);
server.sendContent(part);
server.sendContent_P((const char*)fb->buf, fb->len);
server.sendContent("\r\n", 2);
esp_camera_fb_return(fb);
} while (!server.client.available);
}
void setup {
Serial.begin(115200);
camera_config_t cfg = {};
cfg.ledc_channel = LEDC_CHANNEL_0;
cfg.ledc_timer = LEDC_TIMER_0;
cfg.pin_d0 = Y2_GPIO_NUM; cfg.pin_d1 = Y3_GPIO_NUM;
cfg.pin_d2 = Y4_GPIO_NUM; cfg.pin_d3 = Y5_GPIO_NUM;
cfg.pin_d4 = Y6_GPIO_NUM; cfg.pin_d5 = Y7_GPIO_NUM;
cfg.pin_d6 = Y8_GPIO_NUM; cfg.pin_d7 = Y9_GPIO_NUM;
cfg.pin_xclk = XCLK_GPIO_NUM; cfg.pin_pclk = PCLK_GPIO_NUM;
cfg.pin_vsync = VSYNC_GPIO_NUM; cfg.pin_href = HREF_GPIO_NUM;
cfg.pin_sccb_sda = SIOD_GPIO_NUM; cfg.pin_sccb_scl = SIOC_GPIO_NUM;
cfg.pin_pwdn = PWDN_GPIO_NUM; cfg.pin_reset = RESET_GPIO_NUM;
cfg.xclk_freq_hz = 20000000;
cfg.pixel_format = PIXFORMAT_JPEG;
cfg.frame_size = FRAMESIZE_VGA;
cfg.jpeg_quality = 12;
cfg.fb_count = 1;
if (esp_camera_init(&cfg) != ESP_OK) {
Serial.println("Camera KO — verifier brochage/PSRAM"); while (true) delay(999);
}
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status != WL_CONNECTED) { delay(300); Serial.print("."); }
Serial.print("Flux : http://"); Serial.println(WiFi.localIP);
server.on("/stream", handleStream);
server.begin;
}
void loop { server.handleClient; delay(2); }
Expected verification
After Wi-Fi connection, the IP address is displayed on the console; opening http://IP/stream in a browser displays a continuously refreshed image stream (MJPEG). Quality and smoothness depend on the resolution (VGA = 640×480 is a good compromise without PSRAM) and JPEG quality (12 here, lower = better but heavier).
Common errors
- Missing PSRAM: without PSRAM (N8 variants without R), limit frame_size to QQVGA/QVGA and fb_count to 1; otherwise esp_camera_init fails or the image is corrupted.
- Incorrect pins: each board has its own camera pinout (XIAO, DevKitC, ESP32-S3-EYE differ); copy the pin table from the manufacturer's datasheet, do not guess.
- Beware of stolen pins: on N8R8/N16R8 modules, octal PSRAM occupies GPIO35/36 (and 37 depending on config) and the embedded WS2812 uses GPIO48; cross-check the schematics.
- 5 GHz Wi-Fi: the S3 only sees 2.4 GHz; connection failures often come from this.
- Weak power supply: camera + Wi-Fi + PSRAM peak consumption sometimes exceeds a tired USB port; flickering image = power properly.
Other tutorials for this board
Code examples for this board
clignotante.inoArduinobouton-led.inoArduinorespiration.inoArduinodht22.inoArduinooled-i2c.inoArduinoserveur-web.inoArduino