🛠 Caméra OV2640 : capture et serveur MJPEG
Objectifs
Utiliser l'interface caméra DVP de l'ESP32-S3 avec un module OV2640 (2 MP, interface parallèle 8 bits) pour capturer des images JPEG et les servir en flux MJPEG à un navigateur via Wi-Fi. C'est la capacité qui a fait du S3 la puce de référence des « smart displays » et des projets ESP32-CAM nouvelle génération. Vous apprendrez à choisir la bonne variante (le bus caméra occupe beaucoup de broches, d'où l'intérêt des cartes avec connecteur caméra intégré ou de PSRAM pour les grandes résolutions).
Matériel
- 1 carte ESP32-S3 avec connecteur caméra (DevKitC-1 avec extension, XIAO ESP32S3 Sense, ou module type ESP32-S3-CAM)
- 1 module caméra OV2640 (DCW ou standard)
- De préférence une variante avec PSRAM (N8R8/N16R8) pour le JPEG en SVGA/XGA
- Un réseau Wi-Fi 2,4 GHz
Code complet
// 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 — vérifier 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); }
Vérification attendue
Après connexion Wi-Fi, l'adresse IP s'affiche sur la console ; ouvrir http://IP/stream dans un navigateur affiche un flux d'images rafraîchi en continu (MJPEG). La qualité et la fluidité dépendent de la résolution (VGA = 640×480 est un bon compromis sans PSRAM) et de la qualité JPEG (12 ici, plus bas = mieux mais plus lourd).
Erreurs fréquentes
- PSRAM absente : sans PSRAM (variantes N8 sans R), limiter frame_size à QQVGA/QVGA et fb_count à 1 ; sinon esp_camera_init échoue ou l'image est corrompue.
- Broches incorrectes : chaque carte a son brochage caméra (XIAO, DevKitC, ESP32-S3-EYE diffèrent) ; copier la table de la fiche du fabricant, ne pas deviner.
- Attention aux broches volées : sur les modules N8R8/N16R8, le PSRAM octal occupe GPIO35/36 (et 37 selon config) et le WS2812 embarqué le GPIO48 ; croiser les schémas.
- Wi-Fi 5 GHz : le S3 ne voit que le 2,4 GHz ; un échec de connexion vient souvent de là.
- Alimentation faible : caméra + Wi-Fi + PSRAM en pointe dépassent parfois un port USB fatigué ; image qui saute = alimenter proprement.
Autres tutoriels pour cette carte
Exemples de code pour cette carte
clignotante.inoArduinobouton-led.inoArduinorespiration.inoArduinodht22.inoArduinooled-i2c.inoArduinoserveur-web.inoArduino