串口通讯
首先,需要下载serial库。
sudo apt install ros-noetic-serial
serial功能包主要用于进行通信,可以进行串口通信。
插上外部的串口设备,并查看串口设备的串口名称。
查看端口号:
ll /dev
一般都是ttyUSB0
之后在工作空间创建功能包
catkin_create_pkg serial_pkg roscpp rospy serial std_msgs
也可以直接在CMakeLists.txt文件中添加serial库
再创建一个serial_practice.cpp文件
内容:
#include "ros/ros.h"
#include "serial/serial.h"
#include "string"
serial::Serial ser;
int main(int argc,char** argv)
{
ros::init(argc,argv,"prac_usb");
ros::NodeHandle n;
std::string serial_port_;
int baudrate_;
n.param<std::string>("serial_port",serial_port_,"/dev/ttyUSB0");
n.param<int>("baudrate",baudrate_,115200);
ros::Rate loop(1);
try
{
ser.setPort(serial_port_);
ser.setBaudrate(baudrate_);
serial::Timeout to = serial::Timeout::simpleTimeout(1000);//超时等待
ser.setTimeout(to);
ser.open();
}
catch(serial::IOException& e)
{
ROS_ERROR_STREAM("Unable to open port!!!");
return -1;
}
if(ser.isOpen())
{
ROS_INFO_STREAM("Serial Port initialized...");
}
else{
ROS_INFO_STREAM("initialization failed!!!");
return -1;
}
ROS_INFO("ready");
std::string re;
while(ros::ok())
{
ser.write("1");
re = ser.read(1);
ROS_INFO("123:--- : %s",re.c_str());
loop.sleep();
}
return 0;
}
串口配置主要是以下代码:
ser.setPort(serial_port_);//设置串口 名字
ser.setBaudrate(baudrate_);//设置波特率
serial::Timeout to = serial::Timeout::simpleTimeout(1000);//超时等待
ser.setTimeout(to);
ser.open();//打开串口
上面的文件即是向串口ttyUSB0写入,又是读取串口的数据
以上代码部分完成
但一般这个时候运行不会成功,需要修改文件的权限(改为:可读可写),即:
sudo chmod 666 /dev/ttyUSB0
之后即可正常运行
注意:在CMakeLists.txt文件中还需要添加:
add_executable(serial_practice src/serial_practice.cpp)
target_link_libraries(serial_practice
${catkin_LIBRARIES}
)
这两行代码目的是将cpp文件改成可执行文件,并与库做链接
文件权限解释
sudo chmod 666 /dev/ttyUSB0
如果你疑惑上面代码的意思,这里会进行解释。
666有3位,从左向右:
- 第一个“6”:设置文件所有者访问权限
- 第二个“6”:设置群组访问权限
- 第三个“6”:设置设置其他人访问权限
单独一个“6”的意思:“6”的二进制是1 1 0,有三位,从左向右分别代表可读、可写、可执行文件
“1”表示肯定
“0”表示否定
即“6”的意思是:可读、可写、但不是可执行的文件(这个文件不能运行)
那么“666”的意思是:这个文件对于 文件所有者、群组访问、其他人访问,都是可读可写的。
参考:
上面的文章写的非常详细,想详细了解的可以看一看。
永久打开串口的可读写权限
在正常情况下,你每重新插拔一次串口设备,要想重新读取设备,都是需要重新修改权限的,如果你认为这种方式比较麻烦,那么可以进行下面的操作,之后就可以直接读取,不需要再修改文件的权限。
首先,在终端输入以下代码:
sudo gedit /etc/udev/rules.d/60-serial-usb.rules
注意:60-serial-usb的名字是可以随便起的,没有这个文件会自动创建这个文件。
在打开的文件中添加以下代码:
KERNEL==“ttyUSB[0-5]*”, MODE=“0666”
以上代码意思:将ttyUSB0到ttyUSB5都修改成可读可写文件。
注意:插入的串口号都是从ttyUSB0开始按照顺序进行编的,一般不会超过6个外部串口设备。
之后保存并关闭这个文件,并拔掉串口外设。
在终端输入以下代码,即“udev”:
sudo service udev reload
sudo service udev restart
之后,再次插入外部的串口设备,就可以直接进行读取了,而不需要在修改权限。
固定串口的编号(给USB口起别名)
当你连接多个外部的串口的设备时,由于插入的先后顺序不同,可能就会变成ttyUSB0或者ttyUSB1,这样,就需要修改你的文件里的路径,很麻烦。
采用本方法,就不需要注意先后顺序,只是,你的串口外设每次插入的口都是固定的那个口即可。
这种方法相当于给你主设备的每一个USB口,起别名。
首先,插入一个串口外设,在终端输入以下代码:
udevadm info --attribute-walk --name=/dev/ttyUSB0
在设备信息中找到ATTRS{devpath}字段,比如ATTRS{devpath}==“11”,如下图所示:
也可以换下面这种方式,在终端输入:
ls /sys/class/tty/ttyUSB* -l
记住“11”这个编号,这个编号会有所不同,以自己的设备为准。
在/etc/udev/rules.d目录下添加串口规则文件,比如:70-usb.rules(文件名字随便起),即:在终端输入。
sudo gedit /etc/udev/rules.d/70-usb.rules
在打开的文件中写入:
KERNEL=="tty*", ATTRS{devpath}=="11",MODE="0666", GROUP:="dialout", SYMLINK+="r1"
注意:在SYMLINK+=“r1”,r1是任意起的,这个相当于一个名称。
保存并关闭上面打开的文件。
拔掉外部设备,重新启动“udev”,即:
sudo service udev reload
sudo service udev restart
之后,重新插入外部串口设备,注意,插入的口还是之前的口,在终端中输入:
ls -l /dev | grep ttyUSB*
即r1就是你主设备这个USB口的名称。只要这个USB口插入了外部串口设备,就会有一个这样的别名。
在需要读取串口的文件中,修改成下面这样:
假如你有两个串口外设A和B,在读取A时用了上面的串口,那么,只要你每次都是将A插入主设备这个USB口,那么就不用管先后顺序。
之后,可以利用上面这种方式,给主设备的每一个串口起别名。
参考链接:
其他常用命令
查看外设:
ll /dev
查看对应的 USB 端口信息,获取设备id号:
lsusb
仅查看串口外设:
ls -l /dev | grep ttyUSB*
udev规则:
上面的文章讲的非常详细。
创建读取串口的文件: