單片機智能小車設(shè)計程序文件_第1頁
單片機智能小車設(shè)計程序文件_第2頁
單片機智能小車設(shè)計程序文件_第3頁
單片機智能小車設(shè)計程序文件_第4頁
單片機智能小車設(shè)計程序文件_第5頁
已閱讀5頁,還剩31頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、. . . . 課程設(shè)計作品:自動避障小車   組員:常凱 旭 鞏靖 一、前言 設(shè)計背景: 在科學(xué)探索和緊急搶險中經(jīng)常會遇到對與一些危險或人類不能直接到達(dá)的地域的探測,這些就需要用機器人來完成。而在機器人在復(fù)雜地形中行進(jìn)時自動避障是一項必不可少也是最基本的功能。因此,自動避障系統(tǒng)的研發(fā)就應(yīng)運而生。我們的自動避障小車就是基于這一系統(tǒng)開發(fā)而成的。 意義 隨著科技的發(fā)展,對于未知空間和人類所不能直接到達(dá)的地域的探索逐步成為熱門,這就使機器人的自動避障有了重大的意義。我們的自動避障小車就是自動避障機器人中的一類。自動避障小車可以作為地域探索機器人和緊急搶險機器人的運動系統(tǒng),讓機器人在行進(jìn)中自

2、動避過障礙物。 成員情況 本組三位成員均為2005級基地班學(xué)生,都選修過數(shù)字電路課程。 二、總體方案設(shè)計 1、設(shè)計要求 小車從無障礙地區(qū)啟動前進(jìn),感應(yīng)前進(jìn)路線上的障礙物后,根據(jù)障礙物的位置選擇下一步行進(jìn)方向。并可通過兩個獨立按鍵對小車進(jìn)行控速。 2、小車自動避障的原理小車車頭處裝有三個光電開關(guān),中間一個光電開關(guān)對向正前方,兩側(cè)的光電開關(guān)向兩邊各分開30度,(如右圖所示)。小車在行進(jìn)過程中由光電開關(guān)向前方發(fā)射出紅外線,當(dāng)紅外線遇到障礙物時發(fā)生漫反射,反射光被光電開關(guān)接收。小車根據(jù)三個光電開關(guān)接受信號的情況來判斷前方障礙物的分布并做出相應(yīng)的動作。光電開關(guān)的平均探測距離為30cm。 3、模塊方案比較

3、與論證 根據(jù)設(shè)計要求,我們的自動避障小車主要由六個模塊構(gòu)成:車體框架、電源與穩(wěn)壓模塊、主控模塊、邏輯模塊、探測模塊、電機驅(qū)動模塊組成。 各模塊分述如下:3.1車體框架 在設(shè)計車體框架時,我們有兩套起始方案,自己制作和直接購買玩具電動車。 方案一:自己設(shè)計制作車架 自己制作小車底盤,用兩個直流減速電機作為主動輪,利用兩電機的轉(zhuǎn)速差完成直行、左轉(zhuǎn)、右轉(zhuǎn)、左后轉(zhuǎn)、右后轉(zhuǎn)、倒車等動作。減速電機扭矩大,轉(zhuǎn)速較慢,易于控制和調(diào)速,符合避障小車的要求。而且自己制作小車框架,可以根據(jù)電路板與傳感器安裝需求設(shè)計空間,使得車體美觀緊湊。但自己制作小車設(shè)計制作周期較長,且費用較高,因而我們放棄這一方案。 方案二:購

4、買玩具電動車 玩具電動車價格低廉,有完整的驅(qū)動、傳動和控制單元,其中傳動裝置是我們所需的,縮短了開發(fā)周期。但玩具電動車采用普通直流電機驅(qū)動,帶負(fù)載能力差,調(diào)速方面對程序要求較高。同時,玩具電動車轉(zhuǎn)向依靠前輪電機帶動前輪轉(zhuǎn)向完成,精度低。 考慮到利用玩具電動小車做車架開發(fā)周期短,可留夠充分的時間用于系統(tǒng)調(diào)試,且硬件上的不足我們有信心用優(yōu)良的算法來彌補,故我們選擇方案二。 3.2電源與穩(wěn)壓模塊 方案一:采用交流電經(jīng)直流穩(wěn)壓處理后供電 采用交流電提供直流穩(wěn)壓電源,電流驅(qū)動能力與電壓穩(wěn)定性最好,且負(fù)載對電源影響也最小。但由于需要電線對小車供電,極大影響了壁障小車行動的靈活性與地形的適應(yīng)能力。而且壁障小

5、車極易把拖在地上的電線識別為障礙物,人為增加了不必要的障礙。故我們放棄了這一方案。 方案二:采用蓄電池供電 蓄電池具有較強的電流驅(qū)動能力和較好的電壓穩(wěn)定性能,且成本低廉??刹捎眯铍姵亟?jīng)7812芯片穩(wěn)壓后給電機供電,再經(jīng)過降壓接7805芯片給單片機與其他邏輯單元供電。但蓄電池體積相對龐大,且重量過大,造成電機負(fù)載過大,不適合我們采用的小車車架(玩具電動車車架)。故我們放棄了這一方案。 方案三:采用干電池組進(jìn)行供電 采用四節(jié)干電池降壓至5V后給單片機與其他邏輯單元供電,另取六節(jié)干電池為電機與光電開關(guān)供電。這樣電機啟動與制動時的短暫電壓干擾不會影響到邏輯單元和單片機的工作。干電池用電池盒封裝,體積和

6、重量較小,同時玩具車底座可以安裝四節(jié)干電池,正好可為單片機與其他邏輯單元供電。在穩(wěn)壓方面,起始時考慮使用7805芯片對6V的電池電壓進(jìn)行降壓穩(wěn)壓。但考慮到這樣使得7805芯片消耗大量能量,降低電池壽命;同時,由于mega16、光電開關(guān)、小車電機對于供電電壓要求并不苛刻,故我們將6V電池電壓接一個二極管降壓后直接給單片機與其他邏輯單元供電。而電機和光電開關(guān)的電源不做穩(wěn)壓處理。這樣只需在小車主板上加兩個調(diào)速按鈕,根據(jù)電池電量選擇合適功率即可,甚至于可直接在軟件里設(shè)置自動換擋。 綜合考慮,我們采用方案三。示意圖如下 3.3主控模塊 作為單片機原理與接口技術(shù)課程的course project,我們直接

7、選用了課程主要介紹的,Atmel公司的ATmaga16L單片機作為主控模塊。 Mega16是高性能、低功耗的 8 位AVR 微處理器,具有先進(jìn)的RISC結(jié)構(gòu),部集成兩個具有獨立預(yù)分頻器和比較器功能的8 位定時器/ 計數(shù)器和一個具有預(yù)分頻器、比較功能和捕捉功能的16 位定時器/ 計數(shù)器??赏ㄟ^JTAG對MCU進(jìn)行程序燒寫與仿真。置晶振,使用方便。 在設(shè)計開發(fā)過程中我們使用課程設(shè)計提供的開發(fā)板進(jìn)行程序調(diào)試和下載,配車使用時直接將MCU拔出插入我們小車系統(tǒng)電路板底座中。示意圖如下: 3.4 邏輯模塊 在探測模塊和單片機中斷接口之間、獨立按鍵與單片機中斷接口之間,需要經(jīng)過電平的邏輯處理進(jìn)行連接。主要涉

8、與到一個三輸入或非門和一個二輸入與門。這兩個邏輯關(guān)系我們直接選用74HC系列的集成芯片實現(xiàn)。 由于三輸入或非門在市場上很難購買到,我們采用了兩個二輸入或非門和一個二輸入與門完成了三輸入或非門。由于我們采用的74HC08(四二輸入與門)、74HC02(四二輸入或非門)均為四二輸入的,各提供四個二輸入與門和四個二輸入或非門,我們用各用一片芯片即可實現(xiàn)所需邏輯功能。 示意圖如下: 3.5探測模塊 方案一:使用超聲波探測器 超聲波探測器探測距離遠(yuǎn),測距方便。但由于聲波衍射現(xiàn)象較嚴(yán)重,且波包散面太大,易造成障礙物的錯誤判斷。同時,超聲波探測具有幾厘米甚至幾十厘米的盲區(qū),這對于我們的避障小車是個致命的限制

9、。故我們放棄了這一方案。 方案二:使用光電對管探測 光電對關(guān)價格低廉,性能穩(wěn)定,但探測距離過近(一般不超過3cm),使得小車必須制動迅速。而我們由于采用普通直流電機作為原動力,制動距離至少需要10cm。因此我們放棄了這一方案。 方案三:使用視頻采集處理裝置進(jìn)行探測 使用CCD實時采集小車前進(jìn)路線上的圖像并進(jìn)行實時傳輸與處理,這是最精確的障礙物信息采集方案,可以對障礙物進(jìn)行精確定位和測距。但是使用視頻采集會大大增加小車成本和設(shè)計開發(fā)難度,而且考慮到我們小車行進(jìn)轉(zhuǎn)彎的精確度并未達(dá)到視頻處理的精度,因而使用視頻采集在實際應(yīng)用中是個很大的浪費,所以我們放棄了這一方案。 方案四:使用光電開關(guān)進(jìn)行障礙物信

10、息采集 使用三只E3F-DS30C4光電開關(guān),分別探測正前方,前右側(cè),前左側(cè)障礙物信息,在特殊地形(如障礙物密集地形)可將正前方的光電開關(guān)移置后方進(jìn)行探測。E3F-DS30C4光電開關(guān)平均有效探測距離030cm可調(diào),且抗外界背景光干擾能力強,可在日光下正常工作(理論上應(yīng)避免日光和強光源的直接照射)。我們小車換檔調(diào)速后的最大制動距離不超過30cm,一般在1020cm左右,因而探測距離滿足我們的小車需求。 綜上考慮,我們選用方案四。示意圖如下: 3.6電機驅(qū)動模塊 方案一:使用分立原件搭建電機驅(qū)動電路 使用分立原件搭建電機驅(qū)動電路造價低廉,在大規(guī)模生產(chǎn)中使用廣泛。但分立原件H橋電路工作性能不夠穩(wěn)定

11、,較易出現(xiàn)硬件上的故障,故我們放棄了這一方案。 方案二:使用L298N芯片驅(qū)動電機 L298N是一個具有高電壓大電流的全橋驅(qū)動芯片,輸出電壓最高可達(dá)50V,可以直接通過電源來調(diào)節(jié)輸出電壓;可以直接用單片機的IO口提供信號,而且?guī)в惺鼓芏耍奖鉖WM調(diào)速,電路簡單,性能穩(wěn)定,使用比較方便。L298N芯片可以驅(qū)動兩個二相電機,也可以驅(qū)動一個四相電機,正好符合我們小車兩個二相電機的驅(qū)動要求。 綜合考慮,我們采用L298N芯片驅(qū)動小車電機。 控制示意圖如下:? 最終方案如下: 使用干電池組對系統(tǒng)供電,改造玩具電動車作為小車底座,采用Mega16L作為主控芯片,采用E3F-DS30C4光電開關(guān)進(jìn)行障礙物

12、探測,使用L298N驅(qū)動直流電機。邏輯關(guān)系處理使用74HC系列芯片完成。 三、單元模塊設(shè)計 1、各單元模塊功能介紹與電路設(shè)計 自動避障小車系統(tǒng)的整體電路原理圖如下:?  1.1 直流電源降壓 經(jīng)過測量,一般四節(jié)新南孚電池串聯(lián)帶負(fù)載后可提供5.8V電壓。經(jīng)過二極管穩(wěn)壓至5.15.2V后給邏輯器件供電并給系統(tǒng)提供高電平標(biāo)準(zhǔn)。?1.2 主控芯片使用Mega 16L的PA0PA3接電機驅(qū)動芯片L298N的IN1IN4,實現(xiàn)對電機驅(qū)動芯片的控制,進(jìn)而控制電機的轉(zhuǎn)動。 使用Mega 16L的PB0PB2接經(jīng)過電平轉(zhuǎn)換的探測器信號線,實現(xiàn)對障礙物信息的采集。 使用Mega 16L的PC0、PC1接

13、受獨立按鍵信號,實現(xiàn)對小車行進(jìn)過程中速度的控制。由于我們小車電機電源沒有經(jīng)過穩(wěn)壓,隨著電池電量的消耗,電機電池組的電壓逐漸降低,因而小車速度會發(fā)生變化。我們就可以通過獨立按鍵對速度進(jìn)行提前設(shè)定,使得即使電池組電量變化,小車也能按預(yù)定速度行進(jìn)。 使用Mega 16L的PD2、PD3接收中斷信息。在軟件部分我們可以看到,隨著程序的不斷完善,最終我們的INT0,即PD2并沒有使用。 使用引腳10為單片機供電,引腳31接地。?1.3 邏輯模塊 設(shè)計任務(wù): 三個傳感器信號線給出邏輯電平信號,當(dāng)任何一個是高電平時,給INT0一個低電平信號。(如上一部分所述,最終我們用定時器中斷代替了這個外部中斷,但作為硬

14、件設(shè)計和焊接的一部分,我們還是給以闡釋)。 兩個獨立按鍵分別控制提速和減速,沒有按下時,信號線給出高電平。當(dāng)任意一鍵按下時,信號線給出低電平,同時給出一個低電平給INT1。 任務(wù)實現(xiàn): 第一個任務(wù)的實現(xiàn)原本想采用三輸入或非門74HC27 實現(xiàn)。但由于市場上缺乏供應(yīng),我們用74HC08的一個二輸入與門和74HC02的兩個二輸入或非門完成。?第二個任務(wù)邏輯的實現(xiàn)使用74HC08的一個與門實現(xiàn)。按鍵功能的實現(xiàn),是使用了兩個5K1的電阻分別連接兩個按鍵與邏輯高電平(+5V),無鍵按下電平上拉至邏輯高電平,有鍵按下時降至0V。 1.4 探測模塊 探測模塊的電路圖:設(shè)計任務(wù): 1. 三個光電開關(guān)探測前方障

15、礙物。 2. 將光電開關(guān)傳回的非標(biāo)準(zhǔn)的開關(guān)電平信號轉(zhuǎn)換成CMOS標(biāo)準(zhǔn)電平(即將09V轉(zhuǎn)換成05V)。 任務(wù)實現(xiàn): 1. 光電開關(guān)發(fā)射出的紅外線在經(jīng)障礙物漫反射后會由光電開關(guān)再接收到,這會引起光電開關(guān)傳回的電平的變化。若前方有障礙物,則光電開關(guān)傳回低電平;若前方無障礙物,則光電開關(guān)傳回的是高電平。有電平的變化可以實現(xiàn)對前方障礙物的探測。 2. 光電開關(guān)傳回的信號是非標(biāo)準(zhǔn)的電平信號,這對于Mega16芯片是不適用的。因此,我們使用了三個8050三極管來實現(xiàn)電平的轉(zhuǎn)換。由三極管的電氣特性,當(dāng)其基極為低電平時,即基極發(fā)射極電壓小于導(dǎo)通壓降,其輸出電平為高電平,在其輸出端有用一個5K1的電阻上拉,使輸出

16、的高電壓為+5V;而在基極為高電平時,三極管發(fā)射極正偏,輸出電平為0。這樣輸出電平已經(jīng)轉(zhuǎn)化為CMOS標(biāo)準(zhǔn)電平。不過,這時傳回到Mega16的電平信號已經(jīng)和原來光電開關(guān)傳回的信號高低相反,但這并不影響前方障礙物的探測。 1.5 電機驅(qū)動模塊 電機驅(qū)動模塊的電路圖: 電機驅(qū)動模塊主要功能是將主控芯片發(fā)出的信號通過L298N電機控制芯片轉(zhuǎn)化為小車實際的動作。 L298N芯片有兩個電源引腳VDD引腳和VCC引腳。VDD引腳接+9V電源用來給電機供電,VCC引腳接+5V電源用來給芯片供電,并作為邏輯高電平標(biāo)準(zhǔn)。 L298N芯片通過一個有四個4148二極管組成的保護(hù)電路與電機相連,保護(hù)電路主要是用來在電機

17、開啟和關(guān)閉時泄流之用。 由于我們一直讓轉(zhuǎn)向電機以最大功率使能從而獲得最大的扭矩,保證小車轉(zhuǎn)向成功,而不需要控制轉(zhuǎn)向電機的輸出功率,所以ENA引腳(即轉(zhuǎn)向電機使能引腳)直接接 +5 V,即讓轉(zhuǎn)向電機一直使能。 對于后置的驅(qū)動電機,我們不僅要控制其實現(xiàn)前進(jìn)、后退和停止,還要能夠控制其轉(zhuǎn)速以解決由于電量不足而產(chǎn)生的小車變慢的問題。所以,我們將L298N芯片的ENB引腳與Mega16的PB3引腳(即OC0)連接,用來實現(xiàn)PWM調(diào)速。 L298N芯片的IN1和IN2引腳分別和Mega16的PA1和PA0引腳連接用來接收主控芯片輸出的轉(zhuǎn)向電機的動作指令,并通過OUT1和OUT2來控制轉(zhuǎn)向電機的正轉(zhuǎn)與反轉(zhuǎn),

18、最終功能的實現(xiàn)表現(xiàn)在小車的左轉(zhuǎn)與右轉(zhuǎn)。 L298N芯片的IN3和IN4引腳分別與Mega16的PA3和PA2引腳連接用來接收主控芯片輸出的驅(qū)動電機的動作指令,并通過OUT3和OUT4來控制驅(qū)動電機的正轉(zhuǎn)與反轉(zhuǎn),最終功能的實現(xiàn)表現(xiàn)在小車的前進(jìn)、后退、停止。 2、所用全部硬件資源 增強版ATMega 16L/32開發(fā)板(進(jìn)行程序的初步調(diào)試) 簡版JTAG仿真器(程序的下載和仿真) 遙控電動玩具車 E3F-DS30C4光電開關(guān)3只 Mega 16L單片機1片 L298N電機驅(qū)動芯片1片 74HC02芯片、74HC08芯片各1片 8050NPN三極管3只,4148二極管8只 實驗電路板1只 5K1電阻

19、5只,10K電阻2只 散熱片1只 獨立按鍵2只 40引腳底座1只 電池盒2只 南孚電池6節(jié),華太電池4節(jié) 5列裝排線1米左右 502粘合劑1瓶 四、程序設(shè)計和調(diào)試過程 1、程序調(diào)試過程 目前程序已經(jīng)經(jīng)歷了四個主要版本,對尋障避障的方法前后有較大的改變。 1.1最初的程序設(shè)計主流程圖:?INT0中斷觸發(fā) 端口值是多少? 檢測傳感器端口的反饋值 前方有障礙物 根據(jù)檢測到的障礙物情況(分7種),從7個動作函數(shù)中選擇一個執(zhí)行 前進(jìn) 等待下次中斷觸發(fā) 前方無障礙物 這是一個很簡單而自然的想法。用定時器T0的快速PWM模式控制小車的速度,附加兩個獨立按鍵來控制初始時小車的速度,以便于調(diào)試。第一版程序中為小

20、車設(shè)計了如下7個動作: 發(fā)現(xiàn)前方有小障礙(010):后退并右轉(zhuǎn); 發(fā)現(xiàn)右方有小障礙(100):前進(jìn)并左轉(zhuǎn); 發(fā)現(xiàn)左方有小障礙(001):前進(jìn)并右轉(zhuǎn); 發(fā)現(xiàn)前方有大障礙(111):較大的后退并右轉(zhuǎn); 發(fā)現(xiàn)右方有大障礙(110):后退并右轉(zhuǎn); 發(fā)現(xiàn)左方有大障礙(011):后退并左轉(zhuǎn); 發(fā)現(xiàn)兩邊有障礙但中間無障礙(101):較大的后退并右轉(zhuǎn); 每次動作結(jié)束后,小車都要改運動狀態(tài)為前進(jìn),等待下一次中斷觸發(fā)。 按照這樣的思路寫完程序后,調(diào)試中發(fā)現(xiàn)小車的動作很笨拙,每次一樣動作的距離總是一樣的,不能根據(jù)環(huán)境自動調(diào)整,前進(jìn)后退都太沖;因為動作都是用延時函數(shù)實現(xiàn)的,動作中要禁用全局中斷,導(dǎo)致發(fā)現(xiàn)障礙物不與時,

21、常常一頭撞上去;后退時動作無法調(diào)整,即使已經(jīng)避開了障礙物還是無法與時轉(zhuǎn)換成前進(jìn)狀態(tài),經(jīng)常撞上后面的物體。 鑒于以上發(fā)現(xiàn)的問題,我們又修改寫成了第二版程序,流程圖與第一版大致一樣,所不同的是每次動作的時間都被改得非常短(約幾個毫秒),在每個動作結(jié)束后都在此檢測探測器反饋值,然后根據(jù)反饋值選擇下一步動作。也就是說,8個動作函數(shù)(加了一個前進(jìn))和一個INT0中斷處理函數(shù)形成了循環(huán),循環(huán)的唯一出口在前進(jìn)函數(shù)里,只有檢測到前方已無障礙物時才能退出中斷。我們希望通過縮短每次動作的時間、縮短兩次探測之間的間隔時間來達(dá)到變行進(jìn)邊探測效果,使小車的動作更加靈敏。 1.2 第二版程序的主流程圖:有障礙 無障礙 I

22、NT0中斷觸發(fā) 端口值是多少? 檢測傳感器端口的反饋值 前方有障礙物 根據(jù)檢測到的障礙物情況(分7種),從7個動作函數(shù)中選擇一個執(zhí)行 前進(jìn) 等待下次中斷觸發(fā) 前方無障礙物 檢測判斷端口值 對于這一版程序,我們在調(diào)試過程中發(fā)現(xiàn)小車四處亂撞的問題已經(jīng)基本能解決了,但隨之而來又出現(xiàn)了新問題:控制小車前進(jìn)和轉(zhuǎn)向的端口電平變得很不穩(wěn)定,小車走起路來顫顫巍巍,常常出現(xiàn)卡死的現(xiàn)象。具體表現(xiàn)為:端口值有規(guī)律地閃動,大約0.2秒閃一次,出現(xiàn)一個極短的脈沖,其值恰好是“前進(jìn)”。由此我們想到可能是算法本身的原因造成了這種現(xiàn)象,是退出中斷服務(wù)程序時的一個脈沖。 為了解決端口電平不穩(wěn)定的問題,也為了定時更加準(zhǔn)確,同時節(jié)

23、省CPU時間,我們對程序進(jìn)行了較大調(diào)整,改為用T1定時器來控制動作和檢測。每隔一定時間T1觸發(fā)溢出中斷,在中斷服務(wù)程序中進(jìn)行檢測和行動。這時的行動只是改變控制端口值,不需要延時函數(shù),這就大大節(jié)約了CPU時間。每個動作函數(shù)都精簡到只有一個動作,動作完成后不再作改動,等待下次中斷再修改控制端口值。 1.3 第三版程序的主流程圖:T1溢出中斷 端口值是多少? 檢測傳感器端口的反饋值 前方有障礙物 根據(jù)檢測到的障礙物情況(分7種),從7個動作函數(shù)中選擇一個執(zhí)行 等待下次中斷觸發(fā) 前方無障礙物 從這一流程圖可以看出,我們盡可能的精簡了小車的動作過程,使得整個判斷處理過程簡潔而迅速。另外,我們在這一版程序

24、里加上了自動變速程序,小車的速度不再由各個動作函數(shù)直接指定,而是通過計算一個連續(xù)動作的進(jìn)行時間,由程序自動設(shè)定T0的OCR0值。這樣做主要是為了配合小車的啟動和制動,在啟動和制動時給小車較大的動力,而在一般行進(jìn)時使用普通功率,這樣就可以既有效的控制小車的速度,又能夠保證小車在改變方向時有足夠的動力。程序?qū)崿F(xiàn)了三檔自動變速。此外,我們還修改INT1中斷中的兩個按鍵的功能,不再是控制起始速度,而是控制普通行進(jìn)時的速度,使這兩個控制按鍵更加實用。 在測試中,我們發(fā)現(xiàn)這樣的改變收到了良好的效果。小車在前方障礙物的檢測和避過上已經(jīng)非常靈敏,能在隨意放置的障礙物陣中迅速找到前進(jìn)的路線穿過陣列。由于加上了自

25、動變速程序,小車的動作也變得流暢了許多。 不過,在測試中我們還是發(fā)現(xiàn)了新的問題:小車在碰上前方的障礙時需要后退,后退到光電開關(guān)檢測不到障礙的地方改變方向前進(jìn),這是程序設(shè)計的動作;但是如果小車在光電開關(guān)檢測距離閾值的地方正好速度比較慢,沒有足夠的慣性沖到檢測距離里面或外面,就可能在那里不斷重復(fù)短促的前進(jìn)和后退的動作,從而卡死。 為了解決這個問題,我們在第三版程序的基礎(chǔ)上,又編寫了第四版程序。第四版程序中新增添了防卡死機制,結(jié)合定時器控制和延時函數(shù)控制的優(yōu)點,實現(xiàn)了小車較流暢的后退和轉(zhuǎn)向。 1.4第四版程序的主流程圖: T1溢出中斷 端口值是多少? 檢測傳感器端口的反饋值 前方有障礙物 根據(jù)檢測到

26、的障礙物情況(分7種),從7個動作函數(shù)中選擇一個執(zhí)行 等待下次中斷觸發(fā) 前方無障礙物 記錄上一次的動作持續(xù)時間 是否卡死? 執(zhí)行卡死 處理函數(shù) 清空歷史記錄 否 是 第四版程序的防卡死機制是以一個動作歷史記錄隊列為基礎(chǔ)的。該隊列是一個有8個元素的數(shù)組history8,每次行進(jìn)方向改變,即由后退轉(zhuǎn)為前進(jìn)或由前進(jìn)轉(zhuǎn)為后退時,即認(rèn)為一次連續(xù)動作結(jié)束,記錄這個動作的時間,寫入隊列;隊列共記錄前8次連續(xù)動作的持續(xù)時間,如果這8次動作中有7次以上持續(xù)時間在0.4秒以下,就認(rèn)為小車被卡住了,這時執(zhí)行卡死處理函數(shù),讓小車退出卡死區(qū)域??ㄋ捞幚砗瘮?shù)使用了延時函數(shù)來執(zhí)行,期間禁用了T1,視障礙物情況執(zhí)行1-3次倒

27、退轉(zhuǎn)向動作。此外我們改變了一個動作函數(shù):由于小車的探測距離比車身寬度大得多,當(dāng)左右兩個探測器檢測到有障礙物而中間沒有時,小車將直接前行從障礙物中間穿過。 防卡死機制有效地解決了小車卡死的問題,小車對于前方障礙物的躲避也比較靈敏了。? 這一版程序為我們小車的最終定型程序。 程序模塊構(gòu)成 系統(tǒng)時鐘模塊:通過T1定時器產(chǎn)生0.1秒間隔的溢出中斷,作為小車周期性探測和動作的時鐘。此外有兩個輔助軟件延時函數(shù)。 相關(guān)函數(shù): timer1_init(); isr_timer1_ovf(); trap_handler(); delay100us(n); delay10ms(n); 調(diào)速模塊:通過T0定時器產(chǎn)生

28、PWM波形來控制驅(qū)動電機的輸出功率。程序設(shè)計了3擋自動調(diào)速,對應(yīng)OCR0值max_power, fast_power, mid_power。從啟動開始,利用變量count_move來計算連續(xù)行動的時間,使用最大功率連續(xù)前進(jìn)或后退0.3秒以克服摩擦阻力,接下來0.3秒時用較大功率,以后使用普通功率。其間如果探測到障礙物需要改變行進(jìn)方向,可以隨時重新計時。通過兩個獨立按鍵可以調(diào)整普通功率值,計算按鍵的時間,每個時間單位mid_power值加1。 相關(guān)函數(shù): timer0_init(); set_OCR0(); isr_timer0_ovf(); isr_INT0(); 障礙探測模塊:如前所述,通過

29、讀取PINB端口值判斷前方障礙物情況。共有7種設(shè)定的障礙物情況,詳見程序代碼中宏定義部分。 相關(guān)函數(shù): isr_timer1_ovf(); trap_handler(); 常規(guī)動作模塊:根據(jù)障礙探測模塊的返回值,由8個動作函數(shù)控制小車的各種動作。修改后的動作列表如下(括號為相關(guān)函數(shù)): 發(fā)現(xiàn)前方有小障礙(010):后退并右轉(zhuǎn);(move_front_obj()) 發(fā)現(xiàn)右方有小障礙(100):前進(jìn)并左轉(zhuǎn);(move_right_obj()) 發(fā)現(xiàn)左方有小障礙(001):前進(jìn)并右轉(zhuǎn);(move_left_obj()) 發(fā)現(xiàn)前方有大障礙(111):較大的后退并右轉(zhuǎn);(move_front_bigob

30、j()) 發(fā)現(xiàn)右方有大障礙(110):后退并右轉(zhuǎn);(move_right_bigobj()) 發(fā)現(xiàn)左方有大障礙(011):后退并左轉(zhuǎn);(move_left_bigobj()) 發(fā)現(xiàn)兩邊有障礙但中間無障礙(101):直接前進(jìn)穿過;(move_double_obj()) 動作歷史記錄模塊:建立一個數(shù)組history8,其值代表之前8次連續(xù)動作所經(jīng)過的時間。初始值都設(shè)定為100(10秒),每次T1產(chǎn)生溢出中斷時都判斷是否改變了前進(jìn)或后退狀態(tài)(通過isforward變量標(biāo)志),若有改變則記錄上一次動作的持續(xù)時間,最前一次的時間記錄則自動刪除。在防卡死模塊動作結(jié)束后,歷史記錄自動清空為初始狀態(tài)。 相關(guān)函

31、數(shù): record_history(); trap_handler(); 防卡死模塊:首先判斷小車是否為卡死狀態(tài)。順次讀取history 數(shù)組的各個元素值,若某個元素值小于或等于4(連續(xù)動作持續(xù)時間小于或等于0.4秒),則變量recorder加1;若最終recorder值大于或等于7,說明小車在很短的時間連續(xù)多次改變了行進(jìn)方向,則認(rèn)為小車處在探測閾值的位置上且被卡死。此時執(zhí)行卡死處理函數(shù)trap_handler()。trap_handler()是一個使用軟件延時作為計時方法的函數(shù),執(zhí)行期間禁用T1定時器,這樣設(shè)計是因為軟件延時對時間間隔的控制更為靈活。為了防止像以前版本中的軟件延時動作函數(shù)一樣

32、出現(xiàn)端口值不穩(wěn)定的問題,該函數(shù)使用3層嵌套判斷結(jié)構(gòu),在行進(jìn)中對障礙物情況先后作出3次判斷,若中間有一次探測發(fā)現(xiàn)障礙物消失,則退出函數(shù)繼續(xù)執(zhí)行常規(guī)動作。這樣就可以使函數(shù)的最大動作時間達(dá)到0.9秒,足以使小車退到安全區(qū)域,且保證了端口值的穩(wěn)定性,即動作的流暢性。 相關(guān)函數(shù): isr_timer1_ovf(); trap_handler();五、系統(tǒng)功能與指標(biāo)參數(shù)測試 1、系統(tǒng)實現(xiàn)功能: 對于前方任意放置的障礙物的靈活規(guī)避; 3檔自動變速; 正常行進(jìn)速度的手動連續(xù)調(diào)節(jié); 防卡死機制,可以有效地退出夾縫、角落等區(qū)域。 2、系統(tǒng)主要參數(shù)測試: 給光電開關(guān)供電,前側(cè)放置不同顏色障礙物,通過尾部指示燈觀察探

33、測距離。 淺色:30cm 深色:20cm 通過在小車前方擺放不同顏色的障礙物來測試小車的制動距離。該項測量在小車行進(jìn)中進(jìn)行。 全速制動:25cm 普通功率制動:15cm 附:程序代碼如下: 第四版程序: /ICC-AVR application builder : 2007-6-19 0:32:08 / Target : M16 / Crystal: 1.0000Mhz #include <iom16v.h> #include <macros.h> typedef unsigned char uint8;/可移植的8位無符號變量 typedef unsigned int

34、 uint16;/可移植的16位無符號變量 #define no_obj 0x00 #define right_obj 0x04 #define front_obj 0x02 #define right_bigobj 0x06 #define left_obj 0x01 #define double_obj 0x05 #define left_bigobj 0x03 #define front_bigobj 0x07 #define stop 0xFF #define forward 0xF8 #define backward 0xF4 #define forward_and_left 0xF

35、9 #define forward_and_right 0xFA #define backward_and_left 0xF6 #define backward_and_right 0xF5 uint8 mid_power=0x90; uint8 fast_power=0xC0; uint8 max_power=0xFF; uint8 detect=0x00; uint8 count_move=0; uint8 history8=100,100,100,100,100,100,100,100; uint8 isforward=1; uint8 istrapped=0; uint8 record

36、er=0; uint8 pre_power;pre_isforward; /*100微秒延時*/ void delay100us(uint8 n) uint8 i; for(;n!=0;n-) for(i=100;i!=0;i-) NOP(); /*10毫秒延時*/ void delay10ms(uint8 n) uint16 i; for(i=n*10000;i!=0;i-) NOP(); void set_OCR0(void) if(count_move>=0&&count_move<=3) OCR0=max_power; else if(count_move&

37、gt;3&&count_move<=6) OCR0=fast_power; else if(count_move>6) OCR0=mid_power; else OCR0=fast_power; /*動作歷史記錄函數(shù)*/ void record_history(void) uint8 i; if(pre_isforward!=PINA) for(i=7;i>0;i-) historyi=historyi-1; history0=count_move; /*電機控制程序*/ void move_no_obj(void) PORTA=forward; record

38、_history(); if(isforward=1) count_move+; else count_move=0; isforward=1; void move_right_obj(void) PORTA=forward_and_right; record_history(); if(isforward=1) count_move+; else count_move=0; isforward=1; void move_left_obj(void) PORTA=forward_and_left; record_history(); if(isforward=1) count_move+; e

39、lse count_move=0; isforward=1; void move_right_bigobj(void) PORTA=backward_and_right; record_history(); if(isforward=1) count_move=0; else count_move+; isforward=0; void move_left_bigobj(void) PORTA=backward_and_left; record_history(); if(isforward=1) count_move=0; else count_move+; isforward=0; voi

40、d move_front_obj(void) PORTA=backward_and_right; record_history(); if(isforward=1) count_move=0; else count_move+; isforward=0; void move_front_bigobj(void) PORTA=backward_and_right; record_history(); if(isforward=1) count_move=0; else count_move+; isforward=0; void move_double_obj(void) PORTA=forwa

41、rd; record_history(); if(isforward=1) count_move+; else count_move=0; isforward=1; /*防止車被卡住的倒車程序*/ void trap_handler(void) uint8 i; TCCR1B=0x00; PORTA=backward_and_right; OCR0=max_power; delay10ms(30); switch(PINB&0x07) case no_obj: case right_obj: case left_obj: case double_obj: TCCR1B=0x02; br

42、eak; case left_bigobj: PORTA=backward_and_left; delay10ms(30); switch(PINB&0x07) case no_obj: case right_obj: case left_obj: case double_obj: TCCR1B=0x02; break; case front_obj: case front_bigobj: case right_bigobj: PORTA=backward_and_right; delay10ms(30); PORTA=forward; TCCR1B=0x02; break; case

43、 left_bigobj: PORTA=backward_and_left; delay10ms(30); PORTA=forward; TCCR1B=0x02; break; break; case front_obj: case front_bigobj: case right_bigobj: delay10ms(25); switch(PINB&0x07) case no_obj: case right_obj: case left_obj: case double_obj: PORTA=forward; TCCR1B=0x02; break; case front_obj: c

44、ase front_bigobj: case right_bigobj: delay10ms(25); PORTA=forward; TCCR1B=0x02; break; case left_bigobj: PORTA=backward_and_left; delay10ms(25); PORTA=forward; TCCR1B=0x02; break; break; default:break; for(i=8;i>0;i-) historyi-1=100; void port_init(void) PORTA = 0xF8; DDRA = 0x0F; PORTB = 0x00; D

45、DRB = 0x08; PORTC = 0x03; /m103 output only DDRC = 0x00; PORTD = 0x0C; DDRD = 0x00; /TIMER0 initialize - prescale:8 / WGM: PWM Fast / desired value: 2mSec / actual value: 2.048mSec (-2.4%) void timer0_init(void) TCCR0 = 0x00; /stop TCNT0 = 0x01; /set count OCR0 = 0xFF; /set compare TCCR0 = 0x6A; /st

46、art timer /TIMER1 initialize - prescale:8 / WGM: 0) Normal, TOP=0xFFFF / desired value: 100mSec / actual value: 100.000mSec (0.0%) void timer1_init(void) TCCR1B = 0x00; /stop TCNT1H = 0xCF; /setup TCNT1L = 0x2C; OCR1AH = 0x00; OCR1AL = 0xFA; OCR1BH = 0x00; OCR1BL = 0xFA; ICR1H = 0x00; ICR1L = 0xFA;

47、TCCR1A = 0x00; TCCR1B = 0x02; /start Timer #pragma interrupt_handler timer1_ovf_isr:9 void timer1_ovf_isr(void) uint8 i; /TIMER1 has overflowed TCNT1H = 0xCF; /reload counter high value TCNT1L = 0x2C; /reload counter low value pre_power=OCR0; pre_isforward=isforward; detect=(PINB&0x07); switch(d

48、etect) case no_obj:move_no_obj();break; case right_obj:move_right_obj();break; case right_bigobj:move_right_bigobj();break; case left_obj:move_left_obj();break; case left_bigobj:move_left_bigobj();break; case front_obj:move_front_obj();break; case front_bigobj:move_front_bigobj();break; case double_

49、obj:move_double_obj();break; default:break; set_OCR0(); for(i=8;i>0;i-) if(historyi-1<=4) istrapped+; if(istrapped>=7) trap_handler(); istrapped=0; else istrapped=0; #pragma interrupt_handler int1_isr:3 void int1_isr(void) /external interupt on INT1 switch(PINC)&0x03) case 0x01: if(mid_

50、power<255) mid_power+; delay100us(10); break; case 0x02: if(mid_power>1) mid_power-; delay100us(10); break; default:break; /call this routine to initialize all peripherals void init_devices(void) /stop errant interrupts until set up CLI(); /disable all interrupts port_init(); timer0_init(); ti

51、mer1_init(); MCUCR = 0x00; GICR = 0x80; TIMSK = 0x04; /timer interrupt sources SEI(); /re-enable interrupts /all peripherals are now initialized void main(void) init_devices(); while(1); 基于80C51單片機的智能小車設(shè)計發(fā)布:2011-05-17 | | 來源: xuwenhua | 查看:1359次 | 用戶關(guān)注:O 引言 在現(xiàn)有玩具電動車的基礎(chǔ)上,加裝光電檢測器,實現(xiàn)對電動小汽車的速度、位置、運行狀況的實

52、時測量,并將測量數(shù)據(jù)傳送至單片機進(jìn)行處理,然后由單片機根據(jù)所檢測的各種數(shù)據(jù)實現(xiàn)對電動車的智能控制。1 直流調(diào)速系統(tǒng)采用PWM調(diào)速 直流調(diào)速系統(tǒng)采用晶閘管的直流斬波器與整流電路。晶閘管不受相位控制,而是工作在開關(guān)狀態(tài)。當(dāng)晶閘管被觸發(fā)導(dǎo)通時,電源電壓加到電動機上,當(dāng)晶閘管關(guān)斷時,直流電源與電動機斷開,電動機經(jīng)二極管續(xù)O 引言 在現(xiàn)有玩具電動車的基礎(chǔ)上,加裝光電檢測器,實現(xiàn)對電動小汽車的速度、位置、運行狀況的實時測量,并將測量數(shù)據(jù)傳送至單片機進(jìn)行處理,然后由單片機根據(jù)所檢測的各種數(shù)據(jù)實現(xiàn)對電動車的智能控制。1 直流調(diào)速系統(tǒng)采用PWM調(diào)速 直流調(diào)速系統(tǒng)采用晶閘管的直流斬波器與整流電路。晶閘管不受相位控制,而是工作在開關(guān)狀態(tài)。當(dāng)晶閘管被觸發(fā)導(dǎo)通時,電源電壓加到電動機上,當(dāng)晶閘管關(guān)斷時,直流電源與電動機斷開,電動機經(jīng)二極管續(xù)流,兩端電壓接近于零。脈沖寬度調(diào)制(Pulse Width Modulat-ion),簡稱PWM。脈沖周期不變。只改變晶閘管的導(dǎo)通時間,即通過改變脈沖寬度來進(jìn)行直流調(diào)速。 脈寬調(diào)速也可通過單片機控制繼電器的閉合來實現(xiàn),但是驅(qū)動能力有限。為展利實現(xiàn)電動小汽車的左轉(zhuǎn)和右轉(zhuǎn),本設(shè)計采用了可逆PWM變換器??赡鍼WM變換器主電路的結(jié)構(gòu)式有H型、T型等類型。我們

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論