940 字
5 分钟
ESP32-CAM 实战:构建低成本定时延时摄影系统
一、 项目概述
ESP32-CAM 是一款基于 ESP32-S 芯片的紧凑型摄像头模块,集成 OV2640 摄像头与 MicroSD 卡槽。凭借其不到 50 元的成本,它成为了 DIY 监控、延时摄影(Time-lapse)及视觉追踪项目的首选方案。
本实验目标: 利用 ESP32-CAM 硬件定时器触发快门,将拍摄的图像以自动递增的编号命名,并存储至本地 SD 卡。
二、 硬件准备与接线说明
1. 核心清单
- 开发板:AI-Thinker ESP32-CAM
- 存储:MicroSD 卡(建议容量 16GB 及以下,必须格式化为 FAT32)
- 下载器:USB 转 TTL 模块(ESP32-CAM 通常不自带 USB 接口)
2. 烧录模式接线
由于 ESP32-CAM 没有集成的 USB 转串口芯片,烧录时需要按下表接线:
| ESP32-CAM | USB 转 TTL | 备注 |
|---|---|---|
| 5V / 3V3 | 5V / 3.3V | 建议使用 5V 以保证摄像头瞬时电流 |
| GND | GND | 必须共地 |
| U0R | TXD | 串口接收 |
| U0T | RXD | 串口发送 |
| GPIO 0 | GND | 进入烧录模式的关键:必须短接 |
三、 软件架构设计
本方案采用 esp_camera 驱动库。为了防止设备重启后文件名覆盖,我们利用 ESP32 的 RTC 慢速存储器(RTC_DATA_ATTR) 或 EEPROM 来保存图片序号。
核心代码实现
#include "esp_camera.h"#include "Arduino.h"#include "FS.h"#include "SD_MMC.h"#include "soc/soc.h" // 解决掉电检测问题#include "soc/rtc_cntl_reg.h" // 解决掉电检测问题#include <EEPROM.h> // 用于持久化照片编号
#define EEPROM_SIZE 1
// AI-Thinker ESP32-CAM 引脚定义#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
int pictureNumber = 0;
void setup() { WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // 关闭掉电检测,防止电压瞬降导致重启 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;
// 根据内存情况调整图片质量 if(psramFound()){ config.frame_size = FRAMESIZE_UXGA; // 1600x1200 config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; 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; }
// 初始化 SD 卡 (使用 1-线模式以节省功耗/引脚) if(!SD_MMC.begin("/sdcard", true)){ Serial.println("SD Card Mount Failed"); return; }}
void take_picture() { camera_fb_t * fb = esp_camera_fb_get(); if(!fb) { Serial.println("Capture failed"); return; }
// 读取并更新编号 EEPROM.begin(EEPROM_SIZE); pictureNumber = EEPROM.read(0) + 1;
String path = "/pic_" + String(pictureNumber) + ".jpg"; fs::FS &fs = SD_MMC; File file = fs.open(path.c_str(), FILE_WRITE);
if(!file){ Serial.println("Failed to open file in writing mode"); } else { file.write(fb->buf, fb->len); Serial.printf("Saved: %s\n", path.c_str()); EEPROM.write(0, pictureNumber); EEPROM.commit(); } file.close(); esp_camera_fb_return(fb);}
void loop() { take_picture(); delay(10000); // 每 10 秒拍摄一次}四、 常见问题与工程优化 (FAQ)
1. 为什么 SD 卡挂载失败?
- 格式问题:ESP32-CAM 对分区表很敏感,必须是 MBR 分区格式 的 FAT32。建议使用 SD Formatter 工具。
- 引脚冲突:SD 卡使用的是 HS2 信号线,烧录完成后请拔掉引脚 0 上的跳线,否则可能干扰数据传输。
2. Brownout detector 错误
- 现象:摄像头工作瞬间功耗很大(峰值达 300mA+),导致电压波动重启。
- 对策:在
5V和GND之间并联一个 100uF - 470uF 的电容,或在代码开头加入WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);。
五、 后续进阶建议
- Deep Sleep(深度睡眠):
对于野外拍摄,不建议在
loop()中使用delay()。应调用esp_deep_sleep_start(),让 ESP32 在拍照间隔进入睡眠状态(功耗降至 10mA 以下)。 - Web Server 预览: 利用集成的 Wi-Fi,可以开启一个异步 Web 服务器,实时流式传输摄像头画面。
- PIR 触发: 将 GPIO 13 连接到人体红外传感器,实现“有人经过才拍摄”,大幅节省存储空间。
ESP32-CAM 实战:构建低成本定时延时摄影系统
https://hw.rscclub.website/posts/esp32cam1sdtime/