rosserial进行串口通信
newsun-boki Lv3

rosserial进行串口通信

串口通信

基础介绍

  • 用于两个模块之间传输数据,是我们最常用的数据通信方式之一。包括单片机之间的通信,单片机与工控机之间的通信,单片机与外设模块之间的通信等等。
  • 由于 CPU 与接口之间按并行方式传输,接口与外设之间按串行方式传输,因此,在串行接口中,必须要有 “ 接收移位寄存器 “ (串→并)和 “ 发送移位寄存器 “ (并→串).
  • 串口通讯是以高低电平为传输媒介,一位一位的传输,这一点是后面需要时刻牢记的。

具体发送的过程

  • 波特率:传输速度的参数。指的是信号被调制以后在单位时间内的变化,即单位时间内载波参数变化的次数。如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps。

  • 数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包的数据位数,标准值是6、7和8位。比如,当我想发送一个uint8的整数,它就刚好能够完整发送。

  • 我们只需要记住的是,串口一次只能发送8位二进制数,所以要发送和接受的数据是以8位二进制数的数组存储的,如下:

    1
    uint8_t buffer[12]

产生的问题

那既然我们一次只能发8位数字,那对于float这种32位的数字要怎么发呢?

答案是把它拆开为4个8位数字发出去。

1
2
3
4
5
6
float x = 3.5
unsigned int f1 = (*((unsigned int *)&(x)));
for (int i = 0; i < 4; ++i){ //4个字节的float x转换为buffer中的4位
uint8_t tmp = (f1 >> (8 * i)) & 0xff;
buffer[i] = tmp;
}
  • 看上去拆开的方法显然没有我们想的那么简单。
  • 我们知道float的数据存储类型是比较复杂的,有尾数幂数等等巴拉巴拉。当我们把其拆分的时候会遇到许多问题,为了更好的运算,我们将其转换为无符号32位整数,即unsigned int
  • 仔细看上面的代码 unsigned int f1 = (*((unsigned int *)&(x))),你可能会感觉很疑惑这行代码,但你细看或许就明白了。
  • 实际上是把x的指针类型强行从float变成unsigned int。这样的好处是其在内存中的值不会变,那个二进制数还是那些,而我们直接使用类型转换实际上会改变其在内存中的值。

同样再收到消息的时候我们也需要相同的操作

1
2
3
4
5
6
unsigned int hor = 0;
for(int i = 3; i >= 0 ; i--){ //vertical pitch
hor += buffer[i];
if(i) hor <<= 8;
}
yaw = (*((float*)&hor));

Ubuntu中串口通讯

Ubuntu下的串口助手cutecom可以快速帮你查看是否有串口信号传入你的ubuntu。(虽然我之前并没有用过,使用方法也可以请教电控组成员或自行谷歌,如果不大行就算了吧)

  • 安装cutecom并打开

    1
    2
    sudo apt-get install cutecom
    sudo cutecom
  • 查看连接你电脑的串口信息

    1
    ls -l /dev | grep ttyU* #/dev路径下通常包含了所连外设,故要查看串口需要在这里进行查看,而grep是正则化,只查看名字是ttyU开头的文件

    或者

    1
    dmesg | grep ttyS* #网上看到的,不知道行不行

    你可以通过拔插串口看哪一个设备改变从而确定设备名称。

    详细的你可以看我随便找的一个链接:https://blog.csdn.net/maizousidemao/article/details/103236666

Ros中的串口通讯

Ros使用rosserial包作为串口通信的方式

  1. 首先下载rosserial
1
sudo apt-get install ros-melodic-serial
  • 进入安装位置确认是否安装成功
1
roscd serial
  • 若是成功则能够进入位置
1
/opt/ros/melodic/share/serial
  1. 然后创造工作空间,参照这个博客

  2. 创造功能包并编写以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//serial_port.cpp
#include <ros/ros.h>
#include <serial/serial.h>
#include <iostream>

int main(int argc, char** argv)
{
ros::init(argc, argv, "serial_port");
//创建句柄(虽然后面没用到这个句柄,但如果不创建,运行时进程会出错)
ros::NodeHandle n;

//创建一个serial类
serial::Serial sp;
//创建timeout
serial::Timeout to = serial::Timeout::simpleTimeout(100);
//设置要打开的串口名称
sp.setPort("/dev/ttyUSB0");
//设置串口通信的波特率
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/ttyUSB0 is opened.");
}
else
{
return -1;
}

ros::Rate loop_rate(500);
while(ros::ok())
{
//获取缓冲区内的字节数
size_t n = sp.available();
if(n!=0)
{
uint8_t buffer[1024];
//读出数据
n = sp.read(buffer, n);

for(int i=0; i<n; i++)
{
//16进制的方式打印到屏幕
std::cout << std::hex << (buffer[i] & 0xff) << " ";
}
std::cout << std::endl;
//把数据发送回去
sp.write(buffer, n);
}
loop_rate.sleep();
}

//关闭串口
sp.close();

return 0;
}
  • CmakeLists如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
cmake_minimum_required(VERSION 2.8.3)
project(serial_com)

## Compile as C++11, supported in ROS Kinetic and newer
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(catkin REQUIRED)
include_directories(
include ${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS}
)


find_package(catkin REQUIRED COMPONENTS
OpenCV REQUIRED
roscpp
rospy
std_msgs
serial
)



## Declare a C++ library
# add_library(${PROJECT_NAME}
# src/${PROJECT_NAME}/serial_com.cpp
# )


add_executable(stm_com
serial_port.cpp
)
add_dependencies(stm_com ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(stm_com
${catkin_LIBRARIES}
${OpenCV_LIBRARIES}
)

  1. 运行roscore,运行节点看是否能打开串口。如果提示Unable to open port,是由于权限不够引起的,进行如下操作
    创建文件:(若使用的是ttyACM将ttyusb替换即可)
1
sudo gedit /etc/udev/rules.d/70-ttyusb.rules

在打开的文件中添加

1
KERNEL=="ttyUSB[0-9]*", MODE="0666"

或者直接更改权限

1
sudo chmod 777 /dev/ttyUSB*#后面这个是你的串口设备
  • Post title:rosserial进行串口通信
  • Post author:newsun-boki
  • Create time:2021-11-02 01:56:47
  • Post link:https://github.com/newsun-boki2021/11/02/rosserial/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.