一、项目概述

本项目基于 ESP-DL 库的 yolo11_detect 示例,在 ESP32-S3(N16R8,16MB Flash + 8MB PSRAM)上实现了从网络获取 JPEG 图片、进行 YOLO11n 目标检测、并通过串口交互式输入 URL 输出中文检测结果的功能。


二、开发环境与工具

  • 硬件:ESP32-S3-WROOM-1-N16R8(16MB Flash)

  • 软件框架:ESP-IDF v6.0.1

  • AI 推理库:ESP-DL v3.3.2(组件化安装)

  • 模型:YOLO11n INT8 量化模型(coco_detect_yolo11n_s8_v1.espdl),存放于 Flash 的 coco_det 分区

  • 编程语言:C++(app_main.cpp


三、项目创建与初始化

1. 从官方示例创建项目

bash

idf.py create-project-from-example "espressif/esp-dl=3.3.2:yolo11_detect"

该命令会自动下载示例代码并生成项目骨架。

2. 设置目标芯片

bash

idf.py set-target esp32s3

四、关键配置步骤

4.1 分区表配置(partitions2.csv

原始示例默认使用 8MB Flash,但模型 + 应用超过 8MB,需调整为适配 16MB Flash:

csv

nvs,       data,  nvs,      0x9000,      24K,
phy_init,  data,  phy,      0xf000,      4K,
factory,   app,   factory,  0x010000,    8M,      # 应用分区 8MB
coco_det,  data,  spiffs,   ,            4M,      # 模型分区 4MB(实际模型 2.8MB)
  • 若模型嵌入固件(EMBED_FILES),则无需 coco_det 分区,但此处采用独立分区烧录模型。

4.2 组件依赖(idf_component.yml

项目需要 esp_new_jpeg(但最终使用 dl_image_jpeg 软件解码,故未实际添加)。网络功能所需组件已在 main/CMakeLists.txt 中通过 REQUIRES 声明。

4.3 主组件构建文件(main/CMakeLists.txt

  • 移除 EMBED_FILES(防止模型嵌入 App,导致体积过大)

  • 添加网络组件依赖:

cmake

set(requires coco_detect
             esp_wifi
             esp_http_client
             nvs_flash
             esp_event
             esp_netif)
  • 保留条件编译(esp32_s3_eye_noglib 等)

4.4 Menuconfig 设置

  • Flash SizeSerial flasher config → Flash size → 16 MB

  • 优化选项Compiler options → Optimization Level → -Os(减小 App 体积)

  • 看门狗Component config → ESP System Settings → Enable Task Watchdog Timer → 取消勾选(或延长超时,我们在代码中调用 esp_task_wdt_deinit() 禁用)


五、代码开发与功能实现

5.1 核心功能模块

  • Wi-Fi 连接wifi_init_sta() 使用事件组等待 IP 分配,返回连接状态。

  • HTTP 图片下载:采用 esp_http_client_open() + esp_http_client_fetch_headers() + 循环 esp_http_client_read() 的流式方式,避免一次性读取失败(关键)。

  • JPEG 解码:使用 ESP-DL 的 dl::image::sw_decode_jpeg() 将 JPEG 转为 RGB888。

  • YOLO 推理COCODetect 类自动从 coco_det 分区加载模型,调用 run() 得到检测结果列表。

  • 串口交互:自定义 read_line() 函数,基于 getchar 实现命令行输入,支持退格、忽略非打印字符。

  • 结果输出:使用预定义的中文类别名称数组,将类别 ID 映射为中文显示。

5.2 关键代码片段

下载函数(解决读取 0 字节问题)

cpp

esp_http_client_config_t config = {};
config.url = url;
config.method = HTTP_METHOD_GET;
config.timeout_ms = 30000;
config.user_agent = "Mozilla/5.0";
config.keep_alive_enable = false;
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "Accept-Encoding", "identity");
esp_http_client_open(client, 0);
int content_length = esp_http_client_fetch_headers(client);
// 循环读取直到 content_length 或连接关闭
串口输入函数(避免 fgets 阻塞问题)

cpp

static int read_line(char *buf, int max_len) {
    int idx = 0;
    while (1) {
        int c = getchar();
        if (c == EOF) continue;
        if (c == '\r' || c == '\n') { buf[idx] = '\0'; return idx; }
        // 处理退格、可打印字符...
    }
}

六、编译、烧录与运行

6.1 编译

bash

idf.py build

常见编译错误及解决:

  • missing-field-initializers:改用 wifi_config_t wifi_config = {}; 然后逐个字段赋值,或使用 strcpy

  • 类型不匹配esp_http_client_read_response 要求 char*,传入 uint8_t* 需强制转换 (char*)

  • 未使用变量警告:移除 TAG,在事件处理函数中添加 (void)event_data;

6.2 烧录模型到 Flash 分区

使用 esptool.py 单独烧录模型(或通过 idf.py flash 自动执行,如果已在 CMake 中添加 esptool_py_flash_to_partition):

bash

复制

下载

esptool.py --chip esp32s3 --port COMx write_flash 0x810000 coco_detect_yolo11n_s8_v1.espdl

0x810000 根据分区表计算(coco_det 的偏移量)。若使用 partitions2.csv 自动分配,偏移量可通过 idf.py partition-table 查看。

6.3 烧录应用

bash

idf.py -p COM22 flash

6.4 运行监视

bash

idf.py -p COM22 monitor

程序启动后自动连接 Wi-Fi,然后进入交互模式等待用户输入图片 URL。


七、问题与解决方案汇总

问题现象 原因分析 解决方法
App 分区溢出(factory 太小) 模型被嵌入固件(EMBED_FILES)或 App 本身过大 移除 EMBED_FILES;使用 16MB Flash 并扩大 factory 分区;启用 -Os 优化
HTTP 下载 esp_http_client_read_response 返回 0 一次性读取方式不适合 chunked 或 keep-alive 连接 改用 esp_http_client_open + 循环 esp_http_client_read
串口输入 fgets 不等待,直接退出 stdin 缓冲问题,EOF 提前到来 改用 getchar 循环手动读取,忽略 EOF
看门狗超时复位 YOLO 推理耗时较长(约 5~8秒) 禁用看门狗 esp_task_wdt_deinit() 或延长超时
编译警告 missing-field-initializers 结构体指定初始化顺序与声明不一致 使用全零初始化 + 逐字段赋值
模型加载失败(未找到分区) 分区名 coco_det 与代码中加载名不一致 确认分区表名称与 COCODetect() 默认查找名称一致(示例默认 coco_det
图片下载失败(域名解析) DNS 未配置或网络不通 使用 IP 直连测试,确保 Wi-Fi 连接正常

八、最终程序特点

  • 中文交互:所有提示、错误信息、检测结果类别均为中文。

  • 简洁界面:仅显示必要的状态和结果,无大量调试日志。

  • 灵活输入:支持通过串口动态输入任意图片 URL,重复识别。

  • 稳定下载:流式 HTTP 读取,支持 chunked 和固定长度响应。

  • 资源释放:每次循环后释放图片数据和模型对象,防止内存泄漏。


九、后续可扩展方向

  • 支持从 SD 卡加载模型,释放 Flash 空间。

  • 支持从本地文件系统读取图片(如 SPIFFS)。

  • 增加 JSON 格式输出,方便上位机解析。

  • 接入摄像头实时视频流,实现连续检测。


十、参考资源

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐