项目概览:把 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;直接使用其他版本可能导致依赖解析失败。
- 打开 乐鑫 Windows 安装指南,安装 ESP-IDF Installation Manager(EIM)。
- 在 EIM 中选择自定义安装,明确选择 v6.0.2,并安装 ESP32-S3 所需工具。安装器负责准备 Python、CMake、Ninja 和编译工具链。
- 安装完成后打开该版本对应的 ESP-IDF PowerShell 环境。也可以在已安装的 6.0.2 目录运行
export.ps1激活环境。 - 执行下面的版本检查,确认输出包含
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.txt、sdkconfig.defaults、driver、main 和 windows。以下固件命令都在这个根目录执行。
配置并编译 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_dev 和 espressif/esp_new_jpeg,生成配置、依赖锁文件和构建目录,然后编译 Bootloader、分区表与应用。等待终端出现 Project build complete。
| 构建产物 | 默认烧录地址 | 用途 |
|---|---|---|
build/bootloader/bootloader.bin | 0x0 | 启动加载程序 |
build/partition_table/partition-table.bin | 0x8000 | 分区表 |
build/esp32_box2.bin | 0x10000 | Wi-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.exe、signtool.exe 或驱动工具集,检查 WDK、匹配 SDK 与 Visual Studio 集成。
安装驱动并开启扩展显示
在 windows\Box2Display 目录运行安装脚本:
.\install.ps1
脚本会请求管理员权限。也可以事先打开管理员 Windows PowerShell,再进入该目录运行,以便持续查看安装输出。安装会完成以下操作:
- 把开发证书导入本机“受信任的根证书颁发机构”和“受信任的发布者”。
- 通过
pnputil添加并安装驱动包。 - 把主机程序复制到
C:\Program Files\BOX-2 Display。 - 添加名为
BOX-2 Wi-Fi Display的程序入站防火墙规则,脚本默认对所有网络配置文件生效。 - 为安装时的账户创建
Box2DisplayHost登录计划任务,以最高权限启动主机,并立即运行一次。
签名范围:这里使用本机自签名开发证书,适用于开发与本机测试,不能等同于正式发行驱动。系统安全策略不同,导入证书后仍可能阻止安装或加载;如果被拦截,先记录具体错误并参照 Microsoft 驱动测试签名说明处理。公开分发需要符合 Microsoft 要求的正式签名,不把关闭 Secure Boot、内存完整性或防火墙作为通用安装步骤。
确认安装结果
- 在“设置”中依次打开“系统”和“显示”,找到新增显示器。
- 在“多显示器”中选择“扩展这些显示器”。该屏幕使用 480 × 360 横屏模式。
- 在设备管理器“显示适配器”中确认 BOX-2 Wi-Fi Display Adapter 存在,且没有错误标记。
- 确认 BOX-2 已联网,将一个小窗口拖到扩展屏,检查 LCD 是否同步显示。
安装脚本当前未显式检查 pnputil 的退出码,所以末尾出现“installed and host started”不能单独证明驱动已正常加载;以上实际检查才是完成标准。
开始串流与日常操作
打开 BOX-2 后,先等待启动测试图与联网。登录 Windows 时,计划任务启动主机;主机通过 UDP 5001 自动发现设备,完成握手后向 UDP 5000 发送图像,无需手动指定设备 IP。
- 在 Windows 显示设置中点击“标识”,确认 BOX-2 对应的屏幕。
- 拖动显示器示意图,令扩展屏位置符合你的桌面摆放。
- 把需要常驻的小窗口拖到扩展屏,按 4:3 小尺寸画面调整内容。
- 完成首次配置后可以断开 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 中没有出现显示器
- 确认两个脚本构建、安装过程没有错误,特别查看
pnputil的输出。 - 在任务计划程序确认
Box2DisplayHost正在运行;必要时用管理员终端运行前文的--verbose调试命令。 - 查看设备管理器中的驱动状态,再到显示设置尝试“检测”和“扩展这些显示器”。
- 若出现签名或权限错误,记录错误码,检查开发证书、驱动包完整性和 Windows 驱动安装日志
C:\Windows\INF\setupapi.dev.log。 - 若提示
No 480x360 monitor found.,确认虚拟屏已启用并保持 480 × 360 横屏模式。
Windows 有虚拟屏,BOX-2 一直等待画面
- 确认设备已输出 IP 和 UDP 就绪日志,主机程序仍在运行。
- 确认电脑与 BOX-2 接入可互通的局域网;排查访客网络、AP 隔离、VLAN 与 VPN 路由。
- 在 Windows 防火墙检查
BOX-2 Wi-Fi Display规则是否启用,规则指向的程序路径是否正确。 - 检查 UDP 5000 / 5001 是否被安全软件或网络策略拦截。保留防火墙,针对本程序和局域网通信处理规则。
- 固件与主机应来自同一分支并一起更新,避免协议版本不匹配。
画面卡顿、跳帧或延迟
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.defaults | ESP32-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.ps1 | Windows 端构建、安装更新与卸载脚本 |
固件实际参与编译的文件由 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 驱动加载或网络性能测试。