两块 ESP32-S3-WROOM-1-N16R8 图传板(DVP 接口接 OV2640/OV3660/OV5640), 向队伍客户端与裁判终端推 UDP 图传。固件是跑在 ESP-IDF 上的 Rust,用官方 esp32-camera 组件采集;客户端是 Rust + Slint 桌面程序。 三个 crate 各自独立构建: . firmware,交叉编译到 Xtensa protocol/ 线路格式与帧重组,两端共用,无 ESP-IDF 依赖,有单元测试 client/ Slint 桌面客户端 视频走 UDP 而非 TCP:实测传感器产出 22 fps,TCP MJPEG 只送出 1.9 fps, 且只占用链路能力的 1%——链路是空的,帧堵在队头阻塞后面等一个实时画面 等不起的重传计时器。改为独立数据报、不重传、缺片丢整帧后达到 20.8 fps。 发现是双向的:板子每 2 秒广播 Hello,客户端广播 Subscribe,板子据此定向 推流。板子身份由 MAC 派生,重启不变,所以客户端可以把绑定存进配置。 裁判端同时收两块板子(每个发送方一个重组器),队伍端绑定其中一块并只显示 自己那一边的血量。装甲板接口已预留(ArmorSource trait + ARMOR_PORT), 当前无数据源,界面显示占位符。 vendor 了 esp32-camera 2.1.7:组件注册表的版本求解器找不到它,且需要打一处 补丁(见 components/esp32-camera/target/esp32s3/ll_cam.c)。 .gitignore 三条 target/ 都锚定在根目录,因为 protocol/ 与 client/ 各自也是 独立 crate;而 components/esp32-camera/target/ 是上游的按芯片分目录,里面是 源码,必须保留。
104 lines
4.6 KiB
Plaintext
104 lines
4.6 KiB
Plaintext
# Rust needs more stack than C for the main task and for the threads esp-idf-svc
|
|
# spawns internally.
|
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
|
|
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=4096
|
|
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=4096
|
|
|
|
# Run the CPU at 240 MHz.
|
|
#
|
|
# This is the single biggest win in this file and it is free. ESP-IDF v5.5's
|
|
# Kconfig defaults the ESP32-S3 to *160* MHz (see
|
|
# components/esp_system/port/soc/esp32s3/Kconfig.cpu), so a stock build quietly
|
|
# leaves half the CPU on the table. Camera capture, the JPEG search in
|
|
# esp32-camera, lwIP and the HTTP server are all CPU-bound here, so this moves
|
|
# all of them at once.
|
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
|
|
|
# ESP32-S3-N16R8: 16 MB flash, 8 MB octal PSRAM.
|
|
#
|
|
# DIO at 40 MHz, not the QIO/80 MHz this part is rated for: the flash on the
|
|
# test module has a defective byte (see README) and quad mode pushes it over
|
|
# the edge into a boot loop. Drop back to QIO/80 MHz on a healthy module.
|
|
#
|
|
# QIO would speed up *code* execution noticeably, since the app runs from flash
|
|
# and the flash cache misses go straight to this bus.
|
|
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
|
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
|
|
CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
|
|
|
|
# Code runs from flash, so instruction cache is the cheapest way to hide the
|
|
# slow flash bus. 32 KB instead of the 16 KB default.
|
|
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
|
|
|
|
# Without this ESP-IDF uses partitions_singleapp.csv, whose factory partition is
|
|
# only 1 MB - smaller than the ~1.15 MB this firmware produces, so the image
|
|
# overflows the partition.
|
|
#
|
|
# The custom table also moves the app to 0x40000, which is what keeps the image
|
|
# off the module's defective flash byte; see partitions.csv for why.
|
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="../../../../../../partitions.csv"
|
|
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
|
|
|
# Octal PSRAM is mandatory for the N16R8 module (R8 == 8 MB OPI PSRAM). The
|
|
# camera frame buffers live in it, so this is what makes VGA possible.
|
|
CONFIG_SPIRAM=y
|
|
CONFIG_SPIRAM_MODE_OCT=y
|
|
CONFIG_SPIRAM_SPEED_80M=y
|
|
CONFIG_SPIRAM_USE_MALLOC=y
|
|
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
|
|
CONFIG_SPIRAM_MEMTEST=y
|
|
|
|
# Keep the WiFi and lwIP buffers in internal RAM.
|
|
#
|
|
# This was previously set to `y` on the reasoning that PSRAM is plentiful, which
|
|
# is exactly backwards: WiFi descriptors and TCP segments are touched on every
|
|
# packet, and internal SRAM is an order of magnitude faster to reach than PSRAM
|
|
# behind the memory bus. Putting them in PSRAM shows up as high latency and poor
|
|
# throughput no matter how much PSRAM is free. The frame buffers, which are large
|
|
# and touched rarely by comparison, stay in PSRAM.
|
|
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=n
|
|
|
|
CONFIG_ESP_WIFI_IRAM_OPT=y
|
|
CONFIG_ESP_WIFI_RX_IRAM_OPT=y
|
|
|
|
# Socket buffers sized for a video frame rather than for a text request.
|
|
#
|
|
# A VGA JPEG is ~20 kB. lwIP's 5760-byte default send buffer splits that into
|
|
# four segments, each one a separate pass through the WiFi driver; 17408 is the
|
|
# lwIP-recommended size for bulk transfers and covers a frame in one or two.
|
|
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=17408
|
|
CONFIG_LWIP_TCP_WND_DEFAULT=17408
|
|
|
|
# Camera component
|
|
CONFIG_CAMERA_TASK_STACK_SIZE=4096
|
|
|
|
# Run the camera task on CPU1.
|
|
#
|
|
# The WiFi task is pinned to CPU0. esp32-camera's capture task spends its time
|
|
# in short, latency-sensitive bursts (DMA completion, the JPEG marker search,
|
|
# the copy into the frame buffer) and gets preempted on a shared core, which
|
|
# lengthens every frame. On a two-core part there is no reason to share.
|
|
CONFIG_CAMERA_CORE0=n
|
|
|
|
# PSRAM DMA is left off deliberately.
|
|
#
|
|
# With it on, esp32-camera writes frame buffers in PSRAM straight from GDMA and
|
|
# then looks for the JPEG end-of-image marker only inside the last DMA node
|
|
# (1 KB here). If the marker lands outside that window the frame is thrown away
|
|
# with "NO-EOI", and on this board that is most of them - after a few frames the
|
|
# driver stops handing out frames at all and never recovers.
|
|
#
|
|
# Off, the driver DMAs into an internal-RAM bounce buffer and copies the frame
|
|
# into PSRAM, which costs one extra memcpy of ~23 KB per frame and searches the
|
|
# whole buffer for the marker. That is the right trade for a working stream.
|
|
CONFIG_CAMERA_PSRAM_DMA=n
|
|
# Largest contiguous DMA chunk the driver may ask for.
|
|
CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768
|
|
|
|
# ESP-IDF 5.3+ links both the legacy driver/i2c.h and the new driver_ng I2C
|
|
# driver, and refuses to run both in one image. esp32-camera picks one of them
|
|
# for the SCCB bus; whichever it picks, the other has to stay out of the image,
|
|
# so the conflict check is skipped here.
|
|
CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK=y |