参考:http://blog.csdn.net/zyh821351004/article/details/50596171
参考:https://www.cnblogs.com/sopost/archive/2013/01/09/2853200.html
在机器人开发过程中,发现串口号经常变,每次插入不同的位置,串口号都可能会变化,如果每次都在程序中修改串口号就太麻烦 了, 因此重新给串口设置别名,利用第二个名字来在程序中读取,就可以避免这种问题了。
你在开发的过程中是否会出现 USB端口号会发生变化。 例如: 机器人底盘与雷达都是 ttyUSB* .其序号与接入的先后有关。 对于写好的launch每次修改对应接口是不是很麻法,或者每次得先插入一个再插另外一个。才能保证ttyUSB0 ttyUSB1. 但是如果你重启系统,说不定还是有问题出现。 不如将端口重映射到新的固定的名字,并且设置其权限为可读。 这样不管你的先后插入,符合对应id的硬件端口自动的映射到新定义的名字。
一. 单一的USB映射说明
lsusb 命令查看所有usb端口信息。
[cpp] view plain copy
- yhzhao@yhzhao:~$ lsusb
- Bus 002 Device 002: ID 0bda:0411 Realtek Semiconductor Corp.
- Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
- Bus 001 Device 004: ID 04f2:b48c Chicony Electronics Co., Ltd
- Bus 001 Device 009: ID 046d:c31c Logitech, Inc. Keyboard K120
- Bus 001 Device 010: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light
- Bus 001 Device 005: ID 0bda:5411 Realtek Semiconductor Corp.
- Bus 001 Device 008: ID 24ae:1100
- Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
udev的规则说明,可以参考博客说明:http://blog.csdn.net/cokewei/article/details/8281239
简单说明:
$kernel, %k:设备的内核设备名称,例如:sda、cdrom。
ID 10c4:ea60 表示usb设备的ID(这个ID由芯片制造商设置,可以唯一表示该设备)
10c4 usb_device_descriptor.idVendor
ea60 usb_device_descriptor.idProduct
依据这些信息,就可以简单的写udev规则了:rplidar.rules
sudo gedit /etc/udev/rules.d/rplidar.rules
[cpp] view plain copy
- # set the udev rule , make the device_port be fixed by rplidar
- #
- KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="rplidar"
创建生效后重新插拔USB。
用下面的命令就可以查看对应的映射结果了。
[cpp] view plain copy
- yhzhao@yhzhao:~$ ls -l /dev |grep ttyUSB
- lrwxrwxrwx 1 root root 7 Apr 14 13:18 rplidar -> ttyUSB0
- crwxrwxrwx 1 root uucp 188, 0 Apr 14 13:18 ttyUSB0
- yhzhao@yhzhao:~$
二. USB hub的多端口映射:
在实际调用时,发现485串口的ID与底盘的ID号相同,虽然不是同一个设备,因此如果还用上边的方法的话,会两个一起覆盖掉,导致底盘无法启动,因此需要比较这两个设备的不同点,然后添加规则的时候添加别的属性,使两者区分开来。
首先找到两个设备的串口号,比如分别是USB0和USB1,则调用以下指令来得到端口的详细信息
udevadm info --attribute-walk --path=/sys/bus/usb-serial/devices/ttyUSB0
udevadm info --attribute-walk --path=/sys/bus/usb-serial/devices/ttyUSB1
然后在得到的反馈信息中,找到ID号为0403 6001的两个设备,其中一个是指底盘,另一个就是485串口了
对比可以发现还是有很多参数不同的,这里直接用serial来区分的,底盘的规则是kobuki.rules,serial是kobuki开头的,因此写如下规则:
SUBSYSTEM=="tty",ATTRS{idVendor}=="0403",ATTRS{idProduct}=="6001",ATTRS{serial}=="kobuki*",MODE:"0666",SYMLINK+="kobuki"
485串口的规则是485-device.rules,serial是AL00E7W8,因此写如下规则:
SUBSYSTEM=="tty",ATTRS{idVendor}=="0403",ATTRS{idProduct}=="6001",ATTRS{serial}=="AL00E7W8",MODE:"0666",SYMLINK+="485-device"
这样就可以区分开两个ID相同的串口设备了!
当然还可以用其它方法来区别,比如有一种方法如下:
KERNEL=="ttyUSB*", KERNELS=="1-2.1", MODE:="0777",SYMLINK+="slamtec_base_"
KERNEL=="ttyUSB*", KERNELS=="1-2.2", MODE:="0777",SYMLINK+="slamtec_laser_"
关于具体的关键字含义:
键 含义
ACTION 一个时间活动的名字,比如add,当设备增加的时候
KERNEL 在内核里看到的设备名字,比如sd*表示任意SCSI磁盘设备
DEVPATH 内核设备录进,比如/devices/*
SUBSYSTEM 子系统名字,比如sound,net
BUS 总线的名字,比如IDE,USB
DRIVER 设备驱动的名字,比如ide-cdrom
ID 独立于内核名字的设备名字
SYSFS{ value} sysfs属性值,他可以表示任意
ENV{ key} 环境变量,可以表示任意
PROGRAM 可执行的外部程序,如果程序返回0值,该键则认为为真(true)
RESULT 上一个PROGRAM调用返回的标准输出。
NAME 根据这个规则创建的设备文件的文件名。注意:仅仅第一行的NAME描述是有效的,后面的均忽略。 如果你想使用使用两个以上的名字来访问一个设备的话,可以考虑SYMLINK键。
SYMLINK 根据规则创建的字符连接名
OWNER 设备文件的属组
GROUP 设备文件所在的组。
MODE 设备文件的权限,采用8进制
RUN 为设备而执行的程序列表
LABEL 在配置文件里为内部控制而采用的名字标签(下下面的GOTO服务)
GOTO 跳到匹配的规则(通过LABEL来标识),有点类似程序语言中的GOTO
IMPORT{ type} 导入一个文件或者一个程序执行后而生成的规则集到当前文件
WAIT_FOR_SYSFS 等待一个特定的设备文件的创建。主要是用作时序和依赖问题。
PTIONS 特定的选项: last_rule 对这类设备终端规则执行; ignore_device 忽略当前规则; ignore_remove 忽略接下来的并移走请求。all_partitions 为所有的磁盘分区创建设备文件。
我们给出一个列子来解释如何使用这些键。下面的例子来自Fedora Core 5系统的标准配置文件。
KERNEL=="*", OWNER="root" GROUP="root", MODE="0600"
KERNEL=="tty", NAME="%k", GROUP="tty", MODE="0666", OPTIONS="last_rule"
KERNEL=="scd[0-9]*", SYMLINK+="cdrom cdrom-%k"
KERNEL=="hd[a-z]", BUS=="ide", SYSFS{removable}=="1",
SYSFS{device/media}=="cdrom", SYMLINK+="cdrom cdrom-%k"
ACTION=="add", SUBSYSTEM=="scsi_device", RUN+="/sbin/modprobe sg"上面的例子给出了5个规则,每一个都是KERNEL或者ACTION键开头:
*第一个规则是缺省的,他匹配任意被内核识别到的设备,然后设定这些设备的属组是root,组是root,访问权限模式是0600(-rw——-)。这也是一个安全的缺省设置保证所有的设备在默认情况下只有root可以读写
*第二个规则也是比较典型的规则了。它匹配终端设备(tty),然后设置新的权限为0600,所在的组是tty。它也设置了一个特别的设备文件名:%K。在这里例子里,%k代表设备的内核名字。那也就意味着内核识别出这些设备是什么名字,就创建什么样的设备文件名。
*第三行开始的KERNEL==”scd[0-9]*”,表示 SCSI CD-ROM 驱动. 它创建一对设备符号连接:cdrom和cdrom-%k。
*第四行,开始的 KERNEL==”hd[a-z]“, 表示ATA CDROM驱动器。这个规则创建和上面的规则相同的符号连接。ATA CDROM驱动器需要sysfs值以来区别别的ATA设备,因为SCSI CDROM可以被内核唯一识别。.
*第五行以 ACTION==”add”开始,它告诉udev增加 /sbin/modprobe sg 到命令列表,当任意SCSI设备增加到系统后,这些命令将执行。其效果就是计算机应该会增加sg内核模块来侦测新的SCSI设备。
当然,上面仅仅是一小部分例子,如果你的系统采用了udev方式,那你应该可以看到更多的规则。如果你想修改设备的权限或者创建信的符号连接,那么你需要熟读这些规则,特别是要仔细注意你修改的那些与之相关的设备。
修改你的udev配置
在修改udev配置之前,我们一定要仔细,通常的考虑是:你最好不要修改系统预置的那些规则,特别不要指定影响非常广泛的配置,比如上面例子中的第一行。不正确的配置可能会导致严重的系统问题或者系统根本就无法这个正确的访问设备。
而我们正确的做法应该是在/etc/udev/rules.d/下创建一个信的规则文件。确定你给出的文件的后缀是rules文件名给出的数字序列应该比 标准配置文件高。比如,你可以创建一个名为99-my-udev.rules的规则文件。在你的规则文件中,你可以指定任何你想修改的配置,比如,假设你 修改修改floppy设备的所在组,还准备创建一个信的符号连接/dev/floppy,那你可以这么写:
KERNEL==”fd[0-9]*“, GROUP=“users“, SYMLINK+=“floppy“
有些发行版本,比如Fedora,采用了外部脚本来修改某些特定设备的属组,组关系和权限。因此上面的改动可能并不见得生效。如果你遇到了这个问题,你就需要跟踪和修改这个脚本来达到你的目的。或者你可以修改PROGRAM或RUN键的值来做到这点
summary:
1 "lsusb" find the pid and vid of USB instrument
2 gedit /etc/udev/rules.d/xx.rules document as the following (设置好以后,相当于设置了主机的USB口,设置好以后设备连接的USB口不能再变化)
我用的两个设备都是cp210x,pid和vid号都一样,然后,写了imu和lidar两个rules文件,两个文件里面分别写了如下,然后测试可以这么干
- KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="imu"
- KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="lidar"