Ubuntu udev规则实战:精确区分相同ID的CH340 USB串口设备
当你在机器人开发或嵌入式项目中同时使用多个CH340芯片的USB转串口设备时,会遇到一个棘手的问题:这些设备拥有完全相同的厂商ID和产品ID(1a86:7523),传统的绑定方法失效了。本文将带你深入解决这个实际问题,提供从诊断到实施的完整方案。
1. 问题诊断与设备信息获取
首先我们需要确认设备确实无法通过常规方法区分。插入两个CH340设备后,执行lsusb命令会看到类似输出:
Bus 001 Device 003: ID 1a86:7523 QinHeng Electronics CH340 serial converter Bus 001 Device 004: ID 1a86:7523 QinHeng Electronics CH340 serial converter此时系统会为它们分配ttyUSB0和ttyUSB1,但顺序可能随插拔变化。我们需要更深入的设备信息来区分它们。
使用udevadm命令获取设备详细信息:
udevadm info --attribute-walk --path=$(udevadm info --query=path --name=/dev/ttyUSB0)关键是要找到设备的物理连接路径信息。典型输出中会包含类似这样的片段:
KERNELS=="1-1.2:1.0" ATTRS{idVendor}=="1a86" ATTRS{idProduct}=="7523"其中KERNELS值"1-1.2:1.0"反映了设备在USB拓扑中的物理位置,这是区分相同ID设备的关键。
2. 基于物理端口的区分方案
2.1 确定KERNELS值
对每个CH340设备重复执行以下命令,记录各自的KERNELS值:
for dev in /dev/ttyUSB*; do echo "Device $dev:" udevadm info --attribute-walk --path=$(udevadm info --query=path --name=$dev) | grep -m1 KERNELS done示例输出:
Device /dev/ttyUSB0: KERNELS=="1-1.2:1.0" Device /dev/ttyUSB1: KERNELS=="1-1.3:1.0"2.2 创建udev规则
在/etc/udev/rules.d/目录下创建规则文件,例如99-ch340.rules:
sudo nano /etc/udev/rules.d/99-ch340.rules添加以下内容(根据实际查得的KERNELS值修改):
# 第一个CH340设备 KERNEL=="ttyUSB*", KERNELS=="1-1.2:1.0", MODE:="0666", SYMLINK+="ch340_device_a" # 第二个CH340设备 KERNEL=="ttyUSB*", KERNELS=="1-1.3:1.0", MODE:="0666", SYMLINK+="ch340_device_b"注意:
MODE:="0666"设置了设备权限,确保普通用户可读写
2.3 应用规则并验证
执行以下命令使新规则生效:
sudo udevadm control --reload-rules sudo udevadm trigger重新插拔设备后,检查绑定结果:
ls -l /dev/ch340_*正确输出应显示符号链接已创建:
lrwxrwxrwx 1 root root 7 Aug 25 14:30 /dev/ch340_device_a -> ttyUSB0 lrwxrwxrwx 1 root root 7 Aug 25 14:30 /dev/ch340_device_b -> ttyUSB13. 基于序列号的替代方案(如果可用)
部分CH340设备可能具有唯一序列号,这是更可靠的区分方式。检查序列号:
udevadm info -a -n /dev/ttyUSB0 | grep '{serial}' | head -n1如果输出类似ATTRS{serial}=="12345678",则可使用以下规则格式:
KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{serial}=="12345678", SYMLINK+="ch340_serial_a"4. 方案对比与选择指南
| 区分方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| KERNELS | 所有设备都支持 | USB端口变化需重新配置 | 设备固定连接同一USB端口 |
| 序列号 | 与物理连接无关 | 部分设备可能无序列号 | 设备具有唯一序列号 |
| 物理标签 | 直观易管理 | 需人工标记设备 | 设备数量少且可物理区分 |
决策流程建议:
- 首先检查设备是否有唯一序列号
- 若无序列号,采用KERNELS方案
- 对设备物理端口做标记(如贴标签对应规则中的名称)
5. 实际应用与问题排查
在Python代码中使用绑定后的设备:
import serial # 使用符号链接名称而非ttyUSBx ser = serial.Serial('/dev/ch340_device_a', 115200, timeout=1)常见问题及解决方法:
问题1:规则未生效
- 检查规则文件后缀是否为
.rules - 确认执行了
udevadm control --reload-rules - 查看系统日志:
journalctl -f插入设备时观察输出
问题2:权限不足
- 确保规则中包含
MODE:="0666" - 或将用户加入
dialout组:sudo usermod -aG dialout $USER
问题3:KERNELS值变化
- 保持设备插入同一物理USB端口
- 考虑改用USB集线器固定端口分配
对于需要更高可靠性的生产环境,可以考虑以下增强措施:
- 编写udev规则检查脚本,定期验证设备绑定状态
- 在应用代码中添加设备存在性检查
- 使用设备心跳包机制确认通信正常
通过这套方法,你可以彻底解决相同ID的CH340设备识别问题,构建稳定的开发和生产环境。