树莓派4B基于OpenCV的C++环境的串口通信

忙里偷闲只为摸鱼~

第二次积分赛我们队选择了飞控,我负责图像方面,我先简要说明一下该题中树莓派所需要的功能:用OpenCV图像处理进行巡线,同时识别红圆和绿圆。然后就是关键的一步,树莓派与飞控的通信

树莓派将处理好的数据(为巡线所确定的点、圆心等)发送给飞控,飞控端再通过PID等算法对接收到的数据进行解析,从而控制飞行器的运动。在这里就需要树莓派与飞控通信,我们选择了简单的uart串口通信

本以为会比较顺利,因为树莓派在网上有很多的开源教程,我也找了许多的教程一步步试,费尽了许多周折将串口配置好、下载的库也配置好,程序也编译通过,但是和CH340连电脑,就。。。啥也没显示。。。:-)此时我的心是悲剧的。

最终找了学长才解决的问题。(这里先感谢srh学长!!学长也超级耐心!)

目前网上找到的大多数关于树莓派 4B 串口的文章,包括B站树小悉的视频教程,大都是将硬件串口(ttyAMA0,UART0)设置为主串口(Serial0)关闭蓝牙,这个做法针对树莓派3B及以下是必须的,因为本身串口不够用。但对树莓派 4B 来说并不需要,因为有额外 4 个串口可以利用,默认配置好的硬件串口和miniUART 可以保留设置。我参考了网上的教程,但就是无法串口收发数据,不过使用树莓派的这额外四个串口就成功了。(串口相关的具体可以查看这篇官方文档,用浏览器自带网页搜索“serial”可以较快查到)

然后,在配置WiringPi库的时候也遇到了版本加入OpenCV环境等问题。

话不多说,先分享我的配置过程,也为了让后来人少走一些弯路。这里先默认读者已经会使用树莓派的基本操作,且已经装好OpenCV的C++环境,并且会cmake编译运行。如果不会,请参考这篇文章。下面的操作也是基于这篇文章的基础之上的。

一、串口配置

1. 展示所有串口命令

命令行输入:

dtoverlay -a | grep uart

2. 查看串口信息

我们来康康树莓派4B额外4个串口之一的uart2,命令行输入:

dtoverlay -h uart2

可以查看到配置信息:

相关信息会展现 GPIOs 与树莓派4B额外的4个UART 串口的分配:0-3 对应 UART2, 4-7 对应 UART3,8-11 对应 UART 4,以及 12-15 对应UART 5。

3. 开启串口 UART2-5

执行编辑 config.txt 命令,命令行输入:

sudo nano /boot/config.txt

拉到文件结尾,添加如下代码:

dtoverlay=uart2
dtoverlay=uart3
dtoverlay=uart4
dtoverlay=uart5

按ctrl+x,然后保存,enter退出。

重启树莓派,命令行输入:

sudo reboot

重启后查看串口是否打开,命令行输入:

ls /dev/ttyAMA*

可以看到几个串口都打开了。(AMA1-4分别对应UART2-5)

4、串口接线

接下来我们看看这4个串口分别对应于树莓派的哪些引脚:

UART0: GPIO14 = TXD0 -> ttyAMA0     GPIO15 = RXD0 -> ttyAMA0
UART2: GPIO0  = TXD2 -> ttyAMA1     GPIO1  = RXD2 -> ttyAMA1
UART3: GPIO4  = TXD3 -> ttyAMA2     GPIO5  = RXD3 -> ttyAMA2
UART4: GPIO8  = TXD4 -> ttyAMA3     GPIO9  = RXD4 -> ttyAMA3
UART5: GPIO12 = TXD5 -> ttyAMA4     GPIO13 = RXD5 -> ttyAMA4

我们这里使用UART2,可以看到 GPIO0对应于uart2的TX(引脚编号为27),GPIO1对应于uart2的RX(引脚编号为28)。故将CH340的TX和28号引脚相连,RX引脚和27号引脚相连,GND和30号引脚相连共地。

二、安装WiringPi库

什么?WiringPi?你确定是WiringPi?不是WritingPi?没错,你的英语没问题,就是WiringPi。。:-)

WiringPi是一个用C语言编写的树莓派软件包,可用于树莓派GPIO引脚控制、串口通信、SPI通信及I2C通信等功能。其官方网址为http://wiringpi.com。我们可以看到这个库作者已经停止维护了。我们在这里用的是串口通信,故只用它的wiringSerial库。

安装WiringPi,我试了试若直接apt-get install wiringpi的话不行,只能卡在2.32版本,而树莓派4B要树莓派2.52版本才行。(有可能是我安装的问题)好在 GitHub 仓库上的有源码可以下载。

在命令行输入:

git clone https://github.com/WiringPi/WiringPi.git
cd ~/wiringPi
./build

这样我们就在wiringPi目录下安装好了WiringPi库。

我们查看一下版本,在命令行中输入:

gpio -v

可以看到版本号是 2.7。在树莓派4B上可以正常使用。

三、在OpenCV环境中cmakeWiringPi库

cmake原来OpenCV程序时(OpenCV相关目录下已创建cpp文件test_opencv.cpp)需要在CMakeLists.txt里写如下代码:(如不懂,具体还是请看这篇文章

cmake_minimum_required(VERSION 2.6)
project(test_opencv)
find_package(OpenCV REQUIRED)
add_executable(test_opencv test_opencv.cpp)
target_link_libraries(test_opencv ${OpenCV_LIBS})

要加入WiringPi库,只需在CMakeLists.txt里写:

cmake_minimum_required(VERSION 2.6)
add_definitions( -lwiringPi  )
project(test_opencv)
find_package(OpenCV REQUIRED)
find_library(WIRINGPI_LIBRARIES NAMES wiringPi)
add_executable(test_opencv test_opencv.cpp)
target_link_libraries(test_opencv ${OpenCV_LIBS})
target_link_libraries(test_opencv ${WIRINGPI_LIBRARIES}  -lpthread)    //-lpthread后缀要写上,否则编译会不通过

四、cpp代码编写

使用WiringPi库来串口通信要包含头文件:

#include <wiringPi.h>
#include <wiringSerial.h>

其实用wiringSerial.h就可以了。

在main函数里写串口初始化代码:

wiringPiSetup();

然后打开串口2,并设一个变量fd来作为串口文件描述符:

int fd =serialOpen("/dev/ttyAMA1",9600);   //这里波特率设置为9600

发送函数:

//写在while里,每隔3秒发送一个hello world!!
serialPrintf(fd,"hello world!!\n");   
delay(3000);

功能类似于printf,可以同时发送多个字符串。

注:

以上发送函数只是把数据推送到发送缓冲区里,不会等待串口发送完成。后续程序如果要用到用到串口返回数据应当要考虑到串口传输时间。并且最好等之前的数据全部发送完成后再发送新数据,否则可能会出问题,这也要考虑到串口发送数据的时间,可能需要等待。

我们在项目的目录下输入:

cmake .
make
./test_opencv

可以编译并运行程序了!编译也没有报错!

这样电脑端可以在串口调试助手上接收到数据。图中是vofa上接收数据情况。

当然,我们串口通信是为了发送图像处理后的数据,并和我们的飞控通信,在树莓派端,我们需要将需要的数据打包成帧,建立一个自己写的通信协议,发送给飞控,飞控端解析这些数据帧就可以了。这些会在第二次积分赛总结里写,不过估计要鸽到暑假了。:-)

参考文章:

https://blog.csdn.net/weixin_40796925/article/details/107907991