📑 本文导航
一、基础简介
ESP32‑CAM 是基于 ESP32‑S 芯片的低成本摄像头模块,集成 Wi‑Fi + Bluetooth,自带摄像头接口、MicroSD 卡卡槽;不需要外接主控,本身就可以拍照、视频流传输、图像采集。

核心芯片:ESP32‑S(双核 Tensilica‑LX6,240MHz,520KB SRAM) 工作电压:3.3V,注意!不能直接接 5V 给芯片 IO,摄像头 IO 是 3.3V 电平;模块可以 5V 供电(VIN 引脚)。 通信:Wi‑Fi 802.11 b/g/n,蓝牙 4.2 BLE。 用途:机器视觉原型、视频监控、WiFi 图传、二维码识别、颜色识别;算力远不如 OpenMV,不能本地跑复杂视觉算法。
和 OpenMV 对比
|
项目 |
ESP32‑CAM |
OpenMV4‑H7 R2 |
|
主控 |
ESP32‑S |
STM32H743 |
|
硬件 |
WiFi 蓝牙,SD 卡 |
无 WiFi,UART 串口输出 |
|
本地图像处理 |
只能简单像素处理;不适合复杂算法 |
内置优化视觉库 blobs、apriltag |
|
AI |
TinyML,模型很小,帧率低 |
FOMO,硬件无 NPU |
|
输出方式 |
WiFi 网页流,MQTT;可串口输出 |
UART 串口输出坐标给单片机 |
|
供电 |
5V VIN 供电 |
3.3‑5V |
ESP32‑CAM 短板:
- 内存很小,图像占用内存大,不能做高分辨率实时图像处理;
- 没有板载下载电路!烧录代码必须外接 USB 转 TTL;
- 没有板载按键,没有板载 LED(除摄像头闪光灯);
- 散热差,长时间高负载容易过热降速。
二、常用型号、摄像头传感器
1、模块主板型号
最常见两种:
- ESP32‑CAM‑MB(最经典,AI‑Thinker 原厂) 市面上 95% 买到的就是这一款,板载 SD 卡槽;排针没有焊接,到手自己焊排针。
⚠️没有 CH340 下载芯片,不能直接 USB 下载!
- ESP32‑CAM‑CH340(带底板) 底板集成 CH340 USB 转串口,直接插 USB 烧录程序,新手优先选。底板引出所有 IO。
2、摄像头传感器(OV 系列为主)
OV2640【最常用,标配】
- 像素:200W 像素
- 最大分辨率:UXGA (1600×1200);常用 QVGA (320×240)、VGA (640×480)
- 接口:DVP 并行接口
- 优势:成熟、资料最多;ESP32‑CAM 标配;适合视频流、拍照。
- 劣势:暗光效果一般,噪点多。
OV7670
30 万像素,画质差,现在很少用。
OV3660
300 万像素,画质更好,价格贵;ESP32 内存有限,高分辨率很容易内存溢出死机,一般选 VGA/QVGA。
✅实战建议:直接买 OV2640,绝大多数项目够用,不要盲目追求高像素。分辨率越高内存占用越大,越容易死机。
板载硬件
- 8 个 LED 补光灯(白色闪光灯引脚 GPIO4,可以软件开关)
- MicroSD 卡槽:最大支持 32GB FAT32,保存照片视频
- DVP 摄像头接口(不是 MIPI)
- IO 口:GPIO0、GPIO2、GPIO12‑GPIO17;GPIO0 是下载模式引脚。
三、引脚定义(AI‑Thinker ESP32‑CAM‑MB)
表格
| 引脚 | 功能 | 备注 |
|---|---|---|
| VIN | 5V 电源输入 | 模块供电 5V |
| GND | 地 | 必须共地 |
| 3.3V | 模块输出 3.3V,最大几百 mA | 不要用来外接大设备 |
| GPIO0 | DOWNLOAD 引脚 | 拉低进入烧录模式 |
| GPIO2 | LED 闪光灯 | 高电平点亮补光灯 |
| GPIO12‑GPIO17 | DVP 摄像头数据引脚,不要用作普通 IO | |
| GPIO14‑GPIO15 | SD 卡 SPI | 接 SD 卡槽 |
⚠️大坑:GPIO12~GPIO17 已经硬件连接摄像头,不要当做普通 IO 外接外设,会导致摄像头无法工作。 可用自由 IO 只有:GPIO0、GPIO2。GPIO2 接闪光灯。
烧录接线(ESP32‑CAM‑MB 裸模块,没有底板)
USB‑TTL(CH340) ↔ ESP32‑CAM
- TXD(USB‑TTL) → GPIO3(U0R)
- RXD(USB‑TTL) → GPIO1(U0T)
- GND ↔ GND(必须共地)
- VIN → 5V(不要接 3.3V 供电,供电不足会重启)
- GPIO0 ↔ GND,上电,进入烧录模式;烧录完成断开 GPIO0‑GND 复位运行。
烧录完成后,GPIO0 不要再一直接地,否则永远进入下载模式。
四、开发环境
1.Arduino‑ESP32(最常用,新手首选)
大量现成示例代码:WebServer 视频流、拍照 SD 卡、MQTT、人脸识别、颜色采集。
2.ESP‑IDF(乐鑫官方 SDK)
适合做产品,性能更高,上手难度高;电赛、比赛一般 Arduino 足够。
❗注意内存:ESP32 的 PSRAM(外部伪静态内存)必须打开,否则高分辨率直接内存崩溃。 Arduino 工具选项中:PSRAM → Enabled。
五、典型应用详解
应用 1:WiFi 网页视频流(电赛高频)
功能:ESP32‑CAM 启动 WiFi,开启网页服务器;电脑 / 手机浏览器访问 IP,实时查看摄像头画面。
- 常用分辨率 QVGA 320×240,帧率 10‑18fps;VGA (640×480) 帧率 5‑10fps。
- 局限:ESP32 本身算力弱,只负责采集图像,图像识别不能在 ESP32 本地做。
使用方案 A:电脑 OpenCV 读取网页 MJPG 流,电脑做图像处理,结果通过网络下发给小车主控。 使用方案 B:ESP32 截图,通过 WiFi 发送图片给 STM32;不推荐,延迟极高。
对比 OpenMV:OpenMV 直接 UART 输出坐标;ESP32‑CAM 本身不做识别,识别交给电脑。
应用 2:拍照 + SD 卡存储
触发条件可以是按键、定时器、网页请求;照片保存到 SD 卡。适合巡检抓拍。
应用 3:二维码 / 条形码识别
ESP32‑CAM + Arduino 库
ESP32QRCodeReader。限制:帧率低;镜头距离二维码需要合适,暗光识别很差。适合静态识别,高速运动识别几乎不可用。
应用 4:简单颜色识别(本地)
ESP32 可以读取图像像素 RGB 值,遍历像素统计色块;不支持 HSV Blobs 算法,没有 OpenMV 的优化库,速度很慢。QVGA 分辨率一帧遍历耗时几十‑上百 ms。
电赛不推荐 ESP32‑CAM 本地做颜色循迹,实时性差,容易死机;优先 OpenMV。
应用 5:TinyML 本地 AI 推理
支持训练好的模型(比如人脸检测、物体识别),模型必须很小。
- 速度很慢,QVGA 下 1‑3FPS;只能识别简单目标。
- 适合演示,比赛实时闭环项目慎用。
应用 6:远程监控,MQTT 上传图片
连接路由器,抓拍图片上传 MQTT 服务器,物联网项目。
应用 7:作为图像采集单元配合 STM32 小车(两种方案)
- 方案 1(推荐)ESP32‑CAM 输出 MJPG 视频流,电脑 OpenCV 处理图像,串口 / WiFi 下发坐标给 STM32。
优点:电脑算力强,可以跑完整 OpenCV 算法;缺点:必须要有电脑。
- 方案 2 ESP32 本地简单图像处理,串口发送坐标给 STM32;不推荐,延迟高、不稳定,容易死机。
✔️比赛选型建议
- 需要小车板载视觉,无电脑,直接选 OpenMV4‑H7;
- 可以带电脑,电脑做图像处理,选 ESP32‑CAM。
六、常见问题总结(高频问题)
- 供电不足:ESP32‑CAM 瞬时电流峰值 400mA,USB‑TTL 很多板子供电能力弱,表现反复重启。优先外部 5V 电源供电。
- GPIO12‑17 已经接摄像头,不能做普通 IO;自由 IO 极少。
- 烧录模式:GPIO0 上电拉低;运行时 GPIO0 必须断开。
- PSRAM 没有开启,高分辨率直接死机,Arduino 工具选项打开 PSRAM。
- 电平 3.3V,不要把 5V 信号接到 IO 口,直接烧毁模块。
- OV2640 镜头焦距出厂没有调好!到手旋转镜头调节清晰度,旋转镜头调好之后胶水固定。镜头模糊一切算法都白搭。
- SD 卡必须格式化为 FAT32,簇大小 4096 字节,大于 32GB 不支持。
- 内存有限,不要使用太高分辨率,优先 QVGA (320×240) 做开发。
- ESP32‑CAM 不适合高速闭环控制,图像采集 + 处理延迟很大。
七、Arduino 最小示例代码:WiFi 视频流(ESP32‑CAM‑MB + OV2640)
注意修改 wifi 账号密码
cpp
#include "esp_camera.h"
#include
//摄像头引脚定义 AI‑Thinker ESP32‑CAM‑MB
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
const char* ssid = "你的WiFi名称";
const char* password = "WiFi密码";
WiFiServer server(80);
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_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
//PSRAM开启用QVGA
if(psramFound()){
config.frame_size = FRAMESIZE_QVGA; //320*240
config.jpeg_quality = 12;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_QQVGA;
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 %d",err);
return;
}
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
server.begin();
}
void loop() {
WiFiClient client = server.accept();
if (client) {
String response = "HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
client.print(response);
while(client.connected()){
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) break;
client.print(String("--frame\r\nContent‑Type:image/jpeg\r\nContent‑Length:")+fb->len+"\r\n\r\n");
client.write(fb->buf, fb->len);
client.print("\r\n");
esp_camera_fb_return(fb);
}
client.stop();
}
}
下载运行,串口打印 IP 地址;浏览器打开
http://IP 即可查看实时视频流。