引言
ESP32-CAM以极低成本(<50元)集成了OV2640摄像头、Wi-Fi和MicroSD卡槽,成为DIY延时摄影(Time-Lapse)、监控和视觉项目的首选。
但实际使用中,SD卡挂载失败、Brownout重启、功耗过高、照片覆盖等问题极易卡住新手。本文一次性给你完整可落地方案:优化硬件电源、现代化代码(Deep Sleep版)、全避坑清单,让你从零到可量产级延时摄影系统。
1. 项目概述与硬件准备
核心目标:每隔固定时间(或Deep Sleep唤醒)自动拍照,照片以pic_0001.jpg递增命名,保存至SD卡。
1.1 物料清单
- 开发板:AI-Thinker ESP32-CAM(推荐带PSRAM版本)
- 存储:MicroSD卡 ≤16GB,必须FAT32 + MBR分区
- 下载器:USB转TTL(CH340/FT232)
- 电源:5V≥1A稳压源(拍照瞬间峰值可达400mA)
- 辅助:100~470μF 低ESR电容(并联在5V-GND)
1.2 烧录模式接线表
| ESP32-CAM引脚 | USB转TTL | 备注 |
|---|---|---|
| 5V | 5V | 推荐5V供电 |
| GND | GND | 共地 |
| U0R (GPIO3) | TXD | 接收 |
| U0T (GPIO1) | RXD | 发送 |
| GPIO0 | GND | 必须短接进入下载模式 |
烧录完成后务必拔掉GPIO0跳线,否则SD卡无法正常挂载。
2. 软件环境与核心代码实现
推荐开发环境:Arduino IDE 2.x + esp32 by Espressif 3.x 板卡包。
完整优化代码(推荐Deep Sleep低功耗版)
#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 <Preferences.h> // 推荐替代EEPROM,更稳定
Preferences prefs;
#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
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // 关闭Brownout检测
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.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\n", err);
return;
}
// SD卡初始化(1-bit模式节省功耗和引脚)
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("SD Card Mount Failed");
return;
}
takePicture(); // 首次拍照
goToDeepSleep(); // 进入低功耗睡眠
}
void takePicture() {
camera_fb_t * fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
prefs.begin("photo", false);
int pictureNumber = prefs.getInt("picNum", 0) + 1;
prefs.putInt("picNum", pictureNumber);
prefs.end();
String path = "/pic_" + String(pictureNumber) + ".jpg";
File file = SD_MMC.open(path.c_str(), FILE_WRITE);
if (file) {
file.write(fb->buf, fb->len);
Serial.printf("Picture saved: %s (%d bytes)\n", path.c_str(), fb->len);
file.close();
}
esp_camera_fb_return(fb);
}
void goToDeepSleep() {
Serial.println("Going to deep sleep for 10 seconds...");
esp_sleep_enable_timer_wakeup(10 * 1000000ULL); // 10秒唤醒
esp_deep_sleep_start();
}
void loop() {} // Deep Sleep模式下loop不会执行
3. 电源与硬件优化建议
- 必须加100~470μF低ESR电容 并联在5V-GND,彻底解决Brownout重启。
- 推荐5V 2A电源,避免使用手机充电器(纹波大)。
- 野外供电:建议搭配TP4056锂电 + 太阳能板 + 1000μF电容。
4. 项目CheckList(上手必查)
- SD卡已格式化为FAT32 + MBR?
- GPIO0跳线在烧录后已拔掉?
- 电源端并联了大电容?
- 代码中
psramFound()判断是否正确? - Deep Sleep唤醒时间是否已按需求调整?
- 照片编号是否使用Preferences持久化?
5. 常见避坑指南
- SD卡挂载失败:必须用SD Formatter工具格式化;1-bit模式下GPIO0必须悬空。
- Brownout重启:不加电容或未关闭检测,拍照瞬间必重启。
- 照片覆盖:千万不要用
millis()或简单变量,必须用Preferences/RTC内存持久化。 - 功耗过高:用
delay()会导致电池几小时就耗尽,必须改Deep Sleep(平均功耗可降至<15mA)。 - 画质差:UXGA模式下必须有PSRAM,否则强制降SVGA。
6. 后续进阶方向
- NTP时间戳命名:照片带日期时间(
pic_20260224_143022.jpg)。 - Wi-Fi实时预览:集成CameraWebServer异步服务器。
- PIR/光敏触发:GPIO13接人体红外,仅在需要时唤醒拍照。
- OTA升级:方便野外远程更新固件。
- 升级ESP32-S3-CAM:更高分辨率 + 更大PSRAM(2026推荐)。
7. 总结
ESP32-CAM是性价比最高的摄像头方案之一。掌握电源大电容 + Deep Sleep + Preferences持久化三大核心,就能轻松做出稳定可靠的延时摄影系统。
“先加电容保稳定,再用Deep Sleep省电量,最后用Preferences保数据”是这个项目成功的铁律。
多实测、多留余量,你就能从玩具级快速升级到可商用级产品。