Razor項目所感(上)


簡單的說下我的Razor四旋翼飛行器項目,還沒做完,要暫時擱一擱,就先總結一下。
此項目基於Raspberry Pi上的linux平台進行開發,現仍在開發中。項目地址:
https://github.com/sanwave/Razor

當初設計的功能基本都已實現,主要如下:拍攝照片;獲取精確授時並校正系統時間,樹莓派掉電后是不保存時間的;記錄照片的EXIF信息,主要是地理位置和時間;錄取/停止錄取視頻,這樣設計是因為錄制視頻時不能同時航拍;獲取飛行器當前的姿態,使用到陀螺儀、加速度計、電子羅盤和氣壓計,這方面數據處理還有些問題,不過數據是穩定的,除了氣壓計的數據還沒搞到;開啟視頻實時監控,通過外置供電USB無線網卡自建WiFi熱點和監控主機輸出視頻流。大概就只有這些。本來是准備拿這貨拿來作畢業設計的,不過現在看來可能不太適合。

簡單介紹下我的硬件配置:機架用的是小號風火輪,X240,¥95,后面感覺空間確實太小了,無法施展上述全部功能,稍不注意就有可能被槳打到,所以下次做時一定要買個大號的;電調用的是好盈飛騰10A,電機是新西達的A1510,這兩件和機架是之前老師挑的,我們覺得還不錯,就沒有換,共計(50+50)*4;電池買了塊好點的,酷點3S 2600mAh 25C,120吧;主控樹莓派,外加攝像頭,270+220;姿態傳感器GY-86模塊,80+;GPS模塊,80+;USB無線網卡,50+;nRF無線模塊,四五塊;前面的已經有1300+了,加上其他零零碎碎的至少有1.6k+。做到最后我才發現,樹莓派的硬件PWM只有一個,而軟件PWM遠遠不能滿足要求,而且跑起來CPU占用率很高,照此情形,勢必要再加一塊板子了。確實是之前的疏忽,以后再開項目一定要進行嚴密論證。

軟件到目前為止全部基於linux,這樣就可以放心的使用C++,較C清爽許多,干凈利落,不過Linux下的C++和當初學的C++還有有一點點差別的,因為最開始我用的C,移植過來后IO代碼就沒有改,繼續用着C的stdio庫,同時引用C++的iostream庫時就要報錯,由於不是很必要,我就沒有深究下去。當然,要和硬件打交道,還需要專門的硬件開發庫,我用的是WiringPi,Gordons開發的一個易用友好的庫,仿Arduino風格,上手很簡單。芯片提供商Broadcom也提供了bcm2835庫,有興趣可以去下載。

下面細說下各個功能的實現。

 

自建熱點

購買無線網卡時只顧着考慮和樹莓派的兼容性了,就買了個之前借攀攀用的TP的一款小白,用時才發現構建WiFi Direct沒那么簡單,資料非常少,而且這款不支持。自建AP熱點也只是支持軟件模擬AP,在Windows7 下使用竟然要驅動!國內網站上關於樹莓派的資料還很少,我只好翻牆到外面飽覽E文,幾經曲折,才成功建成AP熱點。具體方法見:http://ncloy.co.uk/blog/?p=593

 

拍攝照片

這個功能實現相對簡單,只是要用樹莓派的攝像頭拍照,必須使用其專用程序,由於官方並未開發GUI程序,所以我們只能用命令行,慢慢就習慣了,而且CUI用程序控制更方便,其豐富的命令行選項為我們提供了大量接口自定義拍攝的照片。比如,我喜歡用暖色,就會指定 "-awb cloud"選項,素描"-style sketch"也很有愛,大家可以試一試。指定EXIF信息可能有些復雜,最好去翻一下EXIF官方文檔,參照里面的格式會感覺很清晰。照片的拍攝時間默認使用系統時間,所以只要提前把系統校正就不用再指定EXIF的拍攝時間,GPS位置信息則只能手動指定了。

關於拍照程序,官方文檔:http://www.raspberrypi.org/wp-content/uploads/2013/07/RaspiCam-Documentation.pdf  第三方中文翻譯:http://dreamcolor.net/2013/05/raspicam-documentation/

 

視頻監控

這個功能是之前實現了的。視頻監控其實原理很簡單,但實現起來有點難度,即不知用何程序去實現,我對linux還不熟,即便是現在的實現也還很不完美。我是用ffmpeg+jwplayer實現的,樹莓派官方的程序用於輸出視頻流,然后ffmpeg將此視頻流轉為打包為flv格式輸出到網絡上,再自建站點,php里內建容器把視頻流接下來即可。

命令行示例: raspivid -t -0 -hf -vf -awb cloud -w 1280 -h 720 -fps 24 -b 5000000 -o - | ffmpeg -i - -vcodec copy -an -metadata streamName=Razor -f flv tcp://localhost:6666

我還不是很理解其中的參數,尤其是最后一個。

php網頁見 https://github.com/sanwave/Razor/blob/master/Others/video.php

至於自建web站點,非常簡單,我用的是ngigx,這里不再贅述。

 

視頻錄制/停止

很慚愧,我最初的初衷是一邊輸出視頻流到網絡一邊本地錄像,但一直沒能實現,網絡上也沒有找到相關資料,雖然原理很簡單,就是把管道復制一份出來就ok了。

視頻錄制很簡單,之前介紹樹莓派攝像頭的文檔就有講解和示例。這里只是提醒一下,視頻錄下來是x264的文件,用MP4Box打包后才能看。

關於停止,大家會說,實現很簡單嘛,直接Ctrl+C就干掉了,但是最后我們用的是程序控制,直接調用shell可以視頻錄制,卻沒辦法停下來,因為我們不知道那個進程的PID。所以,如果我們要穩定控制視頻錄制的開始和停止就必須學習如何處理linux下多進程。我的解決方案是:錄制視頻時,在主進程(控制飛行進程)下fork一新子進程,同時主進程記錄下子進程PID,然后子進程exec到shell,調用命令實現視頻錄制。在這個過程中,shell進程又建立了新的子進程用於執行后面的命令,而在要停止的時候把shell進程kill掉,這樣它的子進程就停止工作,攝像頭空閑了出來。功能已經實現了,但那個shell進程卻沒有被徹底干掉,變成僵屍進程,潛伏在系統中,我暫時還沒有找到辦法干掉他。

 

自建熱點

我用的USB無線網卡型號為TL-WN723N,建立模擬AP的官方hostapd程序是不兼容我的那款網卡的,氣得我差點想換掉,但其實還是可以用的,只不過需要自行編譯hostapd。8188CUS主控建立熱點可參考 http://ncloy.co.uk/blog/?p=593  ,配置文件其實也很講究,我已經上傳到GitHub里,有興趣可以到 https://github.com/sanwave/Razor/blob/master/Others/RasPi_Matrix_Network.txt 查看。

 

姿態傳感器

姿態傳感器模塊GY86包括MPU6050、HMC5883L、MS561101BA三個器件,均使用I2C協議。

我們先來說說linux下的I2C協議程序開發。linux下開發I2C程序最大的優勢在於,有一個名叫i2ctools的程序,極大地方便了調試與I2C器件通信的程序,還能掃描線上接入的I2C器件地址,絕對非常好用,吐血力薦。樹莓派自帶一個硬件I2C接口,不過,這個接口默認是沒有開啟的,需要手動打開。開啟方法詳見:http://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c 。樹莓派上的硬件開發基於WiringPi庫,可去 https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/ 下載安裝。

MPU6050采用標准I2C通信,使用起來還是蠻簡單的,何況網上驅動一籮筐,論標准,還是推薦I2cdevlib給出的Arduino驅動,我的驅動就是從上面移植下來的,而且此網站還提供了MPU6050及其他I2C器件的寄存器表和講解,非常具有參考價值,比呆呆地看datasheet要直觀清晰的多。
先說一下MPU6050的器件通信,典型通信過程如下,前面為數據內容,后面為寄存器地址:
    1. 0x41 => 0x6B 設定時鍾, X軸時鍾
    2. 0x00 => 0x1B 陀螺儀量程,250°/s
    3. 0x00 => 0x1C 加速度計量程,2g
    4. 0x01 => 0x6B 喚醒
    5. 0x3B~0x48 觀察數據輸出,其中,各數據均為2字節長。 0x3B 加速度X, 0x3D 加速度Y, 0x3F 加速度Z, 0x41 溫度, 0x43 陀螺儀X, 0x45 陀螺儀Y, 0x47 陀螺儀Z
由於我是用的GY86模塊中HMC5883L的數據線接在了MPU6050的從I2C接口上,所以在訪問HMC5883L時要先打開MPU6050的bypass模式。HMC5883L的典型通信過程,格式同上:
    1. MPU6050 0x00 => 0x6A 關閉I2C Master 模式
    2. MPU6050 0x02 => 0x37 打開bypass模式
    3. HMC5883 0x70 => 0x00 Config A
    4. HMC5883 0x20 => 0x01 Config B
    5. HMC5883 0x00 => 0x02 連續輸出
    6. HMC5883 0x03~0x08 觀察數據輸出,其中,各數據均為2字節長。注意,0x03為X軸數據,0x05為Z軸數據,0x07為Y軸數據
以上通信過程已經夠基本使用,但我還不滿足,既然MPU6050可以代勞獲取HMC5883L的數據,為什么我不用?這樣取數據時更方便,代碼實現更優雅。典型設置過程如下:   
    1. 0x20 => 0x6A 打開I2C Master模式
    2. 0x00 => 0x37 關閉bypass模式
    3. 0x0D => 0x24 設置操作從器件的時鍾及其他
    4. 0x9e => 0x25 設置從器件的操作模式及其地址
    5. 0x03 => 0x26 設置讀取從器件的起始寄存器地址
    6. 0x86 => 0x27 設置讀取從器件寄存器的長度及開關等
    7. HMC5883L寄存器0x03~0x08的數據會保存在MPU6050寄存器0x49~0x54中,並周期更新
若以上步驟后MPU6050可能獲取不到HMC5883的值,重置一下I2C SLV0試試。我當初就是怎么試都不行,重置了一下,就一直Okay了。

通過以上傳感器我們已經可以獲得飛行器當前的姿態了,但數據不能直接拿來用的,誤差和飄移都太大了,我們要做的工作便是校准和濾波。校准的話,想比大家都會。而濾波,則很有學問了,最好的自然屬卡爾曼濾波了,處理后的結果曲線同真實情況吻合的非常好,但這也是最難的吧,計算量也相當可觀。有人使用簡化版本,但不清楚效果如何,我也沒有試過。用的比較多的大概便是互補濾波了,流傳較廣的Madgwick的AHRS算法便屬於這一類,Fabio的FreeIMU項目使用的也是Madgwick的算法,不過修改了個別參數。根據他們的視頻,效果還是不錯的,但我重現時卻發現漂移的厲害,還不知是何原因。
氣壓計MS561101BA的驅動我還沒有搞定,他用的並不是標准I2C,大家可以參考FreeIMU中提供的驅動。

 

GPS通信

GPS通信采用Uart協議,相對簡單,不過注意,樹莓派的Uart口默認用作命令行調試,需手動關閉,方法詳見:https://sites.google.com/site/semilleroadt/raspberry-pi-tutorials/gpio

我買的GPS模塊比較爛,u-blox的NEO 6M系列的,搜星能力一般,室內獲得授時不是問題,偶爾可以定位。使用Uart 9600時采用NMEA 0183協議V2.3,默認每秒刷新一次i,只能輸出7種語句,不過夠用了。而我的開發工作只是解析這些語句,表面上看簡單無比,但我字符串處理的基本功不夠扎實,費了些時日,最后還是用自己實現的字符串分割函數才完成了這一功能,C語言中的strtok不是一般的坑,而且線程不安全,考慮到C的移植我就沒有使用C++的string庫函數。GPS通信雖然簡單,可是要完全消化這些信息卻不簡單,里面涉及到不同地球物理模型導致的漂移以及各種誤差的計算問題,我都沒怎么考慮,只是初級使用而已。

 

無線通信

無線模塊我們選用了成本極低的nRF24L01,實現近距離無線通信,基本滿足要求。相比之下,其他模塊性價比太差。
nRF的通信難點僅在SPI通信協議上,搞定了SPI,nRF就差不多了。之前我用TI的LM4F軟件模擬SPI就一直沒有搞定nRF,反復檢查代碼,甚至找來同學一起看也沒看出道道兒。電賽中被相同的問題絆到后,我才意識到問題所在,初始化操作延時不夠,單片機啟動延時不夠也是一方面。現在,我也只是把代碼安上去了,還沒有測試,在此也就不多說了。

 

今天就說這么多吧,具體的姿態算法實現和控制算法實現以及上面還沒有解決的問題留到下再說。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM