clear_single_demo
ESP32-S3 + OV5640 单摄低功耗拍照上传固件。
当前固件面向一台定时唤醒工作的野外/低功耗相机设备:设备唤醒后通过 4G 联网,完成 SNTP 校时、拍照、TF 卡本地保存、HTTP 表单上传,然后根据服务器返回的绝对唤醒时间或本地容错策略进入 Deep Sleep。
当前主要能力
- 4G CAT1 模块联网、SIM/信号/注册/PPP 状态日志。
- 每次联网后 SNTP 重新校时,避免 RTC 漂移造成唤醒时间持续偏移。
- OV5640 QSXGA JPEG 拍照,默认分辨率 2560x1920。
- TF 卡保存图片,文件名格式为
YYYYMMDD-HHMMSS.jpg。 - HTTP
multipart/form-data上传图片和设备状态。 - Config Web 本地配置页,支持断电记忆。
- 固件版本号在代码顶部明文维护,并显示到 Web 页面、上传到服务端。
- OV5640 鱼眼镜头曝光优化,可在 Web 中开启/关闭,默认开启。
- 连续上传失败时自动低功耗退避,减少服务器故障时的电量消耗。
当前工程结构
.
├── CMakeLists.txt
├── README.md
├── partitions.csv
├── sdkconfig
├── version.txt
├── components/
├── main/
│ ├── CMakeLists.txt
│ ├── SingleCam.c
│ ├── SingleCam.h
│ ├── gy_gpio.c
│ ├── gy_gpio.h
│ ├── idf_component.yml
│ ├── Kconfig.projbuild
│ └── main.c
└── managed_components/
当前主业务都在 main/SingleCam.c 中。历史 Demo、旧 WiFi 文件、旧休眠拍照文件、旧 Makefile 和测试样例已经清理,不再参与构建。
固件版本
固件版本在 main/SingleCam.c 靠前位置明文定义:
static const char g_single_cam_firmware_version[] = "260402-1423";
约定:
- 该变量由人工维护。
- Codex 不主动修改该变量。
- Config Web 页面会显示该版本。
- 上传服务器表单中会携带
firmware_version字段。
正常运行流程
- 上电或 Deep Sleep 唤醒。
- 初始化 NVS、网络接口和事件循环。
- 读取 NVS 中保存的配置。
- 检查配置按键。
- 如果按下配置键,进入本地 AP + Web 配置模式。
- 如果未按下配置键,进入正常拍照上传模式。
- 4G 初始化并建立 PPP 网络。
- 查询信号、电压、基站定位。
- SNTP 校时。
- 初始化 OV5640 摄像头。
- 根据 Web 配置决定是否写入鱼眼曝光优化寄存器。
- 可选自动对焦。
- 等待自动曝光稳定并丢弃前 3 帧。
- 捕获 JPEG。
- 尝试保存到 TF 卡。
- 上传图片和状态字段到服务器。
- 如果服务器返回有效
next_wakeup_ts,按服务器绝对时间睡眠。 - 如果上传失败,按本地错误退避策略睡眠。
Config Web
按住配置键启动设备后,设备会开启本地 AP 和配置网页。
默认入口:
http://192.168.4.1/
当前支持配置:
- Server URL
- Network Mode
- Sleep OK
- Sleep Error
- Enable GPS
- Enable Auto Focus
- 鱼眼曝光优化
- Reboot Device
配置保存到 NVS,断电后仍保留。
HTTP 上传字段
设备使用 multipart/form-data 上传。
当前主要字段:
imageimeimodem_sniccidimsiesp32_snfirmware_versioncapture_timevbatrssirssi_dbmbs_latitudebs_longitudegnss_latitudegnss_longitudesd_free_mbnetwork_moderequest_id
服务器成功响应建议包含:
{
"code": 0,
"message": "ok",
"server_time_ts": 1775104062,
"next_wakeup_ts": 1775104200,
"trace_id": "example"
}
其中 next_wakeup_ts 是 Unix 秒级绝对时间戳,不是睡眠秒数。设备会用:
sleep_seconds = next_wakeup_ts - 当前本地时间
低功耗失败退避
如果服务器临时关闭或上传失败,设备不会一直高频重试。
当前策略:
- 第一次失败:按 Web 中配置的
Sleep Error睡眠。 - 连续失败:按
1x、2x、4x、8x...自动增加睡眠时间。 - 最大封顶:
1440分钟,即 24 小时。 - 一旦上传成功:连续失败计数清零。
例如 Sleep Error = 3 分钟:
第 1 次失败:3 分钟
第 2 次失败:6 分钟
第 3 次失败:12 分钟
第 4 次失败:24 分钟
第 5 次失败:48 分钟
...
最高:1440 分钟
连续失败计数保存在 RTC 内存中,Deep Sleep 唤醒后仍有效;如果设备完全断电,计数会清零。
鱼眼曝光优化
设备使用鱼眼镜头时,画面四周存在黑边。默认 OV5640 自动曝光可能把黑边也纳入统计,导致圆内植物区域过曝或曝光不稳定。
当前 Web 中的“鱼眼曝光优化”默认开启。开启时会写入 OV5640 AEC/AGC 测光窗口寄存器:
- ROI 聚焦在 2560x1920 图像中心圆形有效区域。
- 角落权重为 0,减少黑边影响。
- 中心权重较高,兼顾植物随时间变化的自然场景。
关闭该选项时,不写入这些寄存器,保持传感器默认自动曝光行为。
构建
已验证环境:
ESP-IDF: 4.4.7
Target: esp32s3
常规 ESP-IDF 环境中:
idf.py build
本机已验证命令:
$env:IDF_PATH='D:\idf_audio_camera\esp-idf'
$env:IDF_TOOLS_PATH='D:\idf_audio_camera\tools'
$env:PATH='D:\idf_audio_camera\tools\cmake\3.23.1\bin;D:\idf_audio_camera\tools\ninja\1.10.2;' + $env:PATH
& 'D:\idf_audio_camera\python_env\idf4.4_py3.8_env\Scripts\python.exe' 'D:\idf_audio_camera\esp-idf\tools\idf.py' build
烧录
常规方式:
idf.py -p COM3 flash
或使用构建完成后 ESP-IDF 输出的 esptool.py write_flash 命令。
发布版本中会附带可直接烧录的固件文件,包括:
bootloader.binpartition-table.binota_data_initial.binaudioCamera.binflash_args.txt
常见日志
时间同步:
time sync start
time sync done
服务器调度:
server schedule parsed
using server schedule
失败低功耗退避:
cycle failed, low-power retry backoff
TF 卡:
TF card mounted
photo saved to TF
上传失败:
upload failed
Connection reset by peer
服务端对接说明
服务端应按普通 HTTP 表单文件上传接口处理 multipart/form-data。
关键要求:
- 接收字段
firmware_version,用于区分设备固件版本。 - 接收字段
request_id,用于排查单次请求。 - 返回
server_time_ts,便于对比设备本地时间。 - 返回
next_wakeup_ts,设备会按该绝对时间进入 Deep Sleep。 - 如果服务端维护或临时不可用,设备会自动进入失败退避,不会持续高频请求。