在弄清楚udev的规则后(可参考我的前一篇博文),我们来看一下rikirobot的设备管理。
rikirobot的源码大家可以去github.com上搜索下载,有很多热心的网友已经将其打包上传,包括我们下面要讨论的setup文件,例如,
https://github.com/ykevin/rikirobot_setup
项目使用usb接口(包括USB串口)进行通讯时,我们都希望有个固定的设备名供程序调用。由于usb为即插即用设备,udev又是动态随机命名,所以,很难保证每次设备的名称都不变;因此,我们需要编写一些名称映射规则文件,对usb设备进行设置。
规则文件以.rules作为扩展名,规则配置路径一般在:
/etc/udev/rules.d/*
由于这些文件有优先级,所以一般在名称前面加上一个数字,系统加载时会按照数字进行排序,数字小的排前面(优先级别相对较高)。
规则格式示例: KERNEL=="ttyUSB*", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="xxxx", MODE:="0777", SYMLINK+="device_name" 其中 ATTRS{idVendor}=="xxxx" ATTRS{idProduct}=="xxxx"
从查询到的结果里进行配置。
下面我以我自己的通过ch340控制ROS小车进行通迅的实际配置为例进行说明。
通过查询命令
$ ls -l /dev |grep USB crw-rw---- 1 root dialout 188, 0 Jan 10 04:56 ttyUSB0 $ ls -l /dev |grep serial drwxr-xr-x 4 root root 80 Jan 10 04:56 serial
可以找到我们的串口设备;
$ lsusb Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 004: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter Bus 001 Device 003: ID 248a:8367 Maxxter USB2.0 Hub Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
再细看一下,
$lsusb -v
可以查到所有的usb设备的详细信息,其中包括要找的ch340,内容如下
Bus 001 Device 004: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x1a86 QinHeng Electronics
idProduct 0x7523 HL-340 USB-Serial adapter
bcdDevice 2.64
iManufacturer 0
iProduct 2
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0027
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 98mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 1
bInterfaceProtocol 2
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
熟悉usb的朋友一下子就可以看出,这个usb的通信协议是bulk,其中endpoint为0x8?为IN,0x0?的为Out,例如,用户的通迅是EP2-0x82(IN)/0x02(out),还有一个中断传输端口EP1-0x81(IN)。具体想了解usb规范的可以到这里去看一下,
USB 2.0 Specification | USB-IF
设备的idVendor和idProduct分别为,
idVendor 0x1a86 QinHeng Electronics idProduct 0x7523 HL-340 USB-Serial adapter
我们就可以建立一个规则,文件名称为 /etc/udev/rules.d/58-riki.rules
与ch340相对应的规则为内容为 KERNEL=="ttyUSB?", SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE="0777" SYMLINK+="rikibase"
规则文件配置完成后,执行命令 service udev reload service udev restart 然后就可以在/dev下找到我们想看的rikibase了(如果不行的话,就重启吧), ls /dev/rikibase
然后在ros相应的launch文件中,配置的参数就可以固定为 /dev/rikibase了。ros的launch文件 serial_port参数定义为/dev/rikibase可以实现对相应硬件的调用设置,而不必插拔usb后在查看到底是那个端口号反复修改launch文件。
全部开源riki底盘树莓派中系统使用的规则配置示例及说明:
58-riki.rulesKERNEL=="ttyACM?", SUBSYSTEM=="tty", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0483", MODE="0777" SYMLINK+="rikibase"
KERNEL=="ttyACM?", SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE="0777" SYMLINK+="rikiarm_left"
KERNEL=="ttyACM?", SUBSYSTEM=="tty", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0046", MODE="0777" SYMLINK+="rikiarm_right"
KERNEL=="ttyUSB?", SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="0001", MODE="0777" SYMLINK+="rikilidar"
KERNEL=="ttyUSB?", SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE="0777" SYMLINK+="rikibase"
KERNEL=="ttyUSB?", SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0777" SYMLINK+="rikibase"
KERNEL=="ttyUSB?", SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", MODE="0777" SYMLINK+="rikilidar"
558-orbbec-usb.rules
# Make primesense device mount with writing permissions (default is read only for unknown devices)
SUBSYSTEM=="usb", ATTR{idProduct}=="0401", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0402", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0403", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0404", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0405", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0406", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0407", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0408", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="0409", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
SUBSYSTEM=="usb", ATTR{idProduct}=="040a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="ubuntu", GROUP:="video"
49-teensy.rules
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789A]?", ENV{MTP_NO_PROBE}="1"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789ABCD]?", MODE:="0666"
KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", MODE:="0666"
10-local-rpi.rules
SUBSYSTEM=="vchiq", GROUP="video", MODE="0660"
解释:
vchiq是个什么子系统?
VCHIQ is a command interface between the running Linux kernel and peripherals (among other things) in the VideoCore silicon. /dev/vchiq provides generic userspace access to those commands for use by (at minimum) the camera and audio subsystems as well. It's a decently dangerous interface to expose to random programs, hence the somewhat restrictive permissions by default.
40-scratch.rulesATTRS{idVendor}=="0694", ATTRS{idProduct}=="0003", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev"
99-com.rules
SUBSYSTEM=="input", GROUP="input", MODE="0660"
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
SUBSYSTEM=="bcm2835-gpiomem", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\
chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;\
chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio;\
chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath\
'"
KERNEL=="ttyAMA[01]", PROGRAM="/bin/sh -c '\
ALIASES=/proc/device-tree/aliases; \
if cmp -s $ALIASES/uart0 $ALIASES/serial0; then \
echo 0;\
elif cmp -s $ALIASES/uart0 $ALIASES/serial1; then \
echo 1; \
else \
exit 1; \
fi\
'", SYMLINK+="serial%c"
本文结束