树莓派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