博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ROS串口编程学习笔记
阅读量:4083 次
发布时间:2019-05-25

本文共 2733 字,大约阅读时间需要 9 分钟。

 

摘自:

ROS串口编程学习笔记

 

2018-07-25 21:15:13 11172

分类专栏:

版权

串口是一种设备间常用的通讯接口,本文将记录如何在ROS上使用其提供的serial包进行串口通信。

首先,这里要引入一个名称为serial的包,这个包的安装命令为:

$ sudo apt-get install ros-
<版本号>
-serial

serial包的介绍:

接下来,创建一个自己的包,借助serial这个包来编写串口通信的代码。

1、创建一个包,依赖roscpp和serial两个包

$ catkin_create_pkg serial_port roscpp serial

2、在这个包的目录下面创建src目录,并在src目录中编写串口通信的代码

 
  1. //serial_port.cpp

  2. #include <ros/ros.h>

  3. #include <serial/serial.h>

  4. #include <iostream>

  5.  
  6. int main(int argc, char** argv)

  7. {

  8. ros::init(argc, argv, "serial_port");

  9. //创建句柄(虽然后面没用到这个句柄,但如果不创建,运行时进程会出错)

  10. ros::NodeHandle n;

  11.  
  12. //创建一个serial类

  13. serial::Serial sp;

  14. //创建timeout

  15. serial::Timeout to = serial::Timeout::simpleTimeout(100);

  16. //设置要打开的串口名称

  17. sp.setPort("/dev/ttyUSB0");

  18. //设置串口通信的波特率

  19. sp.setBaudrate(115200);

  20. //串口设置timeout

  21. sp.setTimeout(to);

  22.  
  23. try

  24. {

  25. //打开串口

  26. sp.open();

  27. }

  28. catch(serial::IOException& e)

  29. {

  30. ROS_ERROR_STREAM("Unable to open port.");

  31. return -1;

  32. }

  33.  
  34. //判断串口是否打开成功

  35. if(sp.isOpen())

  36. {

  37. ROS_INFO_STREAM("/dev/ttyUSB0 is opened.");

  38. }

  39. else

  40. {

  41. return -1;

  42. }

  43.  
  44. ros::Rate loop_rate(500);

  45. while(ros::ok())

  46. {

  47. //获取缓冲区内的字节数

  48. size_t n = sp.available();

  49. if(n!=0)

  50. {

  51. uint8_t buffer[1024];

  52. //读出数据

  53. n = sp.read(buffer, n);

  54.  
  55. for(int i=0; i<n; i++)

  56. {

  57. //16进制的方式打印到屏幕

  58. std::cout << std::hex << (buffer[i] & 0xff) << " ";

  59. }

  60. std::cout << std::endl;

  61. //把数据发送回去

  62. sp.write(buffer, n);

  63. }

  64. loop_rate.sleep();

  65. }

  66.  
  67. //关闭串口

  68. sp.close();

  69.  
  70. return 0;

  71. }

serial包的文档有对每个类和函数的解释,可以参考:

其中解释一下timeout的作用,在serial::Timeout结构体中有这么5个成员:

 
  1.  
  2. serial::Timeout::Timeout (

  3. uint32_t inter_byte_timeout_ = 0,

  4. uint32_t read_timeout_constant_ = 0,

  5. uint32_t read_timeout_multiplier_ = 0,

  6. uint32_t write_timeout_constant_ = 0,

  7. uint32_t write_timeout_multiplier_ = 0

  8. )

参考另一个大神的解释:(出处:)

“间隔超时=ReadIntervalTimeout

总超时   =   ReadTotalTimeoutMultiplier   * 字节数   +   ReadTotalTimeoutConstant 

串口读取事件分为两个阶段(我以Win32 API函数ReadFile读取串口过程来说明一下)

第一个阶段是:串口执行到ReadFile()函数时,串口还没有开始传输数据,所以串口缓冲区的第一个字节是没有装数据的,这时候总超时起作用,如果在总超时时间内没有进行串口数据的传输,ReadFile()函数就返回,当然 没有读取到任何数据。而且,间隔超时并没有起作用。
第二阶段:假设总超时为20秒,程序运行到ReadFile(),总超时开始从0 计时,如果在计时到达10秒时,串口开始了数据的传输,那么从接收的第一个字节开始,间隔超时就开始计时,假如间隔超时为1ms,那么在读取完第一个字节后,串口开始等待1ms,如果1ms之内接收到了第二个字节,就读取第二个字节,间隔超时重置为0并计时,等待第三个字节的到来,如果第三个字节到来的时间超过了1ms,那么ReadFile()函数立即返回,这时候总超时计时是没到20秒的。如果在20秒总计时时间结束之前,所有的数据都遵守数据间隔为1ms的约定并陆陆续续的到达串口缓冲区,那么就成功进行了一次串口传输和读取;如果20秒总计时时间到,串口还陆陆续续的有数据到达,即使遵守字节间隔为1ms的约定,ReadFile()函数也会立即返回,这时候总超时就起作用了。
总结起来,总超时在两种情况下起作用
第一:串口没进行数据传输,等待总超时时间那么长ReadFile()才返回。非正常数据传输
第二:数据太长,总超时设置太短,数据还没读取完就返回了。读取的数据是不全的
间隔超时触发是有条件的
第一:在总超时时间内。
第二:串口进行了数据的传输。
成功的进行一次串口数据的传输和读取,只有总超时和间隔超时相互参与配合才能完成”

3、修改CMakeList文件,添加选项

 
  1. add_executable(serial_port src/serial_port.cpp)

  2.  
  3. add_dependencies(serial_port ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

  4.  
  5. target_link_libraries(serial_port

  6. ${catkin_LIBRARIES}

  7. )

4、编译,运行即可看到结果(记得运行roscore和在工程目录下source devel/setup.bash)

你可能感兴趣的文章
React-Native高校图书馆APP
查看>>
react-navigation使用技巧
查看>>
使用React模仿大众点评
查看>>
营养品类商城
查看>>
微信小程序ofo-applet
查看>>
React Native未来导航者:react-navigation 使用详解
查看>>
ReactNative仿《ONE》APP
查看>>
iOS开发UI篇
查看>>
iOS开发UI篇
查看>>
iOS开发网络篇
查看>>
React Native实战系列第十四篇——购物车
查看>>
React Native FlatList的使用
查看>>
react-native-image-crop-picker学习
查看>>
React Native进行签名打包成Apk
查看>>
React Native相机 相册 定位 设备信息
查看>>
React Native中react-native-baidu-map的安装与使用
查看>>
React-Native Realm 基础用法总结
查看>>
React-Native Realm使用
查看>>
ReactNative 天气应用开发
查看>>
Reac-Native ScrollView回到顶部
查看>>