docs: 整理项目文档并统一界面表述
将项目说明按主题集中到 docs,补齐根目录 README 和 AGENTS,移除弃用方案并保留有效测试记录与未实现提案。同步文档索引、引用及改动日志生成路径,README 增加 GitHub Markdown 导航和 Mermaid 图。 - fix(client): 统一状态与操作文案,录制和截图成功后再显示完成提示 - test(client): 按文件名核对媒体类型,避免依赖时间戳排序 验证:23 份项目文档、144 处本地引用、27 条外链、2 张 Mermaid 图;前端构建和 12 项测试;截图与录制的 4 条异步反馈路径;Windows Rust 编译检查和后端测试。后端 40 项返回成功,其中 3 项 ffmpeg 集成用例因本机缺少工具而未实际执行。
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
# 图传固件入门
|
||||
|
||||
以下命令均在仓库根目录执行。桌面端与装甲板使用各自的构建目标,见[文档首页](../index.md)。
|
||||
|
||||
## 硬件要求
|
||||
|
||||
| 项目 | 当前配置 |
|
||||
| --- | --- |
|
||||
| 开发板 | Freenove ESP32-S3-WROOM CAM |
|
||||
| 模组 | ESP32-S3-WROOM-1-N16R8,16 MB Flash + 8 MB Octal PSRAM |
|
||||
| 摄像头 | OV5640;驱动包含 OV2640 / OV3660 支持,接线需核对 |
|
||||
| 网络 | 2.4 GHz Wi-Fi |
|
||||
| 连接 | 支持数据传输的 USB 线、可识别的串口及稳定供电 |
|
||||
|
||||
默认采集 VGA(640 × 480)、彩色 JPEG quality 12,按传感器节拍发送。相机引脚、Flash 分区和 PSRAM 配置见 [图传板硬件](../hardware/camera.md)。换板型前必须核对接线,避免占用 Flash / PSRAM 引脚。
|
||||
|
||||
## 固件开发环境
|
||||
|
||||
本项目使用 Rust `std` 和 ESP-IDF。ESP32-S3 属于 Xtensa 架构,需要通过 `espup` 安装 Espressif Rust 工具链;普通 `rustup target add` 不能替代这一步。根目录固定使用名为 `esp-1.97.0.0` 的工具链,避免浮动版本影响构建。
|
||||
|
||||
### 1. 安装基础依赖与 Rust 工具
|
||||
|
||||
先安装 [Rust / rustup](https://rustup.rs/)、[Git](https://git-scm.com/downloads)、[Python 3](https://www.python.org/downloads/)(建议 3.11)、[CMake](https://cmake.org/download/) 与 [Ninja](https://ninja-build.org/),确保命令在 `PATH` 中。
|
||||
|
||||
- Windows:使用 PowerShell 7.5 或更新版本,安装 Visual Studio Build Tools 的“使用 C++ 的桌面开发”和 Windows SDK,使用 MSVC Rust 主机工具链。仓库和工具链尽量使用较短、无空格和中文的路径。
|
||||
- Linux(Debian / Ubuntu):安装 `build-essential pkg-config libudev-dev libssl-dev python3 python3-venv cmake ninja-build git curl`。
|
||||
- macOS:安装 Xcode Command Line Tools(`xcode-select --install`),以及 Python、CMake 和 Ninja。
|
||||
|
||||
以下命令显式使用 `+stable`,即使在仓库内执行,也不会要求事先已有 `esp`:
|
||||
|
||||
```text
|
||||
rustup toolchain install stable
|
||||
cargo +stable install espup --locked
|
||||
cargo +stable install ldproxy --locked
|
||||
cargo +stable install espflash --version 4.4.0 --locked
|
||||
espup install --name esp-1.97.0.0 --toolchain-version 1.97.0.0 --targets esp32s3 --std
|
||||
```
|
||||
|
||||
也可以从各工具的官方 releases 下载预编译程序。`espup --std` 安装本项目所需的 Rust / LLVM 工具,ESP-IDF 的 C 工具链由后续构建准备。
|
||||
|
||||
Linux / macOS 每次新开终端后执行:
|
||||
|
||||
```bash
|
||||
. "$HOME/export-esp.sh"
|
||||
```
|
||||
|
||||
Windows 安装后重新打开 PowerShell,让环境变量生效;若当前终端仍找不到 LLVM,可执行 `. "$HOME/export-esp.ps1"`。检查结果:
|
||||
|
||||
```text
|
||||
rustup toolchain list
|
||||
rustc +esp-1.97.0.0 --version
|
||||
cargo +esp-1.97.0.0 --version
|
||||
espflash --version
|
||||
```
|
||||
|
||||
官方入门资料:[The Rust on ESP Book](https://docs.espressif.com/projects/rust/book/getting-started/toolchain.html)、[espup](https://github.com/esp-rs/espup)、[espflash](https://github.com/esp-rs/espflash/tree/v4.4.0/espflash)。
|
||||
|
||||
### 2. 准备 ESP-IDF
|
||||
|
||||
默认使用 ESP-IDF v5.5.5。首次构建时,`esp-idf-sys` 下载 SDK、对应 C 工具链及 Python 依赖,默认缓存到用户目录的 `.espressif/`;需要网络、磁盘空间及缓存目录写入权限。
|
||||
|
||||
已有匹配版本 SDK 时可在终端设置 `IDF_PATH`,不要提交个人绝对路径:
|
||||
|
||||
```powershell
|
||||
# Windows:替换为实际 SDK 源码目录。
|
||||
$env:IDF_PATH = 'C:\Espressif\frameworks\esp-idf-v5.5.5'
|
||||
```
|
||||
|
||||
```bash
|
||||
# Linux / macOS:替换为实际 SDK 源码目录。
|
||||
export IDF_PATH="$HOME/esp/esp-idf-v5.5.5"
|
||||
```
|
||||
|
||||
使用自动下载时,清除指向其他 SDK 的旧 `IDF_PATH`。缓存位置等高级设置见 [esp-idf-sys 构建选项](https://github.com/esp-rs/esp-idf-sys/blob/master/BUILD-OPTIONS.md)。
|
||||
|
||||
## 配置 Wi-Fi 与摄像头
|
||||
|
||||
在根目录复制 `.env.example` 为 `.env`,再用编辑器填写;已有 `.env` 时不要覆盖。
|
||||
|
||||
```powershell
|
||||
# Windows PowerShell
|
||||
Copy-Item .env.example .env
|
||||
```
|
||||
|
||||
```bash
|
||||
# Linux / macOS
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
```dotenv
|
||||
WIFI_SSID='你的2.4G网络名称'
|
||||
WIFI_PASS='你的Wi-Fi密码'
|
||||
|
||||
# 可选,省略时使用固件默认值。
|
||||
#CAM_RES=vga
|
||||
#CAM_QUALITY=12
|
||||
#CAM_QUALITY_MAX=0
|
||||
#CAM_MAX_FPS=0
|
||||
#CAM_CLOCK_PROFILE=default
|
||||
#CAM_FB_COUNT=3
|
||||
#CAM_GRAYSCALE=0
|
||||
#CAM_EXPOSURE_EV=0
|
||||
#CAM_AE_LEVEL=-1
|
||||
#CAM_SHUTTER_LINES=0
|
||||
#CAM_EXPOSURE_MAX_LINES=0
|
||||
#CAM_GAIN_CEILING=0
|
||||
#CAM_HTS=0
|
||||
#UDP_PACKET_GAP_US=0
|
||||
#UDP_RETRY_BUDGET_US=8000
|
||||
#CAM_THERMAL_LIMIT_C=75
|
||||
#CAM_VSYNC_INVERT=1
|
||||
#WIFI_AUTH=wpa2
|
||||
#WIFI_TX_POWER_DBM=15
|
||||
#WIFI_TEST_DROP_AFTER_S=0
|
||||
```
|
||||
|
||||
| 变量 | 默认值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `WIFI_SSID` | 无,必填 | 2.4 GHz 网络名称,最多 32 字节 |
|
||||
| `WIFI_PASS` | 空字符串 | Wi-Fi 密码;开放网络可留空 |
|
||||
| `CAM_RES` | `vga` | `qqvga` / `qvga` / `cif` / `hvga` / `vga` / `svga` / `xga` / `sxga` / `uxga` |
|
||||
| `CAM_QUALITY` | `12` | 0–63,越小通常画质越好、JPEG 越大;当前交付使用 18 |
|
||||
| `CAM_QUALITY_MAX` | `0` | `0` 固定画质;设为 `CAM_QUALITY`–63 时按发送回压在两者之间调节压缩,保留彩色和分辨率。拥塞时每 5 秒增大最多 3 档,连续稳定 15 秒才恢复 1 档 |
|
||||
| `CAM_MAX_FPS` | `0` | 取帧与发送的最高节拍,1–60;`0` 不限帧。仅限制消费节拍,不修改传感器时钟 |
|
||||
| `CAM_CLOCK_PROFILE` | `default` | `default` 保留驱动时钟;`vga30` 使用 OV5640 VGA 约 30.09 fps PLL 配置,保持 HTS/VTS 和读出窗口,SYSCLK 61 MHz / PCLK 15.25 MHz。切换后需重新核对曝光行数 |
|
||||
| `CAM_FB_COUNT` | `3` | PSRAM 帧缓冲数,允许 2 或 3。当前交付选三缓冲,保留发送突发时的采集余量;双缓冲曾在短测降低部分回显延迟,但用户长程运行反馈峰值丢帧明显,保留为试验选项 |
|
||||
| `CAM_GRAYSCALE` | `0` | `1` 使用传感器灰度效果,保留硬件 JPEG;`0` 彩色 |
|
||||
| `CAM_EXPOSURE_EV` | `0` | OV5640 自动曝光目标偏置:`-1` / `-2` 约对应 −1.1 / −1.9 EV;不是标定后的绝对 EV,也不保证快门缩短 |
|
||||
| `CAM_AE_LEVEL` | 未设置 | 可选 OV5640 驱动 AE 档位,−5–5;仅与 `CAM_EXPOSURE_EV=0` 同用。`-1` 将目标从 55 小幅降至 45,目标比值约 −0.29 EV,保留自动曝光/增益;未设置时按 EV 参数处理。实际快门和亮度变化取决于场景 |
|
||||
| `CAM_SHUTTER_LINES` | `0` | OV5640 固定快门,单位为传感器曝光行;`0` 自动曝光,非零保持自动增益。默认 VGA / HTS 2060 下 220 行估算约 10 ms;数值不能超过当前 VTS |
|
||||
| `CAM_EXPOSURE_MAX_LINES` | `0` | OV5640 自动曝光上限,`0` 保留驱动默认。非零保持 AEC/AGC 联动并禁用夜景延帧,不能与固定快门同时使用。默认 VGA 下 440 行约 20 ms;`vga30` 下 592 行约 20 ms。实际曝光由场景和抗频闪步长决定 |
|
||||
| `CAM_GAIN_CEILING` | `0` | OV5640 自动增益上限,`0` 保留驱动默认;1–63,单位为倍,实际上限略低于整数档。短曝光遇到室内弱光时可提高,但暗部噪点和 JPEG 负载可能增加 |
|
||||
| `CAM_HTS` | `0` | OV5640 水平总长度试验参数,`0` 使用驱动默认。缩短消隐会影响彩色稳定性,本机 1500 / 1800 出现绿紫闪烁,已撤回;几何检查通过不代表可用 |
|
||||
| `UDP_PACKET_GAP_US` | `0` | 成功提交视频数据报之间的最小间隔;0–5000 μs,须为调度 tick 的整数倍(当前为 1000 μs)。配合有界帧等待,避免集中突发写入队列 |
|
||||
| `UDP_RETRY_BUDGET_US` | `8000` | 每帧、所有分片及订阅者共用的让出调度重试预算,0–25000 μs,须为 tick 整数倍;`0` 为非阻塞失败即弃。总发送检查期限为 25 ms,采集帧龄期限为 100 ms;分片间隔也计入期限,不会额外延长 |
|
||||
| `CAM_THERMAL_LIMIT_C` | `75` | 芯片内部温度达到该值时减半帧率(向上取整),下降 5°C 后恢复;40–95,`0` 禁用。原先不限帧时降至 8 fps |
|
||||
| `CAM_VSYNC_INVERT` | `1` | 驱动反相 VSYNC;硬件已反相时填 `0` |
|
||||
| `WIFI_AUTH` | 自动选择 | `none` / `wep` / `wpa` / `wpa2` / `wpawpa2` / `wpa3` / `wpa2wpa3` / `wapi`;只在扫描看不到 AP(如隐藏 SSID)时才需要 |
|
||||
| `WIFI_TX_POWER_DBM` | SDK 默认上限 | 可选整数 2–20 dBm;当前交付请求 15 dBm,本板驱动回读 15.00 dBm;启动及重连时应用,拥塞和温控逻辑不降低此上限 |
|
||||
| `WIFI_TEST_DROP_AFTER_S` | `0` | 仅诊断构建:运行指定秒数后主动断网一次并保持 5 秒,用来验证运行时恢复。正式构建保持 `0` |
|
||||
|
||||
`.env` 使用简单的 `KEY=value`;值含空格、`#` 或 `$` 时用单引号包围,不使用变量展开或命令替换。脚本会加载 `.env`,直接 `cargo build` 不会自动读取它。上述参数在编译时写入固件,修改后需要重新编译和烧录。`.env` 已被 Git 忽略;固件也包含凭据,分享前应重新配置。
|
||||
|
||||
运行时断线恢复不重置摄像头、曝光或增益。首次尝试立即发起,失败后按 1、2、4、8、16、30 秒退避;关联与 DHCP 分别有 15 秒期限。恢复 IP 后丢弃旧采集帧、重建 socket 并重新广播,由客户端自动续订。启动时首次联网仍使用扫描与认证模式探测流程。实现依据 [ESP-IDF 断线事件处理说明](https://docs.espressif.com/projects/esp-idf/en/v5.5.5/esp32s3/api-guides/wifi.html#wifi-event-sta-disconnected)。
|
||||
|
||||
## 编译固件
|
||||
|
||||
在仓库根目录执行:
|
||||
|
||||
```powershell
|
||||
# Windows PowerShell
|
||||
$env:CARGO_TARGET_DIR = 'C:\s3vt'
|
||||
.\scripts\build.ps1
|
||||
```
|
||||
|
||||
```bash
|
||||
# Linux / macOS
|
||||
./scripts/build.sh
|
||||
```
|
||||
|
||||
脚本执行 `cargo build --release --locked`,目标为 `xtensa-esp32s3-espidf`。首次编译包含 Rust 标准库、ESP-IDF 和相机组件,耗时较长。构建完成后可用 `-Package` / `--package` 再打一个 `.zip` 固件包,供桌面端维护页使用。
|
||||
|
||||
Windows 的 ESP-IDF 构建输出路径需不超过 88 字符,因此示例使用短目录 `C:\s3vt`(需可写,且不与其他项目共用)。`subst` 不能绕过该检查。下表的 `<TARGET_DIR>` 在 Windows 示例中为 `C:/s3vt`,Linux / macOS 默认是仓库的 `target`。每次新开 Windows 终端都要设置相同的 `CARGO_TARGET_DIR`。
|
||||
|
||||
| 产物 | 位置 |
|
||||
| --- | --- |
|
||||
| 固件 ELF | `<TARGET_DIR>/xtensa-esp32s3-espidf/release/esp32`(没有 `.exe` 后缀) |
|
||||
| Bootloader | `<TARGET_DIR>/xtensa-esp32s3-espidf/release/bootloader.bin` |
|
||||
| 分区表 BIN | `<TARGET_DIR>/xtensa-esp32s3-espidf/release/partition-table.bin` |
|
||||
| 分区表源文件 | 根目录 `partitions.csv` |
|
||||
|
||||
ELF 供 `espflash` 烧录与符号解析,不能当作 BIN 直接写入 Flash。Bootloader、分区表与 App 应来自同一次构建。
|
||||
|
||||
## 烧录与串口验证
|
||||
|
||||
### 1. 查找串口
|
||||
|
||||
```text
|
||||
espflash list-ports
|
||||
```
|
||||
|
||||
Windows 常见 `COM5`;Linux 为 `/dev/ttyACM0` 或 `/dev/ttyUSB0`;macOS 为 `/dev/cu.usbmodem...`。关闭其他串口监视器,Linux 需具备串口访问权限。
|
||||
|
||||
### 2. 烧录 ELF
|
||||
|
||||
本项目使用自定义分区表,显式传入 `partitions.csv` 和本次构建的 Bootloader。将示例端口替换为实际端口:
|
||||
|
||||
```powershell
|
||||
$targetDir = if ($env:CARGO_TARGET_DIR) { $env:CARGO_TARGET_DIR } else { 'target' }
|
||||
espflash flash --chip esp32s3 --port COM5 --flash-size 16mb --flash-mode dio --flash-freq 40mhz --partition-table partitions.csv --bootloader "$targetDir/xtensa-esp32s3-espidf/release/bootloader.bin" --monitor "$targetDir/xtensa-esp32s3-espidf/release/esp32"
|
||||
```
|
||||
|
||||
```bash
|
||||
target_dir="${CARGO_TARGET_DIR:-target}"
|
||||
espflash flash --chip esp32s3 --port /dev/ttyACM0 --flash-size 16mb --flash-mode dio --flash-freq 40mhz --partition-table partitions.csv --bootloader "$target_dir/xtensa-esp32s3-espidf/release/bootloader.bin" --monitor "$target_dir/xtensa-esp32s3-espidf/release/esp32"
|
||||
```
|
||||
|
||||
连接失败时按住 BOOT,点按 RESET / EN,松开 BOOT 后重试。正常启动应看到相机识别、Wi-Fi 获取 IP 和 `ESP32 camera is live` 日志。没有客户端时,`0 clients subscribed` 属于正常状态。
|
||||
|
||||
仅查看日志:
|
||||
|
||||
```text
|
||||
espflash monitor --port COM5
|
||||
```
|
||||
|
||||
### 3. 导出 BIN
|
||||
|
||||
`espflash save-image --merge` 可导出从 `0x0` 写入的合并镜像。完整命令、独立镜像偏移与测试方法见 [开发与验证](../development/firmware.md)。
|
||||
|
||||
保留的 `scripts/flash.sh` 针对特定坏 Flash 模组,依赖 macOS 环境,会修改分区并重编译。普通板卡使用上述标准流程;坏板限制见 [图传板硬件](../hardware/camera.md#损坏-flash-模组的兼容处理)。
|
||||
Reference in New Issue
Block a user