适用开发板:Korvo S3 · 工程
04.advanced.qrcode_detection· targetesp32s3
库:esp_code_scanner· 摄像头:DVP
学习时长:约 20 分钟 · 难度:★★★☆☆
学习目标
完成本节后,你将能够:
- 理解 DVP 摄像头取帧与图像处理的基本流程
- 掌握
esp_code_scanner组件的使用方法 - 了解 RGB565 图像格式与字节序问题
- 实现二维码/条形码的实时检测与内容解析
1. 这个例子在干嘛
这是一个 实时二维码/条形码识别 例程。设备通过 DVP 摄像头持续取帧,对每一帧进行二维码扫描,识别成功后在 LVGL 界面上显示内容,同时串口打印结果。
工作原理可以用一句话概括:拍照 → 找码 → 解码 → 显示。
┌──────────┐ ┌───────────────┐ ┌───────────────┐ ┌──────────┐
│ DVP 摄像头│───→│ RGB565 帧缓冲 │───→│esp_code_scanner│───→│ LVGL 显示│
│ (取帧) │ │ (PSRAM) │ │ (解码) │ │ + 串口 │
└──────────┘ └───────────────┘ └───────────────┘ └──────────┘
支持的码制(取决于 esp_code_scanner 配置):
- QR Code(最常用)
- Data Matrix
- PDF417
- 常见一维条形码(EAN-13、Code 128 等)
与 P4C5 版的区别:Korvo 使用 单路 DVP 并口摄像头,分辨率和处理速度低于 P4 的 MIPI CSI;但识别逻辑完全相同。P4 版见 P4C5 qrcode。
2. 编译烧录
cd Korvo_Firmware\04.advanced.qrcode_detection
idf.py set-target esp32s3
idf.py build flash monitor
提示:首次编译会通过 Component Manager 下载
esp_code_scanner组件,确保网络通畅。
3. 运行现象
| 阶段 | 屏幕表现 | 串口输出 |
|---|---|---|
| 启动 | 摄像头预览画面出现 | camera init OK 等初始化日志 |
| 待扫描 | 实时预览,无额外信息 | 无输出或帧率日志 |
| 识别成功 | label 区域显示解码字符串 | Decoded: https://... 或扫到的文本内容 |
测试方法:用手机打开一个 QR 码(微信二维码、URL 二维码均可),距离摄像头 10~30 cm,确保码在画面中清晰且占一定比例。
4. 关键文件与代码解析
| 文件 | 作用 | 重点关注 |
|---|---|---|
main/app_main.c | 入口,初始化显示与摄像头 | app_main() 调用顺序 |
main/page_cam.c | 核心扫描任务 Cam_Task | 取帧 → 解码 → UI 更新 |
main/app_camera.c | DVP 摄像头驱动初始化 | camera_config_t 参数 |
核心扫描循环(page_cam.c 中的 Cam_Task)
while (1) {
1. esp_camera_fb_get() ← 从 DVP 取一帧 RGB565
2. RGB565 字节序转换 ← 若 LVGL 与 sensor 字节序不同
3. esp_code_scanner_scan() ← 送入解码器
4. 如果识别到内容:
- 更新 LVGL label 文本
- 串口打印解码结果
5. 更新 LVGL image(预览画面)
6. esp_camera_fb_return() ← 归还帧缓冲
}
关键 API:
| API | 说明 |
|---|---|
esp_code_scanner_scan() | 输入 RGB565 图像数据,返回识别结果列表 |
esp_camera_fb_get() | 从摄像头获取一帧(阻塞直到帧就绪) |
esp_camera_fb_return() | 归还帧缓冲给驱动(不归还会耗尽 buffer) |
5. RGB565 字节序——一个常见坑
什么是 RGB565?
用 2 字节表示一个像素:5 位红 + 6 位绿 + 5 位蓝。ESP 摄像头输出的 RGB565 可能是大端序(高字节在前),而 LVGL 默认期望小端序。
不匹配的表现:画面色彩诡异(偏蓝/偏红),但不影响识别功能。
解决方法:在送入 LVGL 前做一次 swap(高低字节交换),代码中通常有 SWAP_BYTES 或逐像素 (pixel >> 8) | (pixel << 8) 操作。
6. 常见问题与排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 扫不出二维码 | 距离太远/太近;光线不足;图像模糊 | 调整距离 10~30cm;补充光源;擦镜头 |
| 画面花屏/色彩异常 | RGB565 字节序未正确 swap | 检查 page_cam.c 中的字节序处理代码 |
| 黑屏无画面 | DVP 排线松动;sensor 未识别 | 先跑 korvo_board_test Camera 页验证硬件 |
| 编译报缺组件 | esp_code_scanner 下载失败 | 检查网络,重新 idf.py reconfigure |
| 识别速度慢 | 分辨率过高;PSRAM 带宽不足 | 降低 camera_config_t 中的 frame_size |
7. 动手改造建议
- 显示识别类型:在 label 旁显示识别到的码制(QR Code / EAN-13 等)
- 识别成功蜂鸣:GPIO 驱动蜂鸣器,识别成功时响一声
- 历史记录:用 LVGL list 控件保存最近 5 条扫码记录
- 网络联动:扫到 URL 后通过 HTTP Client 访问并显示结果
8. 知识延伸
esp_code_scanner与 ZBar 的关系:ESP 版基于 ZBar 优化,减少内存占用- 分辨率与识别率的平衡:QVGA(320×240)是常用甜点——更高分辨率不一定更好,因为处理更慢
- 多码并存:一帧中可能同时存在多个二维码,
scan可返回多个结果
9. 下一步
| 方向 | 推荐例程 |
|---|---|
| 人脸识别(AI 进阶) | face_recognition |
| 摄像头 LVGL 预览 | camera_lvgl_display |
| 网页图传 | camera_webserver |
酷世DIY · Kevincoooool