摘 要:針對小車在行駛過程中的尋跡要求,設計了以AT89C51單片機為核心的控制電路,采用模塊化的設計方案,運用色標傳感器、金屬探測傳感器、超聲波傳感器、霍爾傳感器組成不同的檢測電路,實現小車在行駛中軌跡、探測預埋金屬鐵片、躲避障礙物、測量車速等問題檢測,并對設計的電路進行了理論分析和實際測試。結果表明,該智能小車具有很好的識別與檢測的能力,具有定位精度、運行穩定可靠的特點。
0 引 言
自主尋跡電動小車是一個運用傳感器、單片機、信號處理、電機驅動及自動控制等技術來實現環境感知和自動行駛為一體的高新技術綜合體,它在軍事、民用和科學研究等方面已獲得了應用。本文研究的電動小車是在給定的區域內沿著軌跡完成對各個目標點的訪問,主要指標有行駛距離、時間、探測物計數、障礙物躲避等。本文采用AT89C51單片機作控制,針對小車在行駛過程中的不同要求,采用模塊化設計方案,進行了各部分電路的設計。 1 智能小車控制的基本要求 小車必須沿規定路線行駛,控制部分設計不能采用無線遙控,具體控制要求如下:
(1)電動車從起跑線出發,沿規定引導直線行駛到達B點。在“直道區”下沿引導線埋有1一3塊寬度為15cm、長度不等的薄鐵片。電動車在行駛中檢測到薄
鐵片時需立即發出聲光指示信息,并實時存儲、顯示在“直道區”檢測到的薄鐵片數目。電動車在“直道區”行駛過程中,存儲并顯示每個薄鐵片(中心線)至起跑
線間的距離; (2)電動車到達B點以后進人“彎道區”,沿圓 弧引導線到達C點。C點下埋有邊長為 15cm的正方形薄鐵片,要求電動車到達C點檢測到薄鐵片后在C點處停車5秒,停車期間發出斷續的聲光信息;
(3)電動車在光源的引導下,通過障礙區進人停車區并到達車庫。電動車必須在兩個障礙物之間通過且不得與其接觸;
(4)電動車完成上述任務后應立即停車。停車后,能準確顯示電動車全程行駛時間。 2 方案的選擇與實現
2.1 系統方案的確定
根據題目要求,將控制對象及檢測目標劃分為不同模塊,即障礙物檢測、路面鐵片檢測、路面軌跡檢測、光源檢測、速度路程檢測等模塊。針對不同模塊的控制要求分別采用不同的設計方案實現。系統組成及原理框圖如圖1所示。其中色標傳感器用來檢測小車的運行軌跡,金屬探測傳感器用來檢測路跡下薄鐵片的數目,超聲波傳感器用來檢測小車前進方向的障礙物,霍爾傳感器用于檢測小車行駛的速度及距離。 2.2 各部分硬件電路設計 (1)電動機PWM驅動電路
小車控制的主電路采用由達林頓管組成的H型PWM電路。用單片機控制達林頓管使之工作在占空比可調的開關狀態,精確調整電動機轉速。在這種電路中,管子始終工作在飽和與截止模式下,轉換速度快,效率高。H型電路可以實現轉速和方向的控制,是一種廣泛采用的PWM調速技術。其電路圖如圖2。 (2)路面黑線檢測電路
采用兩個色標傳感器組成檢測電路。探測路面黑線的大致原理是:光線照射到路面并反射,由于黑線
和白紙的反射系數不同,根據接收到的反射光強弱判斷是否沿黑線前進。在車底中部安裝了兩個GDK一Znw型色標傳感器,將兩個色標傳感器探頭置于運行軌跡中間,其間距調整為大于黑線的寬度。色標傳感器接受到不同的顏色后會有不同的電平輸出。本電路中當色標傳感器檢測到黑色,③腳輸出為高電平;檢測到白色,③腳輸出為低電平。實際行駛時,只有當兩個色標傳感器同時檢測為高電平,小車才直線運行,否則運用差步原理,調整方向。檢測電路如圖3。 色標傳感器工作電流大,抗干擾能力強,檢測精度高,在 黑色引導線兩側檢測,可使小車沿運行軌跡精確行 駛。
(3)路面下金屬片檢測電路 在車底中部安裝了一個金屬探測傳感器,將其檢測面對準運行路面,當小車通過金屬鐵塊時,傳感器給出電平信號,送單片機Pl端口,通過對脈沖計數可知金屬片數目。 (4)障礙物檢測電路的設計
采用超聲波傳感器探測障礙物。超聲波傳感器安裝于小車前端,在規定的檢測距離內,當探測到障礙
物時,超聲波傳感器給出脈沖信號至單片機,單片機檢測到該信號后,調整小車方向,以控制小車準確的
繞過障礙物。
(5)光源檢測電路的設計
利用光敏電阻值隨光強弱變化的特性組成光控開關電路,如圖4。當無光照射時,光敏電阻阻值很大,
三極管處于截止狀態,集電極輸出高電平;當有光照射時,光敏電阻阻值變小,三極管飽和導通。將檢測到
的高低電平信號送單片機,依此調整車頭方向,使其 沿光源方向行駛。檢測電路安裝在小車車頭位置。 (6)顯示電路的設計
為了減少外部鎖存器和譯碼模塊,使功耗最小,數碼管全部使用軟件進行靜態顯示。在直道區內,
數碼管顯示鐵片數量和起跑線到鐵片中心的距離;在行駛到終點后,顯示全程所用時間。用CD45fl驅動四
位數碼管,一位顯示鐵片的數目,三位分別顯示行駛的距離與時間。
(7)車速及距離檢測
采用霍爾傳感器檢測小車速度及距離。在車后輪上安裝兩片磁鋼,將霍爾傳感器安裝在固定軸上,通
過對脈沖的計數進行車速及距離的測量。霍爾傳感器的使用原理如圖5,汽車后輪每轉一圈,霍爾元件產生
兩個脈沖,將其送人單片機的TO口進行計數,同時完成脈沖數和距離的計算。
(8)小車進車庫停車電路設計
當小車車體完全進人車庫后,應立即停車。為了準確得到停車信號,利用光敏電阻兩端電壓隨光的強弱變化的規律來設計電路。用200W白熾燈對準光敏電阻,當光敏電阻距離光源不同位置時,其兩端的電
壓按表1規律變化。 用ADC0809的INO端采集其變化電壓,在3.SV時給出停車指令,完成停車任務。 3 系統的軟件設計
控制電路主要由一片89c51單片機組成。89c51主要實現對路面黑線的檢測,以糾正小車的行走方向;負責車速檢測、鐵片檢測、障礙物檢測、光源檢測、光強度檢測、電動機驅動、數據顯示等功能。主程序流程如圖6。 (1)直道檢測。在小車的中部平行裝有兩個色標傳感器,采用查詢檢測的方法對黑線進行檢測。89C51
在檢測到黑線信號后,通過89C51的PI.5和Pl.6口得知是哪一個傳感器檢測到黑線,以此作為調整小車方向的基準。在程序方面,我們采用了差補控制算法。在校正服務程序中通過檢測PI.5和Pl.6口的狀態,運用差補算法,精確調節左右前輪的方向,達到使小車穩定沿黑線行走的目的。為了保證程序的準確性,服務程序中設置了2重黑線檢測,有效的防止了小車沖出跑道。在直道上的鐵片,我們使用金屬探測傳感器來檢測。通過計算小車開始檢測到鐵片與離開鐵片時的圈數之差,乘以車輪的周長,我們可以得到鐵片的長度以及鐵片一半的長度,由此可以得到起跑線到鐵片中央的距離。當車輪轉動時,安裝在輪胎上的磁鋼使霍爾元件產生電平變化。因此只需記錄電平變化的次數,便能得到實際轉速。為了提高準確度,減少誤差,我們安裝了兩塊磁鋼。 (2)轉彎檢測。為了防止小車沖出跑道以及按照黑線轉彎,需要在進人彎道之前降低速度。因此我們采用了高效的H型PWM電路調節轉速。在進人轉彎之前,我們通過提前減速程序使小車降低速度。通過跟隨黑線行駛和檢測最后一片鐵片的位置,我們可以得到準確的停車位置和車頭方向。在鐵片上停留55的期間,驅動聲光報警系統,發出聲光報警信號;同時,由累計脈沖的總數便可得到全程行駛的時間。
(3)障礙檢測。首先我們通過尋找Zoow燈泡的光源,來校正小車的方向。然后通過超聲波對障礙物進行距離檢測,以此為基準,繞過障礙物。再通過檢測光源找到小車與車庫之間的距離,并由此引導小車準確進入車庫。
4 結束語
從測試結果來看,PWM技術能夠極大地提高電動機的驅動效率;雙色標傳感器解決了小車嚴格按照軌跡(黑線)運行的問題;超聲波傳感器能夠精確測量小車與障礙物之間的距離,為躲避障礙物提供了較好的測量方法;霍爾傳感器可精確測量運行中的轉速。從運行情況看,采用本方案設計制作的智能小車,系統可靠性較高,運行穩定,定位準確,達到了設計要求。
單片機源程序如下:
- //========================================================
- // 工程名稱: Car_Demo
- // 功能描述: 實現DIY競賽小車的語音控制
- // 涉及的庫: CMacro1016.lib
- // bsrv222SDL.lib
- // sacmv26e.lib
- // 組成文件: main.c
- // Flash.asm, hardware.asm,ISR.asm
- // hardware.h,s480.h, hardware.inc
- // 硬件連接: IOA0-----KEY1
- // IOA1-----KEY2
- // IOA2-----KEY3
- // IOB10----MOTOR1A
- // IOB11----MOTOR1B
- // IOB12----MOTOR2A
- // IOB13----MOTOR2B
- // 維護記錄: 2007-06 v1.0
- // 本代碼在原凌陽小車代碼上修改而成,版權原作者所有!
- //========================================================
- #include "s480.h"
- #include "bsrsd.h"
- #define P_IOA_Data (volatile unsigned int *)0x7000
- #define P_IOA_Dir (volatile unsigned int *)0x7002
- #define P_IOA_Attrib (volatile unsigned int *)0x7003
- #define P_IOB_Data (volatile unsigned int *)0x7005
- #define P_IOB_Dir (volatile unsigned int *)0x7007
- #define P_IOB_Attrib (volatile unsigned int *)0x7008
- #define P_TimerA_Data (volatile unsigned int *)0x700A
- #define P_TimerA_Ctrl (volatile unsigned int *)0x700B
- #define P_TimerB_Data (volatile unsigned int *)0x700C
- #define P_TimerB_Ctrl (volatile unsigned int *)0x700D
- #define P_Watchdog_Clear (volatile unsigned int *)0x7012
- #define P_INT_Mask (volatile unsigned int *)0x702D
- #define P_INT_Clear (volatile unsigned int *)0x7011
- #define NAME_ID 0x100
- #define COMMAND_GO_ID 0x101
- #define COMMAND_BACK_ID 0x102
- #define COMMAND_LEFT_ID 0x103
- #define COMMAND_RIGHT_ID 0x104
- #define S_NAME 0 //給我取個名字吧
- #define S_ACT1 1 //前進
- #define S_ACT2 2 //倒車,請注意
- #define S_ACT3 3 //左拐
- #define S_ACT4 4 //右拐
- #define S_RDY 5 //Yeah
- #define S_AGAIN 6 //請再說一遍
- #define S_NOVOICE 7 //沒有聽到任何聲音
- #define S_CMDDIFF 8 //說什么暗語呀
- #define S_NOISY 8 //說什么暗語呀
- #define S_START 9 //準備就緒,開始辨識
- #define S_GJG 10 //拐就拐
- #define S_DCZY 11 //倒車,請注意
- extern unsigned int BSR_SDModel[100]; //外部變量BSR_SDModel[100],辨識器自帶
- extern void F_FlashWrite1Word(unsigned int addr,unsigned int Value);
- extern void F_FlashErase(unsigned int sector);
- unsigned int uiTimeset = 3; //運行時間定時,調整該參數控制運行時間
- unsigned int uiTimecont; //運行時間計時
- //=============================================================
- // 語法格式: void Delay();
- // 實現功能: 延時
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void Delay()
- {
- unsigned int i;
- for(i=0;i<0x3Fff;i++)
- {
- *P_Watchdog_Clear=0x0001;
- }
- }
- //=============================================================
- // 語法格式: void PlaySnd(unsigned SndIndex,unsigned DAC_Channel);
- // 實現功能: 語音播放函數
- // 參數: SndIndex-播放語音資源索引號
- // DAC_Channel-播放聲道選擇
- // 返回值: 無
- //=============================================================
- void PlaySnd(unsigned SndIndex,unsigned DAC_Channel)
- {
- BSR_StopRecognizer(); //停止識別器
- SACM_S480_Initial(1); //初始化為自動播放
- SACM_S480_Play(SndIndex, DAC_Channel, 3); //開始播放一段語音
- while((SACM_S480_Status()&0x0001)!= 0) //是否播放完畢?
- {
- SACM_S480_ServiceLoop(); //解碼并填充隊列
- *P_Watchdog_Clear=0x0001; //清看門狗
- }
- SACM_S480_Stop(); //停止播放
- BSR_InitRecognizer(BSR_MIC); //初始化識別器
- }
- //=============================================================
- // 語法格式: int TrainWord(int WordID,int SndID);
- // 實現功能: 訓練一條指令
- // 參數: WordID-指令編碼
- // SndID-指令提示音索引號
- // 返回值: 無
- //=============================================================
- int TrainWord(unsigned int WordID,unsigned int SndID)
- {
- int Result;
- PlaySnd(SndID,3); //引導訓練,播放指令對應動作
- while(1)
- {
- Result = BSR_Train(WordID,BSR_TRAIN_TWICE); //訓練兩次,獲得訓練結果
-
- if(Result==0)break;
- switch(Result)
- {
- case -1: //沒有檢測出聲音
- PlaySnd(S_NOVOICE,3);
- return -1;
- case -2: //需要訓練第二次
- PlaySnd(S_AGAIN,3);
- break;
- case -3: //環境太吵
- PlaySnd(S_NOISY,3);
- return -3;
- case -4: //數據庫滿
- return -4;
- case -5: //檢測出聲音不同
- PlaySnd(S_CMDDIFF,3);
- return -5;
- case -6: //序號錯誤
- return -6;
- default:
- break;
- }
- }
- return 0;
- }
- //=============================================================
- // 語法格式: void TrainSD();
- // 實現功能: 訓練函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void TrainSD()
- {
- while(TrainWord(NAME_ID,S_NAME) != 0) ; //訓練名稱
- while(TrainWord(COMMAND_GO_ID,S_ACT1) != 0) ; //訓練第1個動作
- while(TrainWord(COMMAND_BACK_ID,S_ACT2) != 0) ; //訓練第2個動作
- while(TrainWord(COMMAND_LEFT_ID,S_ACT3) != 0) ; //訓練第3個動作
- while(TrainWord(COMMAND_RIGHT_ID,S_ACT4) != 0) ; //訓練第4個動作
- }
- //=============================================================
- // 語法格式: void StoreSD();
- // 實現功能: 存儲語音模型函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void StoreSD()
- { unsigned int ulAddr,i,commandID,g_Ret;
- F_FlashWrite1Word(0xef00,0xaaaa);
- F_FlashErase(0xe000);
- F_FlashErase(0xe100);
- F_FlashErase(0xe200);
- ulAddr=0xe000;//********
- for(commandID=0x100;commandID<0x105;commandID++)
- {
- g_Ret=BSR_ExportSDWord(commandID);
- while(g_Ret!=0) //模型導出成功?
- g_Ret=BSR_ExportSDWord(commandID);
- for(i=0;i<100;i++) //保存語音模型SD1(0xe000---0xe063)
- {
- F_FlashWrite1Word(ulAddr,BSR_SDModel[i]);
- ulAddr+=1;
- }
- }
- }
- //=============================================================
- // 語法格式: void StoreSD();
- // 實現功能: 裝載語音模型函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void LoadSD()
- { unsigned int *p,k,jk,Ret,g_Ret;
- p=(int *)0xe000;
- for(jk=0;jk<5;jk++)
- {
- for(k=0;k<100;k++)
- {
- Ret=*p;
- BSR_SDModel[k]=Ret; //裝載語音模型
- p+=1;
- }
- g_Ret=BSR_ImportSDWord();
- while(g_Ret!=0) //模型裝載成功?
- g_Ret=BSR_ImportSDWord();
- }
- }
- //=============================================================
- // 語法格式: void GoAhead();
- // 實現功能: 前進子函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void GoAhead() //前進
- {
- PlaySnd(S_ACT1,3); //提示
- *P_IOB_Data=0x1400; //前進
- *P_INT_Mask |= 0x0004; //以下為中斷定時操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 語法格式: void BackUp();
- // 實現功能: 后退子函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void BackUp() //倒退
- {
- PlaySnd(S_DCZY,3); //提示
- *P_IOB_Data=0x2800; //倒退
- *P_INT_Mask |= 0x0004; //以下為中斷定時操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 語法格式: void TurnLeft();
- // 實現功能: 左轉子函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void TurnRight() //右轉
- {
- PlaySnd(S_GJG,3);
- *P_IOB_Data=0x1800; //右轉
- Delay(); //延時
- *P_IOB_Data=0x2400; //左轉
- *P_INT_Mask |= 0x0004; //以下為中斷定時操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 語法格式: void TurnRight();
- // 實現功能: 右轉子函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void TurnLeft() //左轉
- {
- PlaySnd(S_GJG,3); //語音提示
- *P_IOB_Data=0x2400; //左轉
- Delay(); //延時
- *P_IOB_Data=0x1800; //右轉
- *P_INT_Mask |= 0x0004; //以下為中斷定時操作
- __asm("int fiq,irq");
- uiTimecont = 0;
- }
- //=============================================================
- // 語法格式: void Stop();
- // 實現功能: 停車子函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void Stop() //停車
- {
- *P_IOB_Data=0x0000; //停車
- PlaySnd(S_RDY,3); //語音提示
- }
- //=============================================================
- // 語法格式: void BSR(void);
- // 實現功能: 辨識子函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void BSR(void)
- {
- int Result; //辨識結果寄存
- Result = BSR_GetResult(); //獲得識別結果
- if(Result>0) //有語音觸發?
- {
- *P_IOB_Data=0x0000; //臨時停車
- switch(Result)
- {
- case NAME_ID: //識別出名稱命令
- Stop(); //停車待命
- break;
- case COMMAND_GO_ID: //識別出第一條命令
- GoAhead(); //執行動作一:直走
- break;
- case COMMAND_BACK_ID: //識別出第二條命令
- BackUp(); //執行動作二:倒車
- break;
- case COMMAND_LEFT_ID: //識別出第三條命令
- TurnLeft(); //執行動作三:左轉
- break;
- case COMMAND_RIGHT_ID: //識別出第四條命令
- TurnRight(); //執行動作四:右轉
- break;
- default:
- break;
- }
- }
- }
- //=============================================================
- // 語法格式: void IRQ5(void);
- // 實現功能: 中斷服務子函數
- // 參數: 無
- // 返回值: 無
- //=============================================================
- void IRQ5(void)__attribute__((ISR)); //運動定時控制
- void IRQ5(void)
- {
- if(uiTimecont++ == uiTimeset)
- {
- *P_IOB_Data = 0x0000;
- }
- *P_INT_Clear = 0x0004;
- }
- //=============================================================
- // 語法格式: int main(void);
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png (5.4 KB, 下載次數: 29)
下載附件
2018-12-18 23:20 上傳
所有資料51hei提供下載:
單片機智能小車.rar
(387.98 KB, 下載次數: 10)
2018-12-18 18:46 上傳
點擊文件名下載附件
單片機智能小車相關 下載積分: 黑幣 -5
|