前言

众所周知,学习SLAM单凭仿真是绝对不行的,因此入手一款合适的SLAM机器人是再好不过的选择。但是淘宝上的SLAM学习套装不是巨贵就是功能单一,无法进行后续的扩展(如加装机械臂等等)。因此,为了锻炼自己的动手能力(这个借口看起来比较积极,能掩盖没钱的尴尬....),准备从零打造一款ROS机器人的地盘。

本文为本系列第一篇,主要讲解如何实现上下位机的通信的通信协议。在驱动板的选择上我们可以选择Arduino或者STM32开发板。虽然Arduino开发更简单下且与ROS更加兼容。但是由于Arduino的版权问题,我们在工业生产中很难直接使用Arduino。因此为了后续的工业化开发,本项目首选的是STM32F103C8T6开发板。

关于ROS与控制板的通信,这时候就要提起rosserial,这个是ROS提供一种嵌入式节点和运行在主控PC上的ros master通信方式,是的在嵌入式节点上编写,运行ros节点成为可能,主要用于转接IO和各类传感器,运行底层控制算法。但是目前关于结合STM32微控制器使用ROS机器人操作系统的信息其实网上使用的还是很少,因此对于新手来说,进行STM32+rosserial开发ROS并不是最好的选择。这里我选用的是通过串口通信来实现STM32下位机与linux上位机的通信过程。

串口介绍

UART(英文全称:Universal Asynchronous Receiver / Transmitter)是一种异步全双工串行通信协议,由Tx和Rx两根数据线组成,因为没有参考时钟信号,所以通信的上方必须约定串口波特率,数据位宽,奇偶校验位,停止位等配置参数,从而按照相同的速率进行通信。

stm32的串口数据传输都是以字节为单位,但有些特殊的数据类型,如float speed= 12.1,是如何通过串口发送给上位机的呢?

我们知道浮点型float数据类型占用4个字节,实际在内存当中speed = 0x4141999a,stm32中访问speed时,知道speed时浮点型数据,所以一次性读取四个字节,并按照浮点型的鼠标表示规定,将speed转化为十进制的可读数据12.1。

如果我们从串口接收到四个字节的数据{0x41, 0x41, 0x99, 0x9a},如何将这四个字节的数据转换为float型呢? 

如果我们直令float speed= 0x4141999a这样是肯定不行的,下面是我的验证结果。这是我们在串口通讯中经常遇到的问题,如果数据包括了浮点型数据,我们可以通过共用体来解决。

我们定义一个共用体Data,其中包括float型的数据speed,和四字节数组s[]。我们使float speed = 12.1我们查看s【4】的数值,下面使测试程序。

#include <iostream>
using namespace std;

typedef union
{
	float speed;
	unsigned char s[4];
}Union_test;

typedef struct st
{
	float speed2;
}Struct_test;

int main(void) {
	float speed = 12.1;
	Union_test Data;
	Struct_test Data_2;
	Data.speed = 12.1;
	Data_2 = *(Struct_test*)(&(Data.s));
	return 0;
}

监视结果如下:

同样我们用结构体做同样的实验,将数组s【4】={0x00, 0x8F, 0xF6, 0xE4}的首地址s【0】强制转换赋值给结构体Data_2,最后打印的结果也是12.1

这里我们发现一个奇怪的现象,原本的0x9a994141数据实际储存的时候变成了9aH, 99H, 41H, 41H,这是因为在计算机系统中使用了小端储存,众所周知,在计算机系统中,对于超过一个字节的数据,在计算机中的储存要跨越字节,一些机器在储存器中按照从最低为有效字节到最高为有效字的顺序存储对象,而另一些机器则是相反。前一种机器被称为小端存储,后一种被称为大端存储。在这里,经过验证,ubuntu,windows和stm32都是小端存储类型。因此无需担心数据存储问题。

通过上面监视结果,我们发现已经实现了float型数据四字节与char型数组数据类型的转换。在下一章,我们将通过这个共用体数据转换实现ROS与stm32的通信实现。