航天員科研訓(xùn)練中心 楊 勇
介紹了基于路由器直接遙控的wifi視頻小車(chē)的軟硬件制作過(guò)程。小車(chē)以玩具坦克為車(chē)身,以GL-iNnet路由器作為無(wú)線收發(fā)模塊,實(shí)現(xiàn)了路由器GPIO端口直接控制小車(chē),并利用V4L2接口發(fā)送視頻圖像的功能。編制了Android程序,可實(shí)現(xiàn)Android手機(jī)接收視頻,并對(duì)小車(chē)進(jìn)行遙控。
引言:視頻遙控車(chē)一直以來(lái)就是DIY的首選作品,因?yàn)橹谱饕曨l小車(chē)需要軟硬件多方面的技能,涉及電子學(xué)、網(wǎng)絡(luò)、圖形圖像、軟件編程等多方面知識(shí),既有較強(qiáng)的娛樂(lè)性,又能鍛煉和提高自身技能。手邊恰好有一款GL-iNet路由器,這款路由器不但將串口引出,還將空余的5個(gè)GPIO留出,因此可玩性比較高。此外,正好手邊有一輛兒子玩壞的玩具坦克,就有了以這些為基礎(chǔ)做一輛視頻遙控車(chē)的想法。
本次DIY的視頻小車(chē)硬件部分包括:小車(chē)車(chē)身、路由器、電機(jī)驅(qū)動(dòng)模塊、視頻轉(zhuǎn)換器、攝像頭、電源。硬件系統(tǒng)圖如圖1所示。
圖1 硬件系統(tǒng)圖
車(chē)身是利用壞玩具坦克車(chē)的帶有履帶的下半部,車(chē)身內(nèi)是兩只電機(jī),可驅(qū)動(dòng)后輪通過(guò)履帶傳動(dòng)前進(jìn)。電源由于給路由器供電并驅(qū)動(dòng)小車(chē)電機(jī),為直流5V電源,本次DIY制作是將小米移動(dòng)電源臨時(shí)作為小車(chē)的電源。電機(jī)驅(qū)動(dòng)模塊是L9110電機(jī)驅(qū)動(dòng)模塊,一只模塊上有兩只L9110芯片,可同時(shí)驅(qū)動(dòng)2個(gè)直流電機(jī)正反轉(zhuǎn)。
Wifi小車(chē)制作的核心部件是GL-iNet路由器,它是一款專門(mén)為OpenWrt而設(shè)計(jì)路由器,其MCU為Atheros AR9331,主頻400MHz,板載64M內(nèi)存和16M Flash。PCB板有一只USB接口,可連接U盤(pán)或USB攝像頭,板子上預(yù)留了5個(gè)GPIO,1個(gè)電源接口(5V和3.3V各一個(gè)),且串口已經(jīng)焊好。對(duì)路由器的改造包括焊接GPIO端子和電源端子。路由器改造部分見(jiàn)圖2所示。本次DIY使用了5個(gè)預(yù)留GPIO中的四個(gè),Pin21和Pin22控制左輪,Pin18和Pin19控制右輪。將5V電源接口從板子上引出,更方便后續(xù)接線。
攝像頭開(kāi)始使用的是一款支持MJPG格式的USB攝像頭,但后來(lái)測(cè)試過(guò)程中發(fā)現(xiàn)在光線暗時(shí),幀率較低,傳輸?shù)绞謾C(jī)上的視頻有較明顯的卡頓,因此最后更換成一只汽車(chē)倒車(chē)攝像頭,該攝像頭輸出信號(hào)是模擬視頻信號(hào)ITU-R BT.656標(biāo)準(zhǔn)的,為此又增加了一只UVC視頻轉(zhuǎn)換器,該轉(zhuǎn)換器的主控芯片為MS2106,可以將CVBS模擬信號(hào)轉(zhuǎn)換為USB2.0接口的數(shù)字信號(hào),支持720×480、640×480和480×320三種分辨率,且支持M-JPEG圖像格式輸出。該芯片的視頻處理框圖如圖3所示。
圖2 路由器板子引線
圖3 MS2106芯片視頻處理框圖
軟件部分主要分為路由器服務(wù)器端編程和手機(jī)端Android編程。服務(wù)器端和手機(jī)端的控制信號(hào)和視頻信號(hào)均通過(guò)TCP進(jìn)行傳輸。
GL-iNet路由器安裝的是chaos calmer(15.05)版本的OpenWrt操作系統(tǒng),因?yàn)樵瓘S路由器中的OpenWrt是原廠定制的,有許多額外的軟件工具。為了提高系統(tǒng)穩(wěn)定性和增加使用內(nèi)存效率,所以從github上下載了原版的chaos calmer版的OpenWrt,重新編譯后生成bin文件,通過(guò)網(wǎng)頁(yè)端刷新固件。編譯OpenWrt時(shí)注意的方面包括:
a.在編譯前make menuconfig時(shí),將Target System和Target Profile分別選Atheros AR7xxx/AR9xxx和GL.iNet 6408。為了使用USB攝像頭需將Video Support內(nèi)各選項(xiàng)選上;
b.第一次編譯通過(guò)后,需更改package/base-files/files/lib/functions/uci-default.sh和package/base-files/files/bin/config_generate這2個(gè)文件,修改ip地址,以免和家里的無(wú)線路由器ip相同。修改package/kernel/mac80211/files/lib/wifi/mac80211.sh文件,將ssid改成自定義的無(wú)線網(wǎng)絡(luò)名稱,并改為默認(rèn)開(kāi)啟wifi模式。修改后再次編譯。
在OpenWrt端首先到設(shè)置GPIO的功能,把用到的Pin21、Pin22、Pin18和Pin19設(shè)置為輸出模式,以Pin21為例,方法如下:
echo 21 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio21/direction
在程序中可用如下方法將GIPO設(shè)置為1或0(以Pin21為例):
system(“echo 1 > /sys/devices/virtual/gpio/gpio21/value”);
system(“echo 0 > /sys/devices/virtual/gpio/gpio21/value”);
服務(wù)器端主程序?yàn)閏ar_main.c,在主程序中fork兩個(gè)子進(jìn)程,分別是gpioserver和v4l2server。gpioserver打開(kāi)6666端口號(hào),監(jiān)聽(tīng)手機(jī)客戶端的連接,并根據(jù)接收的TCP消息字,向相關(guān)GPIO端口發(fā)送1或0,控制小車(chē)前進(jìn)、后退和左右轉(zhuǎn)向。v4l2server打開(kāi)6688端口號(hào),打開(kāi)USB攝像頭設(shè)備,當(dāng)手機(jī)客戶端的連接后,通過(guò)6688端口向手機(jī)端發(fā)送視頻流。子進(jìn)程間通過(guò)共享內(nèi)存映射的方式實(shí)現(xiàn)進(jìn)程間通信。程序流程圖如圖4所示。
圖4 軟件流程圖
傳統(tǒng)的攝像頭信號(hào)采集和傳輸部分一般采用安裝mjpg-streamer工具,利用web協(xié)議進(jìn)行傳輸。本次DIY沒(méi)有采用該方式,而是使用了V4L2(Video4Linux)的API接口,利用TCP協(xié)議傳輸。V4L2是Linux下關(guān)于視頻采集相關(guān)的設(shè)備驅(qū)動(dòng)框架,為驅(qū)動(dòng)和應(yīng)用程序提供了一套統(tǒng)一的接口規(guī)范。利用V4L2提供的API函數(shù)進(jìn)行視頻采集和傳輸,主要包括打開(kāi)攝像頭設(shè)備、設(shè)置攝像頭視頻輸出模式、設(shè)置視頻緩沖區(qū)隊(duì)列、讀取緩沖區(qū)隊(duì)列并處理數(shù)據(jù)等。本程序視頻輸出的分辨率選取480×320,視頻格式選取MJPEG,采集圖像采用內(nèi)存映射(mmap)方式。
因?yàn)槌绦蛐枰磸?fù)調(diào)試,所以沒(méi)有將程序制作成ipk的安裝程序,而是利用OpenWrt提供的gcc4.8交叉編譯鏈工具,直接將程序編譯成可執(zhí)行程序,然后服務(wù)器端通過(guò)wget將可執(zhí)行程序下載到路由器。
將前文介紹的GPIO的設(shè)置語(yǔ)句編寫(xiě)為shell文件(名稱setled),連同編譯好的主程序可執(zhí)行文件加入到OpenWrt的/etc/rc.local文件中,以確保路由器開(kāi)機(jī)即執(zhí)行該程序。
采用eclipse編寫(xiě)Android程序,程序共2個(gè)Activity界面:設(shè)置界面和主程序界面。設(shè)置界面中設(shè)置服務(wù)器端IP、控制端口號(hào)和視頻傳輸端口號(hào)。主程序界面中有前進(jìn)/后退的按鈕,按鈕事件用于向路由器端發(fā)送TCP數(shù)據(jù)。程序利用SurfaceView類和SurfaceHolder等接口在窗口繪制圖像,在DataInputStream的自定義子類中進(jìn)行Socket連接,并通過(guò)解析jpeg文件的SOI(Start of Image)標(biāo)記0xFF和0xD8來(lái)獲取一副圖像的起始和大小,將數(shù)據(jù)流包裝為一副圖像并繪制到Canvas上顯示。通過(guò)計(jì)算1秒鐘內(nèi)顯示的圖像數(shù)得出幀率,將幀率數(shù)據(jù)顯示在手機(jī)屏幕右下角。
DIY小車(chē)外形如圖5所示,手機(jī)Andriod運(yùn)行程序界面如圖6所示。
圖5 小車(chē)外觀
圖6 Android程序界面
打開(kāi)路由器,先手機(jī)連接路由器wifi熱點(diǎn),然后啟動(dòng)手機(jī)客戶端Android程序。程序界面中左右兩邊的上下箭頭分別控制左右兩個(gè)輪子的前進(jìn)和倒退,通過(guò)這4個(gè)按鈕的不同的組合,可以實(shí)現(xiàn)前進(jìn)、倒退、左轉(zhuǎn)、右轉(zhuǎn)等6種控制模式。實(shí)測(cè)圖像傳輸幀率為30fps左右,視頻流暢,無(wú)卡頓。
DIY制作wifi小車(chē)?yán)寐酚善鳛榭刂坪鸵曨l傳輸部件,沒(méi)有制作復(fù)雜的電路板,倒車(chē)攝像頭、視頻轉(zhuǎn)換器、電機(jī)驅(qū)動(dòng)模塊等可從淘寶購(gòu)買(mǎi),總價(jià)不超過(guò)80元。編寫(xiě)了路由器服務(wù)器端軟件,實(shí)現(xiàn)了V4L2的API接口函數(shù)進(jìn)行視頻圖像傳輸,利用視頻轉(zhuǎn)換器將模擬信號(hào)轉(zhuǎn)換成數(shù)字信號(hào),大大提高了圖像傳輸幀率,使得wifi小車(chē)娛樂(lè)性更強(qiáng)。按照本文所描述的GPIO控制方法,可以制作其他的DIY制作,如遠(yuǎn)程控制家里電器等。Gl-iNet只有5個(gè)空余的GPIO,如果將路由器串口連接C51等單片機(jī),將擴(kuò)展GPIO接口,控制能力也會(huì)大大提高。