一、配置 WSL2 挂载ESP32
1.1 安装 usbipd-win 工具
usbipd-win
是 Windows11 上的 USB/IP 服务器,用于共享 USB 设备给 WSL2:
打开 PowerShell(管理员模式),执行以下命令安装(需联网):
1
| winget install --interactive --exact dorssel.usbipd-win
|
安装完成后,重启电脑(确保服务生效)。
1.2 查找 ESP32 的 USB 设备 ID
将 ESP32 通过 USB 连接到电脑,在 PowerShell 中执行以下命令,列出所有 USB 设备:
输出示例(需找到 ESP32 对应的设备,通常带有COM3等字样):
1
2
| BUSID VID:PID DEVICE STATE
1-3 10c4:ea60 Silicon Labs CP210x USB to UART Bridge (COM3) Not shared
|
记录 BUSID
(如 1-3
)和设备名称,后续用于转发。
1.3 将 USB 设备附加到 WSL2
在 PowerShell 中执行以下命令,将 ESP32 转发到 WSL2(替换 BUSID
为实际值,Ubuntu-22.04
为你的 WSL 发行版名称):
1
2
3
4
5
6
7
| # 在管理员 PowerShell 中
# 1. 绑定设备以供共享
usbipd bind --busid 1-3
# 2. 将已绑定的设备附加到 WSL
usbipd attach --wsl --busid 1-3
|
1.4 验证 WSL2 已识别 USB 设备
打开 WSL2 终端(如 Ubuntu),执行以下命令验证设备是否被识别:
1
2
3
| ls /dev/ttyUSB*
# 或者
ls /dev/ttyACM*
|
2.1 配置Docker环境
Dockerfile
这个文件告诉 Docker 如何构建镜像。它会从一个基础 Python 镜像开始,然后安装 PlatformIO Core 和一些必要的工具。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| # 使用本地已有的 Alpine 镜像
FROM alpine:3.22
# 设置环境变量
ENV PLATFORMIO_CORE_DIR=/root/.platformio
# 安装 Python3、pip 和其他必要软件,包括glibc兼容性支持
RUN apk add --no-cache \
python3 \
py3-pip \
git \
gcc \
g++ \
musl-dev \
linux-headers \
eudev-dev \
gcompat \
libstdc++ \
libgcc \
bash \
&& ln -sf python3 /usr/bin/python
# 升级 pip 并安装 PlatformIO
RUN python3 -m pip install --upgrade pip --break-system-packages && \
python3 -m pip install platformio --break-system-packages
# 创建 udev 规则目录和 PlatformIO udev 规则文件
RUN mkdir -p /etc/udev/rules.d && \
echo '# PlatformIO udev rules' > /etc/udev/rules.d/99-platformio-udev.rules && \
echo 'SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE="0666", GROUP="dialout"' >> /etc/udev/rules.d/99-platformio-udev.rules && \
echo 'SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE="0666", GROUP="dialout"' >> /etc/udev/rules.d/99-platformio-udev.rules && \
echo 'SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="0666", GROUP="dialout"' >> /etc/udev/rules.d/99-platformio-udev.rules && \
echo 'SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="0666", GROUP="dialout"' >> /etc/udev/rules.d/99-platformio-udev.rules
# 设置工作目录
WORKDIR /root
# 保持容器运行
CMD [ "sleep", "infinity" ]
|
docker-compose.yml
这个文件可以让我们更方便地管理容器的配置和启动。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| services:
platformio-dev:
# 使用当前目录下的 Dockerfile 进行构建
build: .
# 容器的名字,方便识别
container_name: platformio-dev
# 保持容器持续运行
command: sleep infinity
# 将当前目录下的 project 文件夹挂载到容器的工作区
# 这样你在 Windows 中修改的代码会实时同步到容器里
volumes:
- ./project:/root/project
# 关键!给予容器访问主机 USB 设备的特权
privileged: true
|
2.2 常用命令
初始化项目
1
2
3
4
5
6
7
8
9
10
11
12
| # 替换 "esp32-3s-devkitc-1" 为你具体的开发板型号
pio project init --board esp32-3s-devkitc-1
# 初始化后项目结构
project/
├── .pio/ # PlatformIO构建输出
├── include/ # 头文件
├── lib/ # 库文件
├── src/
│ ├── main.cpp # 主程序文件(Blink示例)
│ └── serial_test.cpp.bak # 串口测试程序(备用)
├── test/ # 测试文件
└── platformio.ini # PlatformIO配置文件
|
编译项目
1
| docker exec -it platformio-dev sh -c "cd ./project && pio run"
|
上传固件
1
2
3
| # 串口编号
let port = "/dev/ttyACM0"
docker exec -it platformio-dev sh -c "cd ./project && pio run -t upload --upload-port $port"
|
监视串口
1
2
| # 注意波特率一定要正确否则监视输出会乱码
docker exec -it platformio-dev sh -c "cd ./project && pio device monitor --port $port --baud 115200"
|
2.3 其他脚本
自检脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| #!/bin/bash
# ESP32串口诊断脚本
# 用于诊断串口连接和权限问题
echo "=== ESP32串口诊断工具 ==="
echo
# 检查系统串口设备
echo "1. 系统串口设备列表:"
ls -la /dev/tty* | grep -E "(USB|ACM)"
echo
# 检查容器内的串口设备
echo "2. 容器内串口设备列表:"
docker exec -it pio-dev-container sh -c "ls -la /dev/tty* | grep -E '(USB|ACM)'"
echo
# 检查USB设备
echo "3. USB设备列表:"
docker exec -it pio-dev-container sh -c "lsusb"
echo
# 检查PlatformIO设备列表
echo "4. PlatformIO检测到的设备:"
docker exec -it pio-dev-container sh -c "pio device list"
echo
# 检查udev规则
echo "5. udev规则状态:"
docker exec -it pio-dev-container sh -c "ls -la /etc/udev/rules.d/"
echo
echo "=== 诊断完成 ==="
echo
echo "常见问题解决方案:"
echo "1. 如果设备未显示,请检查:"
echo " - ESP32是否正确连接到USB端口"
echo " - USB线缆是否支持数据传输"
echo " - 容器是否以特权模式运行"
echo
echo "2. 如果权限被拒绝,请检查:"
echo " - 用户是否在dialout组中"
echo " - udev规则是否正确加载"
echo
echo "3. 如果串口乱码,请检查:"
echo " - 波特率是否匹配 (115200)"
echo " - 串口参数设置是否正确"
|
部署脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
| #!/bin/bash
# ESP32统一管理平台
# 集成编译、上传、监视功能于一体
# 显示帮助信息
show_help() {
echo "ESP32统一管理平台"
echo "用法: $0 [命令] [参数]"
echo ""
echo "命令:"
echo " build 编译ESP32项目"
echo " upload [串口] 上传固件到ESP32(默认串口: /dev/ttyACM0)"
echo " monitor [串口] 监视串口输出(默认串口: /dev/ttyACM0)"
echo " all [串口] 编译、上传、监视一条龙(默认串口: /dev/ttyACM0)"
echo " help 显示此帮助信息"
echo ""
echo "示例:"
echo " $0 build # 仅编译"
echo " $0 upload # 上传到默认串口"
echo " $0 upload /dev/ttyUSB0 # 上传到指定串口"
echo " $0 monitor # 监视默认串口"
echo " $0 all # 编译、上传、监视默认串口"
echo " $0 all /dev/ttyUSB0 # 编译、上传、监视指定串口"
}
# 获取串口参数,如果没有提供则使用默认值
get_port() {
if [ -z "$1" ]; then
echo "/dev/ttyACM0"
else
echo "$1"
fi
}
# 编译项目
build_project() {
echo "=========================================="
echo "开始编译ESP32项目..."
echo "=========================================="
docker exec -it platformio-dev sh -c "cd ./project && pio run"
if [ $? -eq 0 ]; then
echo "=========================================="
echo "✅ 编译完成!"
echo "=========================================="
return 0
else
echo "=========================================="
echo "❌ 编译失败!"
echo "=========================================="
return 1
fi
}
# 上传固件
upload_firmware() {
local port=$(get_port "$1")
echo "=========================================="
echo "准备上传固件到ESP32..."
echo "使用串口: $port"
echo "=========================================="
docker exec -it platformio-dev sh -c "cd ./project && pio run -t upload --upload-port $port"
if [ $? -eq 0 ]; then
echo "=========================================="
echo "✅ 上传完成!"
echo "=========================================="
return 0
else
echo "=========================================="
echo "❌ 上传失败!请检查ESP32连接和串口设置"
echo "=========================================="
return 1
fi
}
# 监视串口
monitor_serial() {
local port=$(get_port "$1")
echo "=========================================="
echo "开始监视串口输出..."
echo "使用串口: $port"
echo "波特率: 115200"
echo "按 Ctrl+C 退出监视"
echo "=========================================="
# 在容器内执行监视命令,工作目录已经是 /root/workspace/github/esp32-docker-project
docker exec -it platformio-dev sh -c "cd ./project && pio device monitor --port $port --baud 115200"
}
# 一条龙操作:编译、上传、监视
all_in_one() {
local port=$(get_port "$1")
echo "🚀 启动ESP32开发一条龙模式!"
echo "目标串口: $port"
echo ""
# 第一步:编译
if ! build_project; then
echo "编译失败,停止后续操作"
exit 1
fi
echo ""
echo "等待2秒后继续..."
sleep 2
# 第二步:上传
if ! upload_firmware "$port"; then
echo "上传失败,停止后续操作"
exit 1
fi
echo ""
echo "等待3秒后开始监视..."
sleep 3
# 第三步:监视
monitor_serial "$port"
}
# 主程序
main() {
# 检查是否提供了命令
if [ $# -eq 0 ]; then
show_help
exit 0
fi
case "$1" in
"build")
build_project
;;
"upload")
upload_firmware "$2"
;;
"monitor")
monitor_serial "$2"
;;
"all")
all_in_one "$2"
;;
"help"|"-h"|"--help")
show_help
;;
*)
echo "❌ 未知命令: $1"
echo ""
show_help
exit 1
;;
esac
}
# 运行主程序
main "$@"
|