樹莓派4B基於OpenCV的C++環境的串列埠通訊

QHWYX發表於2022-04-09

第二次積分賽我們隊選擇了飛控,我負責影像方面,我先簡要說明一下該題中樹莓派所需要的功能:用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

相關文章