ESP32‑CAM 应用详解

单片机/PLC wes 15 hours ago (2026-07-30) 31 views
📑 本文导航

一、基础简介

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 短板:
  1. 内存很小,图像占用内存大,不能做高分辨率实时图像处理;
  2. 没有板载下载电路!烧录代码必须外接 USB 转 TTL
  3. 没有板载按键,没有板载 LED(除摄像头闪光灯);
  4. 散热差,长时间高负载容易过热降速。

二、常用型号、摄像头传感器

1、模块主板型号

最常见两种:
  1. ESP32‑CAM‑MB(最经典,AI‑Thinker 原厂) 市面上 95% 买到的就是这一款,板载 SD 卡槽;排针没有焊接,到手自己焊排针。
⚠️没有 CH340 下载芯片,不能直接 USB 下载!
  1. 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,绝大多数项目够用,不要盲目追求高像素。分辨率越高内存占用越大,越容易死机。

板载硬件

  1. 8 个 LED 补光灯(白色闪光灯引脚 GPIO4,可以软件开关)
  2. MicroSD 卡槽:最大支持 32GB FAT32,保存照片视频
  3. DVP 摄像头接口(不是 MIPI
  4. 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
  1. TXD(USB‑TTL) → GPIO3(U0R)
  2. RXD(USB‑TTL) → GPIO1(U0T)
  3. GND ↔ GND(必须共地
  4. VIN → 5V(不要接 3.3V 供电,供电不足会重启)
  5. 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. 方案 1(推荐)ESP32‑CAM 输出 MJPG 视频流,电脑 OpenCV 处理图像,串口 / WiFi 下发坐标给 STM32。
优点:电脑算力强,可以跑完整 OpenCV 算法;缺点:必须要有电脑。
  1. 方案 2 ESP32 本地简单图像处理,串口发送坐标给 STM32;不推荐,延迟高、不稳定,容易死机。
✔️比赛选型建议
  • 需要小车板载视觉,无电脑,直接选 OpenMV4‑H7;
  • 可以带电脑,电脑做图像处理,选 ESP32‑CAM。

六、常见问题总结(高频问题)

  1. 供电不足:ESP32‑CAM 瞬时电流峰值 400mA,USB‑TTL 很多板子供电能力弱,表现反复重启。优先外部 5V 电源供电。
  2. GPIO12‑17 已经接摄像头,不能做普通 IO;自由 IO 极少。
  3. 烧录模式:GPIO0 上电拉低;运行时 GPIO0 必须断开。
  4. PSRAM 没有开启,高分辨率直接死机,Arduino 工具选项打开 PSRAM。
  5. 电平 3.3V,不要把 5V 信号接到 IO 口,直接烧毁模块。
  6. OV2640 镜头焦距出厂没有调好!到手旋转镜头调节清晰度,旋转镜头调好之后胶水固定。镜头模糊一切算法都白搭
  7. SD 卡必须格式化为 FAT32,簇大小 4096 字节,大于 32GB 不支持。
  8. 内存有限,不要使用太高分辨率,优先 QVGA (320×240) 做开发。
  9. 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 即可查看实时视频流。