ROS串口通信实验
文章目录前言一、前言硬件英伟达NX环境Ubuntu18.04ROS Melodic一、安装cutecomsudo apt-get install cutecomsudo cutecom安装ROS串口sudo apt-get install ros-melodic-serial安装完后在一个新的终端里输入roscd serial/如果能够正常cd到/opt/ros/melodic/share/ser
前言
硬件
英伟达NX
USB转串口模块
环境
Ubuntu18.04
ROS Melodic
串口助手
一、安装ROS串口驱动
安装ROS串口
sudo apt-get install ros-melodic-serial
安装完后在一个新的终端里输入
roscd serial/
如果能够正常cd到/opt/ros/melodic/share/serial
,说明串口驱动安装成功.
二、新建软件包编译
mkdir -p ~/serial_ws/src
cd ~/serial_ws/src/
catkin_init_workspace
cd ~/serial_ws/
catkin_make
echo "source ~/serial_ws/devel/setup.bash">>~/.bashrc
source ~/.bashrc
echo $ROS_PACKAGE_PATH
新建功能包:
cd ~/serial_ws/src/
catkin_create_pkg serial_test roscpp rospy std_msgs serial
三、实现串口收发
主要的逻辑是在serial_test1节点接收串口数据并解析,然后通过话题发布给serial_test2。在serial_test2中发布需要发送的数据给serial_test1进行订阅,然后在serial_test1中发送。
待续。。
自定义消息
参考:https://mbot1.blog.csdn.net/article/details/124212863?spm=1001.2014.3001.5502
cd ~/serial_ws/src/serial_test
mkdir msg
cd msg
gedit serial_test.msg
填入如下:
std_msgs/Header header
float32 test1
int32 test2
编辑package.xml文件
gedit ~/serial_ws/src/serial_test/package.xml
确保它包含以下两行且没有被注释。如果没有,添加进去:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
修改serial_test包下面的CMakeLists.txt文件:
gedit ~/serial_ws/src/serial_test/CMakeLists.txt
将message_generation
添加到COMPONENTS列表中
添加运行时依赖关系CATKIN_DEPENDS message_runtime
添加msg文件
add_message_files(
FILES
serial_test.msg
)
确保generate_messages()函数被调用
generate_messages(
DEPENDENCIES
std_msgs
)
添加完后无需编译在终端使用rosmsg show serial_test
即可查看是否添加成功
编辑serial_test1代码
cd ~/serial_ws/src/serial_test/src
gedit serial_test1.cpp
填入以下代码并保存
serial_test1的代码的主要功能是订阅serial_test2节点中发布的话题,并将话题内容通过串口发出,同时接收串口数据并通过话题发布出去
//serial_port.cpp
#include <ros/ros.h>
#include <serial/serial.h>
#include <iostream>
#include <string>
#include <cstring>
#include "serial_test/serial_test.h"
//创建一个serial类
serial::Serial sp;
ros::Publisher pub_serial_RX;
ros::Subscriber sub_serial_TX;
serial_test::serial_test serial_RX;
void serial_tx_cb(const serial_test::serial_testConstPtr &serial_tx_ptr)
{
uint8_t buffer[2];
buffer[1]=serial_tx_ptr->test1;
buffer[2]=serial_tx_ptr->test2;
sp.write(buffer,sizeof(buffer));
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "serial_test1");
//创建句柄
ros::NodeHandle n;
//创建timeout
sub_serial_TX=n.subscribe("/serial_test_TX", 10, &serial_tx_cb);
pub_serial_RX = n.advertise<serial_test::serial_test>("/serial_test_RX", 10);
serial::Timeout to = serial::Timeout::simpleTimeout(100);
//设置要打开的串口名称
sp.setPort("/dev/ttyTHS0");
//设置串口通信的波特率
sp.setBaudrate(115200);
//串口设置timeout
sp.setTimeout(to);
try
{
//打开串口
sp.open();
}
catch(serial::IOException& e)
{
ROS_ERROR_STREAM("Unable to open port.");
return -1;
}
//判断串口是否打开成功
if(sp.isOpen())
{
ROS_INFO_STREAM("/dev/ttyTHS0 is opened.");
}
else
{
return -1;
}
ros::Rate loop_rate(50);
while(ros::ok())
{
//获取缓冲区内的字节数
size_t n = sp.available();
uint8_t buffer[n];
if(n!=0)
{
printf("n=%ld\n",n);
sp.read(buffer, n);
if(buffer[0]==0xfd&&buffer[1]==0x88)
{
serial_RX.test1=buffer[2];
serial_RX.test2=buffer[3];
printf("test1=%02x,test1=%02x\n",serial_RX.test1,serial_RX.test2);
}
}
pub_serial_RX.publish(serial_RX);
ros::spinOnce();
loop_rate.sleep();
}
//关闭串口
sp.close();
return 0;
}
然后编辑serial_test2.cpp
cd ~/serial_ws/src/serial_test/src
gedit serial_test2.cpp
填入以下内容
serial_test2的主要作用是订阅serial_test1接受到的串口数据并打印出来,同时将需要串口发送的数据通过话题发布出去
//serial_port.cpp
#include <ros/ros.h>
#include <serial/serial.h>
#include <iostream>
#include <string>
#include <cstring>
#include "serial_test/serial_test.h"
ros::Publisher pub_serial_TX;
ros::Subscriber sub_serial_RX;
serial_test::serial_test serial_TX;
void serial_rx_cb(const serial_test::serial_testConstPtr &serial_rx_ptr)
{
printf("test1=%02x,test1=%02x\n",serial_rx_ptr->test1,serial_rx_ptr->test2);
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "serial_test2");
//创建句柄
ros::NodeHandle n;
//创建timeout
sub_serial_RX=n.subscribe("/serial_test_RX", 10, &serial_rx_cb);
pub_serial_TX = n.advertise<serial_test::serial_test>("/serial_test_TX", 10);
ros::Rate loop_rate(50);
while(ros::ok())
{
serial_TX.test1++;
serial_TX.test2++;
pub_serial_TX.publish(serial_TX);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
修改~/serial_ws/src/serial_test/
下的CmakeLists.txt.
cd ~/serial_ws/src/serial_test/
gedit CMakeLists.txt
在文件的最后加上:
add_executable(serial_test1 src/serial_test1.cpp)
add_dependencies(serial_test1 ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(serial_test1 ${catkin_LIBRARIES})
add_executable(serial_test2 src/serial_test2.cpp)
add_dependencies(serial_test2 ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(serial_test2 ${catkin_LIBRARIES})
编译
cd ~/serial_ws
catkin_make
. ~/serial_ws/devel/setup.bash
四、测试
NX上有三个板载串口,我这里使用ttyTHS0.
对应的引脚如下:
其中ttyTHS0的TX对应上图引脚8,RX对应上图引脚10.
将ttyTHS0的TX接到USB转串口模块的RX,将tyTHS0的RX接到USB转串口模块的TX,同时将USB转串口模块的GND接到NX上的GND,我这里接的是6号引脚.
接好线后,将USB转串口模块接到电脑的串口助手上.
可以在NX的终端上查看一下串口的端口号
cd /dev
ls
ttyTHS开头的就是板载串口
在NX上先执行如下命令赋予权限,否则无法打开串口
sudo chmod 777 /dev/ttyTHS0
然后运行节点
roscore
先打开一个终端,执行:
rosrun serial_test serial_test1
再打开一个终端,执行:
rosrun serial_test serial_test2
执行
rqt_graph
如下:
打开串口助手,连接上USB转串口模块,设置波特率为115200,数据位8位,无校验位,1位停止位,无流控,打开串口后,以16进制显示,可以看到串口收到递增的数据,
然后向NX发送一些数据进行测试,以16进制发送,发送数据头为0xfd和0x88,例如以16进制发送数据fd885678,可以在运行serial_test2的终端中显示接收到的数据
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)