干貨|手把手教你自制六足仿生機(jī)器人

摘要:經(jīng)過(guò)大一那次失敗之后,我決定暫時(shí)停止該項(xiàng)目的開(kāi)發(fā),轉(zhuǎn)而先去學(xué)習(xí)那些有關(guān)嵌入式開(kāi)發(fā)的基礎(chǔ)知識(shí),等以后有能力的時(shí)候再去獨(dú)立完成這個(gè)六足機(jī)器人。很幸運(yùn)的是在我大學(xué)本科即將結(jié)束的時(shí)候,我已掌握了足夠的知識(shí)來(lái)完成那個(gè)曾經(jīng)困擾我已久的機(jī)器人項(xiàng)目,于是我花了幾周的時(shí)間完成了這個(gè)六足機(jī)器人,算是了卻了自己的一個(gè)心愿吧。
一、前言
這個(gè)六足機(jī)器人是我在大四做的,是我大學(xué)本科生涯的最后一個(gè)個(gè)人項(xiàng)目。至于為什么我要做六足機(jī)器人,還要從高考完之后說(shuō)起:當(dāng)時(shí)剛考完的我一直想做一些有意思的事情,直到有一天我發(fā)現(xiàn)了一個(gè)叫PVCBOT的網(wǎng)站,里面記錄了很多如何使用PVC材料來(lái)制作簡(jiǎn)單機(jī)器人的教程,其中有一款叫做PVC六足機(jī)器昆蟲(chóng)的機(jī)器人徹底震撼了我,當(dāng)時(shí)看完教程之后我就下定決心也要做一個(gè)類(lèi)似的六足機(jī)器人,于是我便從懶貓俠前輩那里購(gòu)買(mǎi)了六足機(jī)器人套件(目前應(yīng)該已經(jīng)絕版了),并打算按照提供的教程完成自己的六足機(jī)器人,但無(wú)奈當(dāng)時(shí)的我所掌握的知識(shí)太少,什么單片機(jī)、串口通信、舵機(jī)PWM、電源管理、傳感器、舵機(jī)控制板等都不懂,特別是機(jī)械結(jié)構(gòu)方面我更是一竅不通,所以大一那會(huì)兒我還鬧出了笑話:用硬紙板做六足機(jī)器人的肢體,在安裝好舵機(jī)并通電測(cè)試后,眼睜睜地看著自己的“紙板六足”在舵機(jī)的震動(dòng)下不斷地解體。。。

二、概述
六足仿生機(jī)器人是一個(gè)擁有十八個(gè)關(guān)節(jié)自由度的迷你多足機(jī)器人,它可以實(shí)現(xiàn)紅外遙控、超聲波避障等基本功能。機(jī)器人的硬件核心為Arduino Nano,并采用串口通信的方式與24路舵機(jī)控制板進(jìn)行數(shù)據(jù)交互,從而間接完成對(duì)所有舵機(jī)旋轉(zhuǎn)角度的精確控制,最終使機(jī)器人能夠以各種不同的步態(tài)進(jìn)行移動(dòng)。當(dāng)然,這個(gè)機(jī)器人項(xiàng)目的軟件依舊開(kāi)源,具體代碼可以從我的GitHub倉(cāng)庫(kù)上獲得。

三、制作
六足機(jī)器人的整個(gè)制作過(guò)程主要分為機(jī)械和電子兩部分,由于教程中每一步的圖片都非常清楚,所以機(jī)械這部分沒(méi)花費(fèi)我太多的時(shí)間和精力。而電子部分則全部是我自己設(shè)計(jì)的,雖然原理難度不大,但是要根據(jù)機(jī)器人的機(jī)械結(jié)構(gòu)來(lái)選擇洞洞板的擺放位置并且要完成其上電子元件的布局和焊接工作確實(shí)也比較費(fèi)功夫,而且有的時(shí)候如果處理的不好還要返工,不過(guò)所幸自己在焊電路前就已經(jīng)規(guī)劃好了,所以電路部分的制作也還算順利。
在接下來(lái)的篇幅中,我會(huì)盡可能詳細(xì)地講解機(jī)器人制作過(guò)程中的一些具體步驟和細(xì)節(jié),如果你對(duì)機(jī)器人的原理和最后的效果更感興趣的話,可以跳過(guò)本小節(jié)直接閱讀原理和效果章節(jié)。
3.1 機(jī)械
六足小腿
如下圖所示,六足的小腿部分主要由兩片PVC材質(zhì)的肢體通過(guò)疊加而成,而關(guān)節(jié)部分則使用的是9G金屬齒舵機(jī),只要兩個(gè)自攻螺絲便可將PVC肢體牢牢固定在舵機(jī)上,從而保證六足小腿在與地面接觸時(shí)可以有足夠的力量來(lái)支撐整個(gè)軀體。

因?yàn)槭橇銠C(jī)器人,所以同樣結(jié)構(gòu)的小腿要再做五個(gè)出來(lái)。注意:機(jī)器人的軀體每邊有三個(gè)小腿,左右兩兩對(duì)稱(chēng),所以在組裝的時(shí)候肢體和舵機(jī)安裝的位置是有講究的,要保證結(jié)構(gòu)對(duì)稱(chēng)且不能裝反。

六足大腿
關(guān)節(jié)
六足大腿的關(guān)節(jié)結(jié)構(gòu)比之前介紹過(guò)的小腿關(guān)節(jié)要略微復(fù)雜一些,因?yàn)榇笸鹊年P(guān)節(jié)包含了機(jī)器人足體上下和前后兩個(gè)維度的運(yùn)動(dòng),所以需要兩個(gè)舵機(jī)來(lái)實(shí)現(xiàn)。如下圖所示,首先我們使用螺絲將一個(gè)舵機(jī)固定在方形的關(guān)節(jié)肢體里。

接著我們要重復(fù)以上的安裝步驟再制作出六個(gè)類(lèi)似的肢體結(jié)構(gòu)。不過(guò)在制作的過(guò)程中也要注意機(jī)器人左右兩側(cè)各三個(gè)肢體結(jié)構(gòu)要保持對(duì)稱(chēng)。

然后我們需要將六個(gè)舵機(jī)分別插入到之前預(yù)留好的肢體空槽里,并保證每組的兩個(gè)舵機(jī)在位置上是互相垂直的,即下圖中舵機(jī)圓形旋轉(zhuǎn)軸的朝向要一前一上。

接下來(lái)安裝六足大腿關(guān)節(jié)的固定片,即將固定片卡到下圖中正面那個(gè)舵機(jī)的圓形旋轉(zhuǎn)軸上。固定片,顧名思義是用來(lái)固定的,用在這里主要是防止關(guān)節(jié)處的兩個(gè)舵機(jī)因足體的震動(dòng)而彼此之間出現(xiàn)位置上的偏移。

最后分別使用兩條塑料扎帶對(duì)每組關(guān)節(jié)進(jìn)行進(jìn)一步的加固,其中一條從固定片上方穿過(guò),起到束緊固定片的作用,而另一條則穿過(guò)關(guān)節(jié)側(cè)面的小孔對(duì)結(jié)構(gòu)進(jìn)行固定。

大腿
六足的大腿是由兩個(gè)PVC材質(zhì)的長(zhǎng)方形連桿組成,從下圖中可以很清楚地看到每個(gè)連桿的左右兩側(cè)均安裝有配套的舵盤(pán),它們的作用主要是用于連接六足的小腿關(guān)節(jié)和大腿關(guān)節(jié)。

六足足體
如下圖所示,使用螺絲將之前已經(jīng)制作好的六對(duì)小腿和大腿肢體對(duì)應(yīng)連接在一起。雖然擰螺絲本身沒(méi)什么難度,但是在哪個(gè)位置用螺絲來(lái)固定舵機(jī)還是有規(guī)定的:即舵機(jī)在被肢體連接固定之前要讓其旋轉(zhuǎn)軸回歸到原始的中點(diǎn)位置上(旋轉(zhuǎn)范圍為0~180°的舵機(jī),其中點(diǎn)位置為90°),這樣做的目的是讓所有的舵機(jī)都能夠擁有最合適的運(yùn)動(dòng)范圍,從而防止機(jī)器人在移動(dòng)時(shí)出現(xiàn)足體運(yùn)動(dòng)不對(duì)稱(chēng)的情況。至于如何讓舵機(jī)回歸中點(diǎn),一種辦法是使用現(xiàn)成的舵機(jī)調(diào)試板,只要移動(dòng)旋鈕便可調(diào)節(jié)舵機(jī)的位置;另一種是編寫(xiě)Arduino程序,讓舵機(jī)在上電后自動(dòng)歸中。我用的是第二種方法,感覺(jué)效果還不錯(cuò)。

接下來(lái),我們要把六足的足體全部安裝到其頂部軀體上。同理,在安裝前要確保需要連接固定的舵機(jī)已經(jīng)回歸到中點(diǎn)位置,除此之外還要提前規(guī)定好軀體的哪一側(cè)是機(jī)器人的頭部,哪一端是機(jī)器人的尾部,不要在安裝的時(shí)候把足體裝反了。

如圖所示,我們首先可以找一個(gè)稍微有點(diǎn)高度的物品將機(jī)器人頂部墊高,然后使用扎帶依次將每個(gè)足體的三條舵機(jī)線捆綁起來(lái),這樣不僅看上去更加美觀,便于之后的整理和連線,而且也可以有效阻止舵機(jī)線與運(yùn)動(dòng)中的足體發(fā)生纏繞甚至被扯斷等情況的出現(xiàn),畢竟自己大學(xué)在機(jī)器人基地的時(shí)候就曾親身經(jīng)歷過(guò)電機(jī)線在機(jī)械臂移動(dòng)的過(guò)程中被狠狠地扯斷的悲劇。。。

最后,我們只需要把鋰電池用扎帶固定在底部軀體的尾部,然后將供電線和充電線分別引出,再把所有已經(jīng)扎好的舵機(jī)線按照順序塞到軀體當(dāng)中,并用螺絲將頂部和底部?jī)蓚€(gè)軀體擰緊合二為一便大功告成了(由于這部分沒(méi)有拍照,所以就用文字?jǐn)⑹隽薿rz)。
3.2 電子
電源管理
下圖是機(jī)器人的電源管理模塊。電源管理模塊主要包含電源、降壓電路和控制電路等,具體的原理部分請(qǐng)看下面原理中的電源管理章節(jié)。

下圖是電源管理模塊的背面。為了讓焊接后的電路保持整齊、美觀,我盡可能采用錫接走線的方式來(lái)完成各元件的電氣連接,而沒(méi)辦法走線的地方才使用傳統(tǒng)的飛線進(jìn)行連接。盡管錫接走線的優(yōu)點(diǎn)很明顯,但是它的缺點(diǎn)也比較突出:一個(gè)是浪費(fèi)焊錫,另一個(gè)就是容易短路,其中短路問(wèn)題對(duì)機(jī)器人的影響還是挺嚴(yán)重的,我記得自己之前就有一次不小心把已經(jīng)上電的電源管理模塊隨意放在六足機(jī)器人的頂部軀體上,令我沒(méi)想到的是固定軀體的螺絲的頭部正好卡在電路背面電源正負(fù)極錫接走線的中間,結(jié)果可想而知。
所以,在上電測(cè)試之前,大家要先用萬(wàn)能表對(duì)焊接過(guò)的電路進(jìn)行短路測(cè)試,一定要確保沒(méi)有多余的焊錫渣殘留在電路板上,而且對(duì)于使用錫接走線方式焊接的電路板,一定不要讓其背面直接與潛在具有導(dǎo)電功能的介質(zhì)進(jìn)行接觸,可以適當(dāng)?shù)厥褂勉~柱將板子架高或者用熱熔膠把板子背面全都覆蓋住,以防止短路問(wèn)題的發(fā)生。

在確保電路不存在任何可能潛在的短路問(wèn)題后,可像下圖所示的那樣,對(duì)電路模塊進(jìn)行上電測(cè)試。測(cè)試主要檢測(cè)電源降壓是否達(dá)到預(yù)期設(shè)定的數(shù)值,開(kāi)關(guān)的通斷邏輯是否正確等。

控制單元
下圖是機(jī)器人的控制單元模塊。該控制單元模塊主要由Arduino Nano控制板、HMC58883L電子羅盤(pán)傳感器、MPU6050慣性測(cè)量傳感器(圖中的底座上未插入)、HC-SR04超聲波傳感器和紅外接收管等組成,為了方便在模塊出現(xiàn)問(wèn)題時(shí)能夠?qū)ζ溥M(jìn)行更換,我在洞洞板上焊接了一些棑母底座,這樣模塊就可以直接插在棑母底座上,拆卸很方便。此外,有關(guān)電路原理部分的詳細(xì)介紹可以閱讀下面的原理章節(jié)。

下圖是控制單元模塊的背面。跟上面已經(jīng)介紹過(guò)的電源管理模塊一樣,我使用的依然是錫接走線+飛線的方式對(duì)元件進(jìn)行焊接,由于電氣連接比較多,所以焊完之后要對(duì)電路進(jìn)行更加全面和仔細(xì)的檢查。

如下圖所示,由于我的Arduino Nano控制板的USB轉(zhuǎn)串口在之前的尋光小車(chē)實(shí)驗(yàn)中因短路問(wèn)題被燒壞了,所以我用的是專(zhuān)門(mén)為Arduino最小系統(tǒng)板燒寫(xiě)B(tài)ootloader的USBtinyISP編程器來(lái)下載程序。經(jīng)測(cè)試,所有模塊均能正常工作,那么接下來(lái)的工作就只剩下將機(jī)器人全部組裝好,然后編寫(xiě)和調(diào)試代碼了。

四、原理
4.1 硬件
以下是該仿生六足機(jī)器人的硬件系統(tǒng)連接圖:

由上圖可知,六足機(jī)器人的硬件系統(tǒng)主要由舵機(jī)控制、電源管理、核心主控、數(shù)據(jù)感知和數(shù)據(jù)通信共五部分組成,接下來(lái)進(jìn)行詳細(xì)的介紹:
舵機(jī)控制
金屬齒舵機(jī)
本項(xiàng)目六足機(jī)器人所配備的舵機(jī)具體型號(hào)為YZW Y09G,由于該舵機(jī)內(nèi)部電機(jī)減速齒輪組使用金屬材質(zhì)打造,所以其價(jià)格上要比常見(jiàn)的輝盛SG90塑料齒舵機(jī)貴一些,但是性能卻相當(dāng)出色。該舵機(jī)標(biāo)準(zhǔn)輸入電壓范圍為4.8v~6.0v(電壓稍大于6v也沒(méi)問(wèn)題),扭矩范圍在1.3kg/cm~1.6kg/cm之間,經(jīng)測(cè)試,十八個(gè)舵機(jī)共同作用的扭矩可以基本滿(mǎn)足支撐機(jī)器人軀體以及鋰電池等相關(guān)負(fù)載的需求。當(dāng)然,由于定位精度有限,所以舵機(jī)會(huì)存在控制上的死區(qū)問(wèn)題,我的解決辦法主要是通過(guò)軟件補(bǔ)差的方式來(lái)消除這個(gè)機(jī)械結(jié)構(gòu)上的誤差,使機(jī)器人能夠盡可能準(zhǔn)確地到達(dá)預(yù)定的目標(biāo)位置。
舵機(jī)控制板
舵機(jī)控制板顧名思義就是能夠用于控制多個(gè)舵機(jī)的電路板,由于傳統(tǒng)通過(guò)編寫(xiě)程序讓單片機(jī)輸出多路PWM控制信號(hào)對(duì)于大部分的機(jī)器人愛(ài)好者來(lái)說(shuō)比較復(fù)雜,所以就有高手們將MCU和相關(guān)外圍電路封裝在一起開(kāi)發(fā)了便于使用的舵機(jī)控制板。此外,舵機(jī)控制板一般都會(huì)帶有一個(gè)PC端的調(diào)試軟件,只要在建立串口通信的前提下拖動(dòng)軟件界面上的滑塊,便能精確且實(shí)時(shí)地操控舵機(jī)的旋轉(zhuǎn)角度,而且還能將調(diào)試好的動(dòng)作組合在一起形成動(dòng)作組并下載到舵機(jī)控制板的芯片中進(jìn)行保存,為之后核心主控通過(guò)串口對(duì)其進(jìn)行調(diào)用奠定基礎(chǔ)。本項(xiàng)目六足機(jī)器人使用的是懶貓俠早期開(kāi)發(fā)的一款24路舵機(jī)控制板,具體使用方法見(jiàn)24路舵機(jī)控制板板使用說(shuō)明。
電源管理
電源管理應(yīng)該算是機(jī)器人硬件控制系統(tǒng)里除了核心主控之外最重要的模塊了,畢竟傳感器壞了機(jī)器人還能夠四處移動(dòng),但是電源部分壞了的話機(jī)器人可就只是一個(gè)靜止的模型了。由于本項(xiàng)目六足機(jī)器人采用十八個(gè)舵機(jī)作為關(guān)節(jié)執(zhí)行器,所以盡管9G舵機(jī)的耗電量相對(duì)標(biāo)準(zhǔn)舵機(jī)要小很多,但是十八個(gè)舵機(jī)加起來(lái)所需要的電流大小還是相當(dāng)驚人的,因此經(jīng)過(guò)一段時(shí)間的考量,我最終選擇了一款參數(shù)為7.4v850mAh的鋰電池組作為機(jī)器人的電源,其電能滿(mǎn)足六足機(jī)器人的動(dòng)力需求。
除了鋰電池電源之外,從上面的硬件系統(tǒng)連接圖中還可以看到有兩個(gè)降壓電路,其中一個(gè)降壓電路使用L2596 DC-DC模塊將一路電源的電壓降到標(biāo)準(zhǔn)的5V,用于給Arduino Nano主控制板供電,而另一路使用的是D25XB80大功率整流橋,它擁有標(biāo)稱(chēng)800V的最大逆向電壓和25A的額定前向電流,在鋰電池組充滿(mǎn)電的情況下(標(biāo)稱(chēng)7.4v的鋰電池組充滿(mǎn)電的電壓大概在8.4v左右),連接一片D25XB80可以使電壓整體降到大概6.9v,經(jīng)測(cè)試給24路舵機(jī)控制板和18個(gè)舵機(jī)供電是沒(méi)有問(wèn)題的。
最后為了方便控制鋰電池電源的輸入和降壓后電源的輸出,我并聯(lián)連接了三個(gè)開(kāi)關(guān),并在并聯(lián)支路中分別加入了三個(gè)LED燈用作電源閉合或斷開(kāi)的顯示。關(guān)于電源管理的其他內(nèi)容,大家可以參考一下懶貓俠寫(xiě)的六足機(jī)器人動(dòng)力的分析 這篇博文。
核心主控
核心主控主要負(fù)責(zé)分析傳感器反饋回來(lái)的數(shù)據(jù),然后給舵機(jī)控制板發(fā)出動(dòng)作指令,間接驅(qū)動(dòng)舵機(jī)運(yùn)行到指定角度。在本項(xiàng)目中我使用的核心主控為Arduino Nano,它體型較小,且擁有非常豐富的開(kāi)發(fā)教程和器件驅(qū)動(dòng)庫(kù),很容易上手。
數(shù)據(jù)感知
數(shù)據(jù)感知模塊主要包括HC-04超聲波測(cè)距傳感器、HMC5883L電子羅盤(pán)傳感器、MPU6050慣性測(cè)量傳感器和紅外接收管,其中超聲波測(cè)距傳感器用來(lái)幫助六足機(jī)器人避開(kāi)其正前方的障礙物,而紅外接收管則和常見(jiàn)的迷你紅外遙控器一同構(gòu)成了整個(gè)六足機(jī)器人的遙控系統(tǒng),紅外接收管能夠接收經(jīng)過(guò)38kHz載頻二次調(diào)制生成的紅外信號(hào),并將解碼后的數(shù)據(jù)發(fā)送給Arduino Nano主控進(jìn)行相關(guān)處理。HMC58883L和MPU6050這兩個(gè)傳感器主要用于六足機(jī)器人的運(yùn)動(dòng)感知,通過(guò)采集它們的數(shù)據(jù)并進(jìn)行簡(jiǎn)單的融合處理便能得到機(jī)器人在空間中的位置關(guān)系,從而為之后修正機(jī)器人在移動(dòng)過(guò)程中的路徑偏差提供數(shù)據(jù)上的保障。不過(guò)由于當(dāng)時(shí)開(kāi)發(fā)時(shí)間有限,所以這一部分暫未涉及。
數(shù)據(jù)通信
數(shù)據(jù)通信包括紅外通信、串口通信和藍(lán)牙通信三部分。其中,紅外通信在上面的數(shù)據(jù)感知部分已經(jīng)進(jìn)行過(guò)簡(jiǎn)要的介紹了,即采用NEC的編碼格式將數(shù)據(jù)進(jìn)行相應(yīng)的編碼或解碼,并通過(guò)紅外線的方式完成遙控指令數(shù)據(jù)的傳輸;串口通信則主要用在核心主控和舵機(jī)控制板之間,根據(jù)舵機(jī)控制板所規(guī)定的數(shù)據(jù)格式,主控能夠發(fā)送指令來(lái)控制一個(gè)舵機(jī)或多個(gè)舵機(jī)旋轉(zhuǎn)到指定的位置;最后的藍(lán)牙通信可以使PC端上的軟件與舵機(jī)控制板之間建立起無(wú)線連接,方便六足機(jī)器人動(dòng)作的調(diào)試。
4.2 軟件
核心類(lèi)庫(kù)
hexapod_bionic_robot.h
該頭文件定義了HexapodBionicRobot類(lèi),里面聲明了機(jī)器人避障、處理紅外編碼信息、處理超聲波距離、獲取紅外編碼信息、獲取超聲波距離和移動(dòng)機(jī)器人軀體等核心函數(shù)。
#ifndef?HEXAPOD_BIONIC_ROBOT_H
#define?HEXAPOD_BIONIC_ROBOT_H
#include?
#include?
#define?PIN_IR??????2
#define?PIN_TX??????3
#define?PIN_RX??????4
#define?PIN_TRIG????5
#define?PIN_ECHO????6
#define?PIN_LED?????13
#define?DIR_INIT????1
#define?DIR_STOP????1
#define?DIR_FRONT???2
#define?DIR_BACK????3
#define?DIR_LEFT????4
#define?DIR_RIGHT???5
#define?MODE_REMOTE?25
#define?MODE_AUTO???26
#define?RADIX???????10
#define?RUNTIME?????2400
#define?TIMEOUT?????30000
class?HexapodBionicRobot
{
public:
????HexapodBionicRobot(IRrecv?*ir_receiver,?decode_results?*ir_results);
????void?avoidFrontObstacle(void);
????void?handleInfraredInformation(void);
????void?handleUltrasonicDistance(void);
????void?moveRobotBody(uint8_t?direction,?uint8_t?times);
????uint32_t?getInfraredInformation(void);
????float?getUltrasonicDistance(void);
private:
????int?????????????mode_flag_;
????float???????????duration_;
????float???????????distance_;
????IRrecv?????????*ir_receiver_;
????decode_results?*ir_results_;
};
#endif?//?HEXAPOD_BIONIC_ROBOT_H
hexapod_bionic_robot.cpp
該源文件實(shí)現(xiàn)了HexapodBionicRobot類(lèi)里面所有已經(jīng)聲明的函數(shù),其中g(shù)etInfraredInformation()函數(shù)調(diào)用了官方的IRremote庫(kù),可以實(shí)時(shí)獲取紅外遙控器所發(fā)送的紅外編碼,而handleInfraredInformation()函數(shù)則會(huì)將獲取到的紅外編碼與已經(jīng)定義好的進(jìn)行比對(duì),若符合則跳轉(zhuǎn)入相應(yīng)的代碼塊進(jìn)行處理(機(jī)器人前后左右的移動(dòng),以及遙控模式或自動(dòng)模式切換等),當(dāng)然程序也會(huì)通過(guò)調(diào)用avoidFrontObstacle()函數(shù)來(lái)判斷是否在遙控六足機(jī)器人移動(dòng)的過(guò)程中,機(jī)器人前方的障礙物距離軀體較近,若距離小于事先設(shè)定的閾值,機(jī)器人便會(huì)自動(dòng)后退或停止以進(jìn)行避讓。
#include?"hexapod_bionic_robot.h"
#define?DEBUG?1
HexapodBionicRobot::HexapodBionicRobot(IRrecv?*ir_recviver,
???????????????????????????????????????decode_results?*ir_results)
????:?ir_receiver_(ir_recviver),
??????ir_results_(ir_results)
{
????pinMode(PIN_LED,?OUTPUT);
????pinMode(PIN_TRIG,?OUTPUT);
????pinMode(PIN_ECHO,?INPUT);
????mode_flag_?=?MODE_REMOTE;
????duration_?=?0.0;
????distance_?=?0.0;
}
void?HexapodBionicRobot::avoidFrontObstacle(void)
{
????float?distance?=?getUltrasonicDistance();
????Serial.println(distance);
????if?(distance?==?false)?{
????????return?;
????}
????else?if?(distance?<=?2.5)?{
????????moveRobotBody(DIR_STOP,?2);
????}
????else?if?(distance?<=?5.0)?{
????????moveRobotBody(DIR_BACK,?2);
????}
}
void?HexapodBionicRobot::handleUltrasonicDistance(void)
{
????float?distance?=?getUltrasonicDistance();
????if?(distance?==?false)?{
????????return?;
????}
????else?if?(distance?<=?5.0)?{
????????digitalWrite(PIN_LED,?HIGH);
#if?DEBUG
????????Serial.println("Warning!?Distance?is?too?close!!!");
#endif
????}
????else?{
????????digitalWrite(PIN_LED,?LOW);
????}
#if?DEBUG
????Serial.print("Distance:?");
????Serial.print(distance);
????Serial.println("cm");
#endif
????delay(100);
}
void?HexapodBionicRobot::handleInfraredInformation(void)
{
????float?distance?=?0.0;
????uint32_t?ir_results?=?getInfraredInformation();
????if?(ir_results?==?false)?{
????????return?;
????}
????else?{
#if?DEBUG
????????Serial.print("Infrared?code:?");
????????Serial.println(ir_results,?HEX);
#endif
????????if?(ir_results?==?0XFF629D)?{
????????????mode_flag_?=?MODE_REMOTE;
????????}
????????else?if?(ir_results?==?0XFFE21D)?{
????????????mode_flag_?=?MODE_AUTO;
????????}
????????if?(mode_flag_?==?MODE_REMOTE)?{
????????????digitalWrite(PIN_LED,?LOW);
????????????if?(ir_results?==?0xFF02FD)?{
????????????????moveRobotBody(DIR_FRONT,?2);
????????????????delay(RUNTIME);
????????????}
????????????else?if?(ir_results?==?0xFF9867)?{
????????????????moveRobotBody(DIR_BACK,?2);
????????????????delay(RUNTIME);
????????????}
????????????else?if?(ir_results?==?0xFFE01F)?{
????????????????moveRobotBody(DIR_LEFT,?2);
????????????????delay(RUNTIME);
????????????}
????????????else?if?(ir_results?==?0xFF906f)?{
????????????????moveRobotBody(DIR_RIGHT,?2);
????????????????delay(RUNTIME);
????????????}
????????????else?if?(ir_results?==?0xFFA857)?{
????????????????moveRobotBody(DIR_STOP,?2);
????????????????delay(RUNTIME);
????????????}
????????????avoidFrontObstacle();
????????}
????????else?if?(mode_flag_?==?MODE_AUTO)?{
????????????digitalWrite(PIN_LED,?HIGH);
????????????while?(ir_results?!=?0XFF629D)?{
????????????????ir_results?=?getInfraredInformation();
????????????????moveRobotBody(DIR_FRONT,?2);
????????????????delay(RUNTIME);
????????????????avoidFrontObstacle();
????????????}
????????????mode_flag_?=?MODE_REMOTE;
????????}
????}
}
void?HexapodBionicRobot::moveRobotBody(uint8_t?direction,?uint8_t?times)
{
????char?string_direction[5];
????char?string_times[5];
????itoa(direction,?string_direction,?RADIX);
????itoa(times,?string_times,?RADIX);
????Serial.print("#");
????Serial.print(string_direction);
????Serial.print("G");
????Serial.print(string_times);
????Serial.println("C");
}
uint32_t?HexapodBionicRobot::getInfraredInformation(void)
{
????if?(ir_receiver_->decode(ir_results_))?{
????????ir_receiver_->resume();
????????return?ir_results_->value;
????}
????else?{
????????return?false;
????}
}
float?HexapodBionicRobot::getUltrasonicDistance(void)
{
????duration_?=?0.0;
????distance_?=?0.0;
????digitalWrite(PIN_TRIG,?LOW);
????delayMicroseconds(10);
????digitalWrite(PIN_TRIG,?HIGH);
????delayMicroseconds(10);
????digitalWrite(PIN_TRIG,?LOW);
????duration_?=?pulseIn(PIN_ECHO,?HIGH,?TIMEOUT);
????if?(duration_?==?0.0)?{
????????return?false;
????}
????else?{
????????distance_?=?duration_?*?0.017;
????????return?distance_;
????}
}
測(cè)試代碼
hexapod_bionic_robot_test.ino
該測(cè)試代碼的原理非常簡(jiǎn)單,首先setup()函數(shù)會(huì)以115200的波特率初始化并打開(kāi)串口,然后Arduino Nano會(huì)向串口發(fā)送#1G2C(1號(hào)動(dòng)作組循環(huán)運(yùn)行2次)讓六足機(jī)器人站立起來(lái),緊接著程序會(huì)使能紅外接收管,讓其可以接收遙控器發(fā)送的紅外編碼。等初始化結(jié)束后,主程序會(huì)跳轉(zhuǎn)到loop()函數(shù)執(zhí)行HexapodBionicRobot類(lèi)對(duì)象的handleInfraredInformation()函數(shù)完成紅外遙控以及超聲波避障等功能。
#include?
#include?
IRrecv?????????g_ir_receiver(PIN_IR);
decode_results?g_ir_results;
void?setup()
{
????Serial.begin(115200);
????Serial.println("#1G2C");
????g_ir_receiver.enableIRIn();
}
void?loop()
{
????HexapodBionicRobot?hexapod_bionic_robot(&g_ir_receiver,?&g_ir_results);
????hexapod_bionic_robot.handleInfraredInformation();
}
五、成果
以下是制作完成后的成果圖和測(cè)試視頻:





六、總結(jié)
回想起當(dāng)初,自己就是看了六足機(jī)器昆蟲(chóng)-你的下一個(gè)足式移動(dòng)機(jī)器人這篇教程才開(kāi)始迷上六足機(jī)器人的,沒(méi)想到大四快畢業(yè)的時(shí)候自己能有機(jī)會(huì)完成這個(gè)屬于自己的六足仿生機(jī)器人,說(shuō)實(shí)話當(dāng)看到六足機(jī)器人第一次從團(tuán)身狀態(tài)下依靠自己的力量站立起來(lái)時(shí),我的內(nèi)心是無(wú)比激動(dòng)的,盡管由于舵機(jī)的力矩偏小導(dǎo)致機(jī)器人的足體在支撐地面時(shí)會(huì)有輕微吱吱的抖動(dòng),但是得益于十八個(gè)關(guān)節(jié)自由度,六足機(jī)器人可以做出很多機(jī)器人都無(wú)法做出的復(fù)雜動(dòng)作,我想這也許就是多足機(jī)器人的魅力所在吧!
不過(guò)話說(shuō)回來(lái),對(duì)于機(jī)器人初學(xué)者來(lái)說(shuō),制作一個(gè)六足機(jī)器人的難度相較于輪式機(jī)器人還是非常大的,而且投入的時(shí)間和資金成本也比較多。如果你的動(dòng)手能力和技術(shù)水平足夠強(qiáng),且跟我一樣認(rèn)為六足機(jī)器人非??岬脑?,你也可以嘗試去做一臺(tái)屬于自己的六足機(jī)器人并為它擴(kuò)展更多有意思的功能(比如我加入了MPU6050和HMC5883L模塊來(lái)做機(jī)器人運(yùn)動(dòng)感知與矯正,可惜因時(shí)間有限沒(méi)能實(shí)現(xiàn))。最后我總結(jié)一下能成功自制六足機(jī)器人所需要的三個(gè)關(guān)鍵因素:1、從始至終發(fā)自?xún)?nèi)心的熱愛(ài);2、擁有機(jī)械、電子和軟件方面的專(zhuān)業(yè)知識(shí);3、為實(shí)現(xiàn)最終目標(biāo)而堅(jiān)持不懈的努力!
文章作者:繆宇飏,myyerrol ?轉(zhuǎn)載于:https://myyerrol.io/zh-cn/2018/05/21/diy_robots_2_hexapod_bionic_robot/
推薦閱讀:
關(guān)注公眾號(hào),后臺(tái)回復(fù)「1024」獲取學(xué)習(xí)資料網(wǎng)盤(pán)鏈接。
歡迎點(diǎn)贊,關(guān)注,轉(zhuǎn)發(fā),在看,您的每一次鼓勵(lì),我都將銘記于心~
