文档库
六足图传实现与设备绑定
本章适合已经看到图传、准备修改代码的读者。范围是examples/nodehexa-video当前v1.1.0实现。它的职责是把摄像头作为可发现、可配置、可诊断的外设,而不是在串口上传输每个像素。
先读哪些文件
| 文件 | 职责 |
|---|---|
| main/board_pins.h | 本板固定GPIO |
| main/app_main.cpp | 启动、采集、UART调度、HTTP、档位与过流处理 |
| main/uart_protocol.h / .cpp | UART v2帧、CRC、增量解析 |
| main/wifi_binding.h / .cpp | 网络配置校验、NVS、Wi-Fi任务与流会话 |
| components/camera_orientation | GC2145方向位设置 |
| sdkconfig.defaults / partitions.csv | SDK基线与Flash布局 |
启动顺序与任务分工
启动时建立相机锁、串口发送锁、流客户端锁和档位队列;初始化GPIO、NVS、网络基础设施;以STA MAC形成cameraId;启动Wi-Fi管理与UART任务;初始化相机;启动HTTP及档位/过流任务。
| 执行单元 | 做什么 | 为什么分开 |
|---|---|---|
| UART任务 | 解析请求、HELLO、状态上报 | 不把耗时连接/采集放进串口接收路径 |
| Wi-Fi管理任务 | 保存与应用配置、连接、退避重试 | Wi-Fi事件回调只改变状态,避免重复调用连接API |
| 档位任务 | 取最新请求、重新初始化、失败回滚 | 控制回执不用等待整次切换完成 |
| HTTP流处理 | 获取帧、编码JPEG、发送multipart | 不占用UART来传图 |
| 过流任务 | 检查GPIO6,关闭相机电源并更新状态 | 网络与诊断仍可保留 |
档位队列和配网队列均采用覆盖方式保留最新请求,不承诺快速连发的每个中间配置都会执行。客户端应一次提交一个目标,并根据状态等待完成。
图像生命周期
GC2145 RGB565-BE
→ esp_camera_fb_get()
→ 在相机锁内frame2jpg(..., 80, ...)
→ esp_camera_fb_return()
→ 释放相机锁
→ 发送JPEG及multipart头
→ free(JPEG)
相机使用15 MHz XCLK、PSRAM帧缓冲、两帧缓冲、CAMERA_GRAB_WHEN_EMPTY。jpgSetRgb565BE(true)与传感器字节顺序对应。RGB565每像素两个字节,若把高低字节颠倒,颜色会异常。
固件先归还原始帧再发送网络数据,因此慢客户端不会占着原始摄像头缓冲等待发送。仍有JPEG分配和网络发送时间;不是无限并发或恒定帧率。流入口用客户端锁限制同时使用,忙时可能返回503。没有观看者时,framesOk不会像持续推理帧数一样增长:它是在成功发送JPEG后递增。
档位切换与方向
切换不是简单调用sensor.set_framesize。驱动缓冲与DMA复制路径在初始化时建立,因此先停用相机、重新初始化目标档位,再恢复方向。目标初始化失败时尝试恢复旧档位。
GC2145的水平镜像与垂直翻转位在同一寄存器,公共组件合并写入,避免分开读改写相互覆盖。新初始化与回滚后均恢复默认双翻转。修改此处后应同时测试网页方向、UART识别坐标和机器人机械方向。
过流任务每约20 ms轮询,发现有效信号时先关闭相机电源,再处理驱动清理。它不是对外承诺的精确保护响应时间;物理短路应立即断电检查。
配网与绑定时序
相机 HELLO(cameraId、camera_binding_v1) → 主控
相机 ← RESPONSE + cameraProvision(SSID、密码、BSSID、robotId、session)
相机 ACK已排队 → 主控
相机 Wi-Fi管理任务:保存配置 → 连接指定BSSID → 获得IP并核对接入点
相机 cameraStatus(bound、IP、streamToken...) → 主控
浏览器 GET主控/api/caps → 获取peripherals.camera.streamUrl
浏览器 使用该URL向相机81端口取流
BSSID指定目标AP;robotId表达绑定对象;主控session表示本次启动/配置会话。相机自己的启动随机量与主控session组成流令牌,任一侧会话改变后旧URL失效。令牌通过UART状态交给主控,/status不返回密码和令牌。
相机获得IP后核对实际接入AP的SSID/BSSID,并用UART下发的身份建立绑定状态;这不是通过HTTPS向主控验证证书的流程,不是对恶意同网攻击的完整认证方案。
NVS与恢复
NVS命名空间nodehexa_cam,新配置存为binding blob;可读取旧ssid/password记录以兼容未绑定设备。session不写Flash;网络未改变时重复HELLO不会因会话同步反复写入NVS。已绑定相机拒绝降级为SSID-only配置。
网络阶段可能为waiting、saving、applying、connecting、connected、await_session、retry或rejected。连接等待有上限,错误后退避重试;新配置可更新目标。相机复位后可以读取网络,但持久化记录没有主控session,绑定场景需要重新同步后才开放流。
完整镜像烧录会覆盖NVS区,详见烧录说明。如果更换主控或恢复旧版本,要把清除绑定作为明确操作,不应在业务代码里遇到连接失败就自动擦除NVS。
修改后的最小验收
确认两个分辨率、切换失败状态、主控单独重启、相机单独重启、过期URL、重复配网、断网重连和旧版兼容行为。多机实验应同时运行两台,核对cameraId/robotId与实际画面,不能仅看两个页面都能打开。主机回归测试不能代替这些硬件网络实验。