摘要:經過大一那次失敗之后,我決定暫時停止該項目的開發,轉而先去學習那些有關嵌入式開發的基礎知識,等以后有能力的時候再去獨立完成這個六足機器人。很幸運的是在我大學本科即將結束的時候,我已掌握了足夠的知識來完成那個曾經困擾我已久的機器人項目,于是我花了幾周的時間完成了這個六足機器人,算是了卻了自己的一個心愿吧。
一、前言
這個六足機器人是我在大四做的,是我大學本科生涯的最后一個個人項目。至于為什么我要做六足機器人,還要從高考完之后說起:當時剛考完的我一直想做一些有意思的事情,直到有一天我發現了一個叫PVCBOT的網站,里面記錄了很多如何使用PVC材料來制作簡單機器人的教程,其中有一款叫做PVC六足機器昆蟲的機器人徹底震撼了我,當時看完教程之后我就下定決心也要做一個類似的六足機器人,于是我便從懶貓俠前輩那里購買了六足機器人套件(目前應該已經絕版了),并打算按照提供的教程完成自己的六足機器人,但無奈當時的我所掌握的知識太少,什么單片機、串口通信、舵機PWM、電源管理、傳感器、舵機控制板等都不懂,特別是機械結構方面我更是一竅不通,所以大一那會兒我還鬧出了笑話:用硬紙板做六足機器人的肢體,在安裝好舵機并通電測試后,眼睜睜地看著自己的“紙板六足”在舵機的震動下不斷地解體。。。
二、概述
六足仿生機器人是一個擁有十八個關節自由度的迷你多足機器人,它可以實現紅外遙控、超聲波避障等基本功能。機器人的硬件核心為Arduino Nano,并采用串口通信的方式與24路舵機控制板進行數據交互,從而間接完成對所有舵機旋轉角度的精確控制,最終使機器人能夠以各種不同的步態進行移動。當然,這個機器人項目的軟件依舊開源,具體代碼可以從我的GitHub倉庫上獲得。
三、制作
六足機器人的整個制作過程主要分為機械和電子兩部分,由于教程中每一步的圖片都非常清楚,所以機械這部分沒花費我太多的時間和精力。而電子部分則全部是我自己設計的,雖然原理難度不大,但是要根據機器人的機械結構來選擇洞洞板的擺放位置并且要完成其上電子元件的布局和焊接工作確實也比較費功夫,而且有的時候如果處理的不好還要返工,不過所幸自己在焊電路前就已經規劃好了,所以電路部分的制作也還算順利。
在接下來的篇幅中,我會盡可能詳細地講解機器人制作過程中的一些具體步驟和細節,如果你對機器人的原理和最后的效果更感興趣的話,可以跳過本小節直接閱讀原理和效果章節。
3.1 機械
六足小腿
如下圖所示,六足的小腿部分主要由兩片PVC材質的肢體通過疊加而成,而關節部分則使用的是9G金屬齒舵機,只要兩個自攻螺絲便可將PVC肢體牢牢固定在舵機上,從而保證六足小腿在與地面接觸時可以有足夠的力量來支撐整個軀體。
因為是六足機器人,所以同樣結構的小腿要再做五個出來。注意:機器人的軀體每邊有三個小腿,左右兩兩對稱,所以在組裝的時候肢體和舵機安裝的位置是有講究的,要保證結構對稱且不能裝反。
六足大腿
關節
六足大腿的關節結構比之前介紹過的小腿關節要略微復雜一些,因為大腿的關節包含了機器人足體上下和前后兩個維度的運動,所以需要兩個舵機來實現。如下圖所示,首先我們使用螺絲將一個舵機固定在方形的關節肢體里。
接著我們要重復以上的安裝步驟再制作出六個類似的肢體結構。不過在制作的過程中也要注意機器人左右兩側各三個肢體結構要保持對稱。
然后我們需要將六個舵機分別插入到之前預留好的肢體空槽里,并保證每組的兩個舵機在位置上是互相垂直的,即下圖中舵機圓形旋轉軸的朝向要一前一上。
接下來安裝六足大腿關節的固定片,即將固定片卡到下圖中正面那個舵機的圓形旋轉軸上。固定片,顧名思義是用來固定的,用在這里主要是防止關節處的兩個舵機因足體的震動而彼此之間出現位置上的偏移。
最后分別使用兩條塑料扎帶對每組關節進行進一步的加固,其中一條從固定片上方穿過,起到束緊固定片的作用,而另一條則穿過關節側面的小孔對結構進行固定。
大腿
六足的大腿是由兩個PVC材質的長方形連桿組成,從下圖中可以很清楚地看到每個連桿的左右兩側均安裝有配套的舵盤,它們的作用主要是用于連接六足的小腿關節和大腿關節。
六足足體
如下圖所示,使用螺絲將之前已經制作好的六對小腿和大腿肢體對應連接在一起。雖然擰螺絲本身沒什么難度,但是在哪個位置用螺絲來固定舵機還是有規定的:即舵機在被肢體連接固定之前要讓其旋轉軸回歸到原始的中點位置上(旋轉范圍為0~180°的舵機,其中點位置為90°),這樣做的目的是讓所有的舵機都能夠擁有最合適的運動范圍,從而防止機器人在移動時出現足體運動不對稱的情況。至于如何讓舵機回歸中點,一種辦法是使用現成的舵機調試板,只要移動旋鈕便可調節舵機的位置;另一種是編寫Arduino程序,讓舵機在上電后自動歸中。我用的是第二種方法,感覺效果還不錯。
接下來,我們要把六足的足體全部安裝到其頂部軀體上。同理,在安裝前要確保需要連接固定的舵機已經回歸到中點位置,除此之外還要提前規定好軀體的哪一側是機器人的頭部,哪一端是機器人的尾部,不要在安裝的時候把足體裝反了。
如圖所示,我們首先可以找一個稍微有點高度的物品將機器人頂部墊高,然后使用扎帶依次將每個足體的三條舵機線捆綁起來,這樣不僅看上去更加美觀,便于之后的整理和連線,而且也可以有效阻止舵機線與運動中的足體發生纏繞甚至被扯斷等情況的出現,畢竟自己大學在機器人基地的時候就曾親身經歷過電機線在機械臂移動的過程中被狠狠地扯斷的悲劇。。。
最后,我們只需要把鋰電池用扎帶固定在底部軀體的尾部,然后將供電線和充電線分別引出,再把所有已經扎好的舵機線按照順序塞到軀體當中,并用螺絲將頂部和底部兩個軀體擰緊合二為一便大功告成了(由于這部分沒有拍照,所以就用文字敘述了orz)。
3.2 電子
電源管理
下圖是機器人的電源管理模塊。電源管理模塊主要包含電源、降壓電路和控制電路等,具體的原理部分請看下面原理中的電源管理章節。
下圖是電源管理模塊的背面。為了讓焊接后的電路保持整齊、美觀,我盡可能采用錫接走線的方式來完成各元件的電氣連接,而沒辦法走線的地方才使用傳統的飛線進行連接。盡管錫接走線的優點很明顯,但是它的缺點也比較突出:一個是浪費焊錫,另一個就是容易短路,其中短路問題對機器人的影響還是挺嚴重的,我記得自己之前就有一次不小心把已經上電的電源管理模塊隨意放在六足機器人的頂部軀體上,令我沒想到的是固定軀體的螺絲的頭部正好卡在電路背面電源正負極錫接走線的中間,結果可想而知。
所以,在上電測試之前,大家要先用萬能表對焊接過的電路進行短路測試,一定要確保沒有多余的焊錫渣殘留在電路板上,而且對于使用錫接走線方式焊接的電路板,一定不要讓其背面直接與潛在具有導電功能的介質進行接觸,可以適當地使用銅柱將板子架高或者用熱熔膠把板子背面全都覆蓋住,以防止短路問題的發生。
在確保電路不存在任何可能潛在的短路問題后,可像下圖所示的那樣,對電路模塊進行上電測試。測試主要檢測電源降壓是否達到預期設定的數值,開關的通斷邏輯是否正確等。
控制單元
下圖是機器人的控制單元模塊。該控制單元模塊主要由Arduino Nano控制板、HMC58883L電子羅盤傳感器、MPU6050慣性測量傳感器(圖中的底座上未插入)、HC-SR04超聲波傳感器和紅外接收管等組成,為了方便在模塊出現問題時能夠對其進行更換,我在洞洞板上焊接了一些棑母底座,這樣模塊就可以直接插在棑母底座上,拆卸很方便。此外,有關電路原理部分的詳細介紹可以閱讀下面的原理章節。
下圖是控制單元模塊的背面。跟上面已經介紹過的電源管理模塊一樣,我使用的依然是錫接走線+飛線的方式對元件進行焊接,由于電氣連接比較多,所以焊完之后要對電路進行更加全面和仔細的檢查。
如下圖所示,由于我的Arduino Nano控制板的USB轉串口在之前的尋光小車實驗中因短路問題被燒壞了,所以我用的是專門為Arduino最小系統板燒寫Bootloader的USBtinyISP編程器來下載程序。經測試,所有模塊均能正常工作,那么接下來的工作就只剩下將機器人全部組裝好,然后編寫和調試代碼了。
四、原理
4.1 硬件
以下是該仿生六足機器人的硬件系統連接圖:
由上圖可知,六足機器人的硬件系統主要由舵機控制、電源管理、核心主控、數據感知和數據通信共五部分組成,接下來進行詳細的介紹:
舵機控制
金屬齒舵機
本項目六足機器人所配備的舵機具體型號為YZW Y09G,由于該舵機內部電機減速齒輪組使用金屬材質打造,所以其價格上要比常見的輝盛SG90塑料齒舵機貴一些,但是性能卻相當出色。該舵機標準輸入電壓范圍為4.8v~6.0v(電壓稍大于6v也沒問題),扭矩范圍在1.3kg/cm~1.6kg/cm之間,經測試,十八個舵機共同作用的扭矩可以基本滿足支撐機器人軀體以及鋰電池等相關負載的需求。當然,由于定位精度有限,所以舵機會存在控制上的死區問題,我的解決辦法主要是通過軟件補差的方式來消除這個機械結構上的誤差,使機器人能夠盡可能準確地到達預定的目標位置。
舵機控制板
舵機控制板顧名思義就是能夠用于控制多個舵機的電路板,由于傳統通過編寫程序讓單片機輸出多路PWM控制信號對于大部分的機器人愛好者來說比較復雜,所以就有高手們將MCU和相關外圍電路封裝在一起開發了便于使用的舵機控制板。此外,舵機控制板一般都會帶有一個PC端的調試軟件,只要在建立串口通信的前提下拖動軟件界面上的滑塊,便能精確且實時地操控舵機的旋轉角度,而且還能將調試好的動作組合在一起形成動作組并下載到舵機控制板的芯片中進行保存,為之后核心主控通過串口對其進行調用奠定基礎。本項目六足機器人使用的是懶貓俠早期開發的一款24路舵機控制板,具體使用方法見24路舵機控制板板使用說明。
電源管理
電源管理應該算是機器人硬件控制系統里除了核心主控之外最重要的模塊了,畢竟傳感器壞了機器人還能夠四處移動,但是電源部分壞了的話機器人可就只是一個靜止的模型了。由于本項目六足機器人采用十八個舵機作為關節執行器,所以盡管9G舵機的耗電量相對標準舵機要小很多,但是十八個舵機加起來所需要的電流大小還是相當驚人的,因此經過一段時間的考量,我最終選擇了一款參數為7.4v850mAh的鋰電池組作為機器人的電源,其電能滿足六足機器人的動力需求。
除了鋰電池電源之外,從上面的硬件系統連接圖中還可以看到有兩個降壓電路,其中一個降壓電路使用L2596 DC-DC模塊將一路電源的電壓降到標準的5V,用于給Arduino Nano主控制板供電,而另一路使用的是D25XB80大功率整流橋,它擁有標稱800V的最大逆向電壓和25A的額定前向電流,在鋰電池組充滿電的情況下(標稱7.4v的鋰電池組充滿電的電壓大概在8.4v左右),連接一片D25XB80可以使電壓整體降到大概6.9v,經測試給24路舵機控制板和18個舵機供電是沒有問題的。
最后為了方便控制鋰電池電源的輸入和降壓后電源的輸出,我并聯連接了三個開關,并在并聯支路中分別加入了三個LED燈用作電源閉合或斷開的顯示。關于電源管理的其他內容,大家可以參考一下懶貓俠寫的六足機器人動力的分析 這篇博文。
核心主控
核心主控主要負責分析傳感器反饋回來的數據,然后給舵機控制板發出動作指令,間接驅動舵機運行到指定角度。在本項目中我使用的核心主控為Arduino Nano,它體型較小,且擁有非常豐富的開發教程和器件驅動庫,很容易上手。
數據感知
數據感知模塊主要包括HC-04超聲波測距傳感器、HMC5883L電子羅盤傳感器、MPU6050慣性測量傳感器和紅外接收管,其中超聲波測距傳感器用來幫助六足機器人避開其正前方的障礙物,而紅外接收管則和常見的迷你紅外遙控器一同構成了整個六足機器人的遙控系統,紅外接收管能夠接收經過38kHz載頻二次調制生成的紅外信號,并將解碼后的數據發送給Arduino Nano主控進行相關處理。HMC58883L和MPU6050這兩個傳感器主要用于六足機器人的運動感知,通過采集它們的數據并進行簡單的融合處理便能得到機器人在空間中的位置關系,從而為之后修正機器人在移動過程中的路徑偏差提供數據上的保障。不過由于當時開發時間有限,所以這一部分暫未涉及。
數據通信
數據通信包括紅外通信、串口通信和藍牙通信三部分。其中,紅外通信在上面的數據感知部分已經進行過簡要的介紹了,即采用NEC的編碼格式將數據進行相應的編碼或解碼,并通過紅外線的方式完成遙控指令數據的傳輸;串口通信則主要用在核心主控和舵機控制板之間,根據舵機控制板所規定的數據格式,主控能夠發送指令來控制一個舵機或多個舵機旋轉到指定的位置;最后的藍牙通信可以使PC端上的軟件與舵機控制板之間建立起無線連接,方便六足機器人動作的調試。
4.2 軟件
核心類庫
hexapod_bionic_robot.h
該頭文件定義了HexapodBionicRobot類,里面聲明了機器人避障、處理紅外編碼信息、處理超聲波距離、獲取紅外編碼信息、獲取超聲波距離和移動機器人軀體等核心函數。
#ifndefHEXAPOD_BIONIC_ROBOT_H #defineHEXAPOD_BIONIC_ROBOT_H #include#include #definePIN_IR2 #definePIN_TX3 #definePIN_RX4 #definePIN_TRIG5 #definePIN_ECHO6 #definePIN_LED13 #defineDIR_INIT1 #defineDIR_STOP1 #defineDIR_FRONT2 #defineDIR_BACK3 #defineDIR_LEFT4 #defineDIR_RIGHT5 #defineMODE_REMOTE25 #defineMODE_AUTO26 #defineRADIX10 #defineRUNTIME2400 #defineTIMEOUT30000 classHexapodBionicRobot { public: HexapodBionicRobot(IRrecv*ir_receiver,decode_results*ir_results); voidavoidFrontObstacle(void); voidhandleInfraredInformation(void); voidhandleUltrasonicDistance(void); voidmoveRobotBody(uint8_tdirection,uint8_ttimes); uint32_tgetInfraredInformation(void); floatgetUltrasonicDistance(void); private: intmode_flag_; floatduration_; floatdistance_; IRrecv*ir_receiver_; decode_results*ir_results_; }; #endif//HEXAPOD_BIONIC_ROBOT_H
hexapod_bionic_robot.cpp
該源文件實現了HexapodBionicRobot類里面所有已經聲明的函數,其中getInfraredInformation()函數調用了官方的IRremote庫,可以實時獲取紅外遙控器所發送的紅外編碼,而handleInfraredInformation()函數則會將獲取到的紅外編碼與已經定義好的進行比對,若符合則跳轉入相應的代碼塊進行處理(機器人前后左右的移動,以及遙控模式或自動模式切換等),當然程序也會通過調用avoidFrontObstacle()函數來判斷是否在遙控六足機器人移動的過程中,機器人前方的障礙物距離軀體較近,若距離小于事先設定的閾值,機器人便會自動后退或停止以進行避讓。
#include"hexapod_bionic_robot.h" #defineDEBUG1 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; } voidHexapodBionicRobot::avoidFrontObstacle(void) { floatdistance=getUltrasonicDistance(); Serial.println(distance); if(distance==false){ return; } elseif(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(); returnir_results_->value; } else{ returnfalse; } } floatHexapodBionicRobot::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){ returnfalse; } else{ distance_=duration_*0.017; returndistance_; } }
測試代碼
hexapod_bionic_robot_test.ino
該測試代碼的原理非常簡單,首先setup()函數會以115200的波特率初始化并打開串口,然后Arduino Nano會向串口發送#1G2C(1號動作組循環運行2次)讓六足機器人站立起來,緊接著程序會使能紅外接收管,讓其可以接收遙控器發送的紅外編碼。等初始化結束后,主程序會跳轉到loop()函數執行HexapodBionicRobot類對象的handleInfraredInformation()函數完成紅外遙控以及超聲波避障等功能。
#include#include IRrecvg_ir_receiver(PIN_IR); decode_resultsg_ir_results; voidsetup() { Serial.begin(115200); Serial.println("#1G2C"); g_ir_receiver.enableIRIn(); } voidloop() { HexapodBionicRobothexapod_bionic_robot(&g_ir_receiver,&g_ir_results); hexapod_bionic_robot.handleInfraredInformation(); }
五、成果
以下是制作完成后的成果圖和測試視頻:
六、總結
回想起當初,自己就是看了六足機器昆蟲-你的下一個足式移動機器人這篇教程才開始迷上六足機器人的,沒想到大四快畢業的時候自己能有機會完成這個屬于自己的六足仿生機器人,說實話當看到六足機器人第一次從團身狀態下依靠自己的力量站立起來時,我的內心是無比激動的,盡管由于舵機的力矩偏小導致機器人的足體在支撐地面時會有輕微吱吱的抖動,但是得益于十八個關節自由度,六足機器人可以做出很多機器人都無法做出的復雜動作,我想這也許就是多足機器人的魅力所在吧!
不過話說回來,對于機器人初學者來說,制作一個六足機器人的難度相較于輪式機器人還是非常大的,而且投入的時間和資金成本也比較多。如果你的動手能力和技術水平足夠強,且跟我一樣認為六足機器人非常酷的話,你也可以嘗試去做一臺屬于自己的六足機器人并為它擴展更多有意思的功能(比如我加入了MPU6050和HMC5883L模塊來做機器人運動感知與矯正,可惜因時間有限沒能實現)。最后我總結一下能成功自制六足機器人所需要的三個關鍵因素:1、從始至終發自內心的熱愛;2、擁有機械、電子和軟件方面的專業知識;3、為實現最終目標而堅持不懈的努力!
-
硬件
+關注
關注
11文章
3312瀏覽量
66200 -
網站
+關注
關注
2文章
258瀏覽量
23157 -
六足機器人
+關注
關注
9文章
23瀏覽量
17040
原文標題:手把手教你自制六足仿生機器人
文章出處:【微信號:All_best_xiaolong,微信公眾號:大魚機器人】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論