我有一个 Arduino,有时会绑定到/dev/ttyUSB0
,有时会绑定到/dev/ttyUSB1
,使我的脚本失败。
我不想枚举我的设备可能位于的所有可能性,但我宁愿将其绑定在静态的地方,例如/dev/arduino
。
我该如何实现这一目标?
答案1
根据建议,您可以添加一些 udev 规则。我编辑了/etc/udev/rules.d/10-local.rules
包含:
ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="my_uart"
您可以通过运行来检查设备的变量
udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)
您可以阅读更深入的指南http://www.reactivated.net/writing_udev_rules.html
答案2
上面的规则语法可能适用于某些发行版,但不适用于我的(Raspbian)。由于我从未找到一个文档来解释所有的来龙去脉,所以我编写了自己的文档,以便找到这里。这就是它的归结。
找出 ttyUSB 上有什么:
dmesg | grep ttyUSB
列出设备的所有属性:
udevadm info --name=/dev/ttyUSBx --attribute-walk
(当然,用您的设备编号而不是 x)。挑选一个唯一的标识符集,例如idVendor + idProduct。如果您有多个具有相同 idVendor 和 idProduct 的设备,您可能还需要 SerialNumber。每个设备的序列号应该是唯一的。
创建一个文件
/etc/udev/rules.d/99-usb-serial.rules
,其中包含类似以下行的内容:SUBSYSTEM=="tty", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678", SYMLINK+="your_device_name"
假设您不需要那里的序列号,当然还有您在步骤 2 中找到的 idVendor 和 idProduct 的号码。
加载新规则:
sudo udevadm trigger
2021 年 7 月 6 日编辑:虽然这在当时(2015 年)、Archlinux 以及其他发行版上运行良好,但您可能需要第一的如果自动加载失败,请执行
sudo udevadm control --reload
。验证发生了什么:
ls -l /dev/your_device_name
将显示符号链接所指向的 ttyUSB 编号。如果是
/dev/ttyUSB1
,则验证谁拥有它以及它属于哪个组:ls -l /dev/ttyUSB1
然后只是为了好玩:
udevadm test -a -p $(udevadm info -q path -n /dev/your_device_name)
答案3
多个相同 USB 设备问题
我有一个带有四个摄像头的树莓派。我拍了照片,将fswebcam
相机识别为/dev/video0
......video3
有时相机是video0
、vide02
、video4
但video6
我们现在可以忘记这一点。
我需要一个持久的 ID 来识别摄像机编号,以便video0
始终是同一台摄像机,因为我为图片添加了标题。不幸的是,这并不可靠地发生 - 在启动时,相机被枚举为video0
..video3
但并不总是以相同的方式。
这些相机都具有相同的 ID 和序列号。
这个问题的解决方案涉及 udev 规则,但其中也存在很多问题。
如果您发出命令
udevadm info –attribute-walk –path=/dev/video0
你会得到一堆输出,但最重要的是
KERNEL=”video0”, SUBSYSTEM=”video4linux” and KERNELS=”1:1.2.4:1.0”.
KERNELS 位是 USB 集线器端口。对于四个摄像头,其中有四个 - 它们在重新启动时不会更改,但video{x}
与端口相关联。可能改变。
因此,我们需要一个 udev 规则将视频编号绑定到 USB 集线器端口 - 类似于:
KERNEL==”video0”,SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0”,SYMLINK+=”camera0”
看起来很简单 – 使用以下命令访问相机
fswebcam –d $realpath /dev/camera0
但它不起作用 - 如果您将其放入 udev 规则中并且系统已将 video0(启动时)分配给不同的端口,则 udev 规则将被忽略。符号链接/dev/camera0
基本上是这样说的no such device
。方一。
我们想要的是将符号链接绑定到 USB 集线器地址,而不是数字video{x}
。它需要一个Python程序。
第一步是运行
fswebcam –d /dev/video${x} tst.jpg
1 到 8之间。每次通话后的x
的存在tst.jpg
标识该视频号码上是否有摄像头。由此创建一个活动视频编号的列表。我的经验是,它要么0,1,2,3
适用0,2,4,6
于我使用过的相机。
其他人当然可以使用不同的过程来构建此列表。
然后对于列表中的每个视频编号运行
udevadm info –attribute-walk –path=/dev/videox > dd
KERNELS= line
并从中提取dd
.在此过程中,您最终会得到相机的 USB 端口地址列表。对此列表进行排序,以便在下一步中始终以相同的顺序处理它。将此称为“地址列表”。
再次运行该udevadm … > dd
程序并制作一个看起来像这样的列表
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camerax”. Call this the “video list”.
现在逐步浏览地址列表 - 对于每个条目,从视频列表中查找相应的条目。创建一个看起来像行集合的新列表,例如
KERNEL==”video0”, SUBSYSTEM=”video4linux”,KERNELS==”1:1.2.4:1.0 ”,SYMLINK+=”camera2”
x(符号链接号)被地址列表中的序列号替换。
现在您有了一个有效的 udev 规则。与 USB 集线器地址绑定的符号链接,无论启动时分配给该端口的视频编号是什么。
将最终列表写入文件/etc/udev/rules.d/cam.rules
。运行udevadm trigger
激活它,工作就完成了。 /dev/camera2
无论视频编号如何,都将是同一台摄像机(USB 端口)。
答案4
我还能够在 中找到一个独特的设备/dev/serial/by-id
。我还没有尝试重新启动,但该目录中的文件只是指向相应设备文件 ( ttyACM[0-9]
) 的链接。
我在 Raspberry Pi 上运行 arch linux,但我只是通过执行find
包含“Arduino”的文件名来偶然发现它们。我的 python 程序运行良好,使用这些文件作为从我的 Arduino 读取/写入数据的设备(到目前为止,单个 Pi 上有两个)。