闵立的开源项目

PROJECT GUIDE / 01 — WIRELESS DISPLAY

Wi-Fi 扩展屏

让 BOX-2 成为电脑的无线扩展屏。从固件刷写、首次配网,到 Windows 驱动与桌面串流,一步步完成连接。

项目概览:把 BOX-2 变成无线扩展屏

这套方案把 ATK-DNESP32S3-BOX2-WIFI 连接到 Windows 11,作为可以拖入窗口的第二块显示器。Windows 端创建虚拟显示器,主机程序抓取画面、缩放并编码为 JPEG;BOX-2 通过局域网接收、解码,再显示到 LCD。

本教程对应 feat/box2-wifi-display 分支。部署顺序是:准备工具链、获取源码、编译烧录、串口配网、构建安装 Windows 端,最后开启扩展显示。

项目当前实现
Windows 虚拟屏480 × 360,横屏,30 Hz
BOX-2 实际画面320 × 240,JPEG 质量 80,主机最高约 30 帧/秒
画面传输Wi-Fi / UDP 5000;自动发现使用 UDP 5001
鼠标显示主机将放大的系统鼠标指针合成到图像中
网络恢复自动发现设备,短暂断网或设备重启后尝试恢复串流
USB 的用途烧录、首次配网、查看日志;日常画面走 Wi-Fi

传输链路为 Windows 虚拟屏以 480 × 360 输出,缩放至 320 × 240 后编码为 JPEG,经 UDP 分片传输至 BOX-2,解码为 RGB565 后显示在 LCD 上。丢失分片的帧会被跳过;实际帧率受无线信号、电脑负载和设备解码速度影响。

准备硬件与开发环境

硬件与网络

  • 一台 ATK-DNESP32S3-BOX2-WIFI,以及能够传输数据的 USB 线。
  • 一台 Windows 11 x64 电脑。当前 Windows 项目仅提供 x64 构建配置。
  • 一个 2.4 GHz Wi-Fi 网络,使用 WPA2/WPA3 密码认证;密码至少 8 个字符。
  • 电脑与 BOX-2 处于能够相互通信的局域网。电脑可以通过有线或 Wi-Fi 接入;BOX-2 必须连接 2.4 GHz。

优先在普通家庭或开发局域网部署。访客网络、AP 客户端隔离、不同 VLAN 或网络策略可能拦截设备发现与串流。若网络由管理员管理,请让管理员允许设备间所需通信。

ESP32 固件工具链

安装 ESP-IDF 6.0.2。工程的 driver/idf_component.yml 将 IDF 版本固定为 ==6.0.2;直接使用其他版本可能导致依赖解析失败。

  1. 打开 乐鑫 Windows 安装指南,安装 ESP-IDF Installation Manager(EIM)。
  2. 在 EIM 中选择自定义安装,明确选择 v6.0.2,并安装 ESP32-S3 所需工具。安装器负责准备 Python、CMake、Ninja 和编译工具链。
  3. 安装完成后打开该版本对应的 ESP-IDF PowerShell 环境。也可以在已安装的 6.0.2 目录运行 export.ps1 激活环境。
  4. 执行下面的版本检查,确认输出包含 ESP-IDF v6.0.2
idf.py --version
git --version

idf.py 无法识别,先重新打开正确版本的 ESP-IDF 终端;仅安装 Git 或 Python 并不能代替激活 IDF 环境。完整配置步骤见 ESP32-S3 快速入门

Windows 主机与驱动工具链

  • Visual Studio 2022 Build Tools,安装“使用 C++ 的桌面开发”工作负载和 MSVC v143 工具集。
  • Windows Driver Kit(WDK)10.0.26100 系列,以及匹配构建号的 Windows SDK。
  • 确认 WDK 对 Visual Studio 的集成已安装,能够提供 WindowsUserModeDriver10.0 工具集。

仓库要求 WDK 10.0.26100 或更高版本。为保持 Visual Studio 2022 兼容,按 Microsoft WDK 安装说明选择对应版本;该页面目前为 VS 2022 指向 WDK 26100.6584,可从 其他 WDK 下载获取。SDK 与 WDK 的构建号需要匹配,不能仅凭“最新版”混装。

获取 Wi-Fi 显示分支

下面将工程放在用户目录的 source\esp32-box2-display 中。在 ESP-IDF 6.0.2 PowerShell 执行;如果你使用其他目录,后续进入工程的路径也要相应调整。

New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\source" | Out-Null
Set-Location "$env:USERPROFILE\source"
git clone --branch feat/box2-wifi-display --single-branch https://github.com/mlpre/esp32_box2.git esp32-box2-display
Set-Location .\esp32-box2-display
git branch --show-current

最后一行应输出 feat/box2-wifi-display。如果目标文件夹已存在,请先确认里面的项目与分支,避免在另一套 BOX-2 工程中混用命令。

工程根目录应包含 CMakeLists.txtsdkconfig.defaultsdrivermainwindows。以下固件命令都在这个根目录执行。

配置并编译 ESP32-S3 固件

首次编译可以直接使用项目默认配置,无需在菜单里填写 Wi-Fi。sdkconfig.defaults 已指定 ESP32-S3、16 MB Flash、OPI PSRAM 和 USB Serial/JTAG 控制台;Wi-Fi 信息在烧录后通过串口写入。

Set-Location "$env:USERPROFILE\source\esp32-box2-display"
idf.py --version
idf.py build

首次运行会下载 espressif/esp_codec_devespressif/esp_new_jpeg,生成配置、依赖锁文件和构建目录,然后编译 Bootloader、分区表与应用。等待终端出现 Project build complete

构建产物默认烧录地址用途
build/bootloader/bootloader.bin0x0启动加载程序
build/partition_table/partition-table.bin0x8000分区表
build/esp32_box2.bin0x10000Wi-Fi 显示应用

烧录时以本次构建生成的 build/flash_args 为准。新克隆的项目使用默认配置即可;若沿用过其他 ESP 芯片的本地构建目录,请先备份自定义配置,再用 idf.py set-target esp32s3 重新选择目标并构建。

烧录固件并首次配网

确认串口并烧录

通过 USB 数据线连接 BOX-2,在设备管理器的“端口(COM 和 LPT)”中确认设备,也可以运行:

Get-PnpDevice -Class Ports | Format-Table Status,FriendlyName

下面以 COM7 为例,请替换成实际端口。在 ESP-IDF 环境和工程根目录执行:

idf.py -p COM7 flash monitor

如果无法自动进入下载模式,按住 BOOT,短按 RESET,再松开 BOOT 后重试。监视器与其他串口工具不要同时占用同一端口。按 Ctrl + ] 退出 IDF 串口监视器。

在串口监视器中发送两行 Wi-Fi 信息

首次启动且没有保存的网络信息时,会出现:

BOX2_PROVISION_READY
Send WIFI_SSID:<ssid> and WIFI_PASS:<password> over USB serial.

串口监视器中依次发送下列两行,每行输入后按回车。替换冒号后面的内容,保留英文前缀;这里的两行不是 PowerShell 命令。

WIFI_SSID:你的无线网络名称
WIFI_PASS:你的无线网络密码

网络名称不能为空,密码至少 8 个字符。固件不接受开放网络;为避免编码差异,首次验证可使用简单的英文网络名称与密码。凭据保存到 NVS,普通应用烧录会保留它们。

按顺序确认日志:

BOX2_SSID_ACCEPTED
BOX2_PASS_ACCEPTED
BOX2_IP=设备获得的IP地址
BOX2_UDP_READY=5000

ACCEPTED 表示输入已被接收;拿到 BOX2_IP 才表示联网成功,出现 BOX2_UDP_READY=5000 表示视频接收服务已就绪。若显示 BOX2_PASS_REJECTED,重新发送满足长度要求的 WIFI_PASS: 行。

固件日志会显示 SSID 与密码长度,不会打印密码正文。上传排障日志前仍应检查其中的网络名称、IP 等信息。

更换已保存的 Wi-Fi

当前分支没有单独的清除网络指令。更换路由器或输错密码后,可擦除 Flash 并重新烧录,再执行上面的串口配网。擦除会删除设备全部 Flash 内容,包括固件和已保存的 Wi-Fi 信息。

idf.py -p COM7 erase-flash
idf.py -p COM7 flash monitor

构建 Windows 主机与显示驱动

打开普通 Windows PowerShell,进入 Windows 工程目录。构建本身不需要管理员权限:

Set-Location "$env:USERPROFILE\source\esp32-box2-display\windows\Box2Display"
.\build.ps1

若系统明确提示脚本被执行策略阻止,确认脚本来自本次获取的源码后,可只对当前 PowerShell 进程临时允许执行,再重新构建:

Set-ExecutionPolicy -Scope Process Bypass
.\build.ps1

该设置只作用于当前进程,关闭窗口即失效;组织组策略仍可能限制执行。无需为此修改整台电脑的长期执行策略。

build.ps1 没有必填参数,会调用 MSBuild 构建 Release x64 主机和 UMDF 间接显示驱动,生成 INF/CAT 驱动包,并创建或复用本机代码签名证书。新建证书主题为 BOX-2 Display Development,有效期五年,脚本使用它签署 CAT。

输出位置(相对 Windows 工程目录)内容
out\Host\Box2DisplayHost.exe抓屏、缩放、编码和 UDP 发送程序
out\Package\Box2Display.inf驱动安装说明
out\Package\Box2Display.dll间接显示驱动
out\Package\Box2Display.cat签名后的驱动目录文件
out\Package\Box2Display.cer本次开发签名使用的公开证书

看到 Build complete: 后再进入安装步骤。如果出现 MSBuild was not found,补装 VS 2022 C++ 工具;如果缺少 Inf2Cat.exesigntool.exe 或驱动工具集,检查 WDK、匹配 SDK 与 Visual Studio 集成。

安装驱动并开启扩展显示

windows\Box2Display 目录运行安装脚本:

.\install.ps1

脚本会请求管理员权限。也可以事先打开管理员 Windows PowerShell,再进入该目录运行,以便持续查看安装输出。安装会完成以下操作:

  1. 把开发证书导入本机“受信任的根证书颁发机构”和“受信任的发布者”。
  2. 通过 pnputil 添加并安装驱动包。
  3. 把主机程序复制到 C:\Program Files\BOX-2 Display
  4. 添加名为 BOX-2 Wi-Fi Display 的程序入站防火墙规则,脚本默认对所有网络配置文件生效。
  5. 为安装时的账户创建 Box2DisplayHost 登录计划任务,以最高权限启动主机,并立即运行一次。

签名范围:这里使用本机自签名开发证书,适用于开发与本机测试,不能等同于正式发行驱动。系统安全策略不同,导入证书后仍可能阻止安装或加载;如果被拦截,先记录具体错误并参照 Microsoft 驱动测试签名说明处理。公开分发需要符合 Microsoft 要求的正式签名,不把关闭 Secure Boot、内存完整性或防火墙作为通用安装步骤。

确认安装结果

  1. 在“设置”中依次打开“系统”和“显示”,找到新增显示器。
  2. 在“多显示器”中选择“扩展这些显示器”。该屏幕使用 480 × 360 横屏模式。
  3. 在设备管理器“显示适配器”中确认 BOX-2 Wi-Fi Display Adapter 存在,且没有错误标记。
  4. 确认 BOX-2 已联网,将一个小窗口拖到扩展屏,检查 LCD 是否同步显示。

安装脚本当前未显式检查 pnputil 的退出码,所以末尾出现“installed and host started”不能单独证明驱动已正常加载;以上实际检查才是完成标准。

开始串流与日常操作

打开 BOX-2 后,先等待启动测试图与联网。登录 Windows 时,计划任务启动主机;主机通过 UDP 5001 自动发现设备,完成握手后向 UDP 5000 发送图像,无需手动指定设备 IP。

  1. 在 Windows 显示设置中点击“标识”,确认 BOX-2 对应的屏幕。
  2. 拖动显示器示意图,令扩展屏位置符合你的桌面摆放。
  3. 把需要常驻的小窗口拖到扩展屏,按 4:3 小尺寸画面调整内容。
  4. 完成首次配置后可以断开 USB 数据连接;设备有电并与电脑网络互通即可继续显示。

M 键电源操作

供电方式长按中间 M 键 1.5 秒恢复使用
电池关闭 LCD,释放 SYS_POW 电源锁存,硬件关机再次长按 M 键开机
USB进入显示待机,USB 供电仍然存在短按一次 M 键唤醒,继续显示新画面

手动启动、停止与调试

在管理员 Windows PowerShell 中,可使用已安装的计划任务启动主机:

Start-ScheduledTask -TaskName Box2DisplayHost
Get-ScheduledTask -TaskName Box2DisplayHost | Select-Object TaskName,State

需要查看主机日志时,先让已有实例退出,等待进程结束后以前台详细模式运行:

& "$env:ProgramFiles\BOX-2 Display\Box2DisplayHost.exe" --stop
Get-Process -Name Box2DisplayHost -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
& "$env:ProgramFiles\BOX-2 Display\Box2DisplayHost.exe" --verbose

前台运行时按 Ctrl + C 停止;也可在另一个管理员窗口执行 --stop。主机有单实例保护,已有实例运行时再次启动会退出。停止主机会关闭它创建的虚拟显示设备,重新启动即可恢复;这些操作不会取消下次登录时的自动启动。

更新、清理与卸载

更新固件

拿到更新后的同一分支源码后,在 ESP-IDF 6.0.2 PowerShell 的工程根目录重新构建并烧录:

Set-Location "$env:USERPROFILE\source\esp32-box2-display"
idf.py -p COM7 build flash monitor

普通更新保留 NVS 的网络信息。若只需清理构建产物,在工程根目录运行 idf.py fullclean;该操作不会擦除设备 Flash。sdkconfig.defaults 与两个组件的 idf_component.yml 是工程文件,应保留。

更新 Windows 主机与驱动

Set-Location "$env:USERPROFILE\source\esp32-box2-display\windows\Box2Display"
.\build.ps1
.\install.ps1

安装脚本会停止旧主机、替换程序、更新任务并重新启动。修改驱动后需要重新生成并签名整个驱动包;仅替换 DLL 会使驱动包与目录签名不一致。

卸载前处理当前分支的脚本变量冲突

本教程核对的提交中,uninstall.ps1 使用了 $host 作为路径变量。PowerShell 不区分变量名大小写,它会与只读自动变量 $Host 冲突并导致卸载中止。先用文本编辑器打开脚本,将其中三处完整变量名 $host 改为 $hostExe,保存后再执行。如果后续版本已修正,直接运行即可。变量说明见 PowerShell 自动变量文档

Set-Location "$env:USERPROFILE\source\esp32-box2-display\windows\Box2Display"
notepad .\uninstall.ps1

关闭编辑器后,运行:

.\uninstall.ps1

脚本会申请管理员权限,停止主机并移除任务、程序防火墙规则、匹配的驱动包及安装目录。完成后检查设备管理器与任务计划程序,确认相关条目已移除。

卸载不会自动清除开发证书。确定不再使用后,可打开 certlm.msc,在本机“受信任的根证书颁发机构”和“受信任的发布者”中按主题与指纹确认并删除此次导入的 BOX-2 Display Development 证书;构建时在当前用户个人证书库创建的证书可通过 certmgr.msc 管理。只处理本项目对应的证书。

可选:生成单文件烧录镜像

用于离线烧录或留存固件版本时,可以把默认构建的三个镜像合并。在 ESP-IDF 6.0.2 PowerShell 中进入工程根目录,先确保 idf.py build 成功。

esptool --chip esp32s3 merge-bin `
  --flash-mode dio --flash-freq 80m --flash-size 16MB `
  -o .\build\esp32_box2_full.bin `
  0x0 .\build\bootloader\bootloader.bin `
  0x8000 .\build\partition_table\partition-table.bin `
  0x10000 .\build\esp32_box2.bin

反引号是 PowerShell 续行符,其后不要添加空格。上述地址对应项目默认分区;若改过分区或 Flash 配置,应先根据 build/flash_args 调整合并参数。

生成的 build\esp32_box2_full.bin 必须从地址 0x0 烧录,不能当作单独应用镜像写到 0x10000

esptool --chip esp32s3 --port COM7 --baud 460800 write-flash `
  --flash-mode dio --flash-freq 80m --flash-size 16MB `
  0x0 .\build\esp32_box2_full.bin

这个文件由构建产物合并而成,不包含从设备读取的 NVS 凭据,不能作为整片 Flash 数据备份。合并镜像写入的覆盖范围也包括镜像之间的填充区,应按需要重新配网。

按现象排查问题

第一步:用串口确定设备到了哪一步

在 ESP-IDF 终端与工程根目录执行:

idf.py -p COM7 monitor
日志或现象含义下一步
BOX2_PROVISION_READY正在等待首次配网发送 WIFI_SSID 与 WIFI_PASS 两行
BOX2_PASS_REJECTED密码未通过长度检查确认至少 8 个字符,重新发送密码行
反复出现 Wi-Fi disconnected; reconnecting连接未成功或持续掉线先检查 2.4 GHz、信号、认证方式和密码;需要改凭据时擦除后重新配网
BOX2_IP=...BOX2_UDP_READY=5000联网并开启视频接收服务转查 Windows 主机、显示驱动与网络互通
UDP stream client accepted主机与设备完成串流握手检查扩展模式、目标窗口与运行统计
屏幕变黑但设备仍供电可能进入 USB 显示待机短按中间 M 键唤醒

串口或烧录失败

  • 先换可传数据的 USB 线,重新确认端口号;进入下载模式后 COM 编号可能变化。
  • 关闭占用串口的其他软件。不能同时运行两个串口监视器。
  • 连接超时则尝试 BOOT + RESET 下载流程,再重新执行烧录。
  • 编译阶段报 IDF 版本冲突,回到 6.0.2 环境;组件下载失败则先检查构建电脑的网络。

Windows 中没有出现显示器

  1. 确认两个脚本构建、安装过程没有错误,特别查看 pnputil 的输出。
  2. 在任务计划程序确认 Box2DisplayHost 正在运行;必要时用管理员终端运行前文的 --verbose 调试命令。
  3. 查看设备管理器中的驱动状态,再到显示设置尝试“检测”和“扩展这些显示器”。
  4. 若出现签名或权限错误,记录错误码,检查开发证书、驱动包完整性和 Windows 驱动安装日志 C:\Windows\INF\setupapi.dev.log
  5. 若提示 No 480x360 monitor found.,确认虚拟屏已启用并保持 480 × 360 横屏模式。

Windows 有虚拟屏,BOX-2 一直等待画面

  1. 确认设备已输出 IP 和 UDP 就绪日志,主机程序仍在运行。
  2. 确认电脑与 BOX-2 接入可互通的局域网;排查访客网络、AP 隔离、VLAN 与 VPN 路由。
  3. 在 Windows 防火墙检查 BOX-2 Wi-Fi Display 规则是否启用,规则指向的程序路径是否正确。
  4. 检查 UDP 5000 / 5001 是否被安全软件或网络策略拦截。保留防火墙,针对本程序和局域网通信处理规则。
  5. 固件与主机应来自同一分支并一起更新,避免协议版本不匹配。

画面卡顿、跳帧或延迟

UDP 不重传缺失的画面片段,拥塞时会跳过帧。让 BOX-2 靠近接入点,使用干扰较少的 2.4 GHz 信道,减少无线中继与并行大流量传输。每两秒输出一次的 STREAM_STATS 能帮助定位瓶颈:

字段观察内容
rx_fps完整帧接收与解码速度
lcd_fps实际 LCD 成功刷新速度
drop_fps帧丢弃情况;并不等同于网络数据包丢包率
rx_mbps接收数据吞吐量
jpeg_ms / lcd_ms平均解码耗时 / LCD 绘制耗时

rx_fps 很低,优先检查主机与网络;若接收正常但 LCD 刷新低,结合解码与绘制耗时观察设备端。30 帧/秒是主机的目标上限,不是所有网络条件下的保证。

源码结构与参考资料

路径职责
sdkconfig.defaultsESP32-S3、Flash、PSRAM、网络与控制台默认配置
main/rgb_stream_main.c当前应用入口:配网、发现、收流、解码、显示与电源键
main/hardware_test_screen.*启动等待页面
driver/BOX-2 板级驱动:LCD、按键、电源、音频、运动传感器与存储
windows/Box2Display/Host/虚拟设备创建、抓屏、缩放、JPEG 编码与 UDP 发送
windows/Box2Display/Driver/Windows UMDF 间接显示驱动
build.ps1 / install.ps1 / uninstall.ps1Windows 端构建、安装更新与卸载脚本

固件实际参与编译的文件由 main/CMakeLists.txt 决定;仓库保留的其他硬件测试源文件不等于当前 Wi-Fi 显示应用的入口。driver 可作为 ESP-IDF 组件复用,通过 EXTRA_COMPONENT_DIRS 注册,并由应用组件声明 PRIV_REQUIRES driver

视频串流协议版本为 4,每个 UDP 数据报带 24 字节头部,JPEG 负载最多 1400 字节。固件只处理完整重组的 320 × 240 JPEG 帧,并优先显示最新完整帧;设备发现协议与视频串流握手分别实现。

内容依据分支提交 264e42dace5724d688ffa943bb69e8fef0560035 核对。命令与行为经过文档及源码检查;本教程未替代真实 BOX-2 硬件烧录、Windows 驱动加载或网络性能测试。