一、 綜述: a) 項(xiàng)目名稱:小車自動(dòng)走迷宮; b) 小組成員: i. 周杰:負(fù)責(zé)總體規(guī)劃,及ARM編程; ii. 宋大成:負(fù)責(zé)車輪驅(qū)動(dòng); iii. 陳瀟:負(fù)責(zé)紅外驅(qū)動(dòng); c) 小車圖片: MicroMouse615: MicroMouse120: 二、 項(xiàng)目介紹: 電腦鼠走迷宮競賽的目的是制作一個(gè)微型機(jī)器人,它能在最短的時(shí)間內(nèi)穿越迷宮到達(dá)終點(diǎn)。參賽的機(jī)機(jī)器人稱為“電腦鼠”,將電腦鼠放入迷宮并啟動(dòng)操作的人稱為“操作員”。 電腦鼠的基本功能是從起點(diǎn)開始走到終點(diǎn),這個(gè)過程稱為一次“運(yùn)行”,所花費(fèi)的時(shí)間稱為“運(yùn)行時(shí)間”。從終點(diǎn)回到起點(diǎn)所花費(fèi)的時(shí)間不計(jì)算在運(yùn)行時(shí)間內(nèi)。從電腦鼠的第一次激活到每次運(yùn)行開始,這段期間所花費(fèi)的時(shí)間稱為“迷宮時(shí)間”。如果電腦鼠在比賽時(shí)需要手動(dòng)輔助,這個(gè)動(dòng)作稱為“碰觸”。競賽使用這三個(gè)參數(shù),從速度﹑求解迷宮的效率和電腦鼠的可靠性三個(gè)方面來進(jìn)行評分。器人稱為“電腦鼠”,將電腦鼠放入迷宮并啟動(dòng)操作的人稱為“操作員”。 在G02小組的工作中,基本完成了電腦鼠的驅(qū)動(dòng)部分和算法部分:電腦鼠可以進(jìn)行直線行走、90度左轉(zhuǎn)、90度右轉(zhuǎn)和180度后轉(zhuǎn);能準(zhǔn)確監(jiān)測左前右三個(gè)方向的擋板,能準(zhǔn)確判斷左右間距是否恰當(dāng);能進(jìn)行調(diào)距運(yùn)動(dòng),以保持與左右擋板的距離;能簡單判斷通路,并計(jì)算記憶合適通路;并按照通路完成迷宮行走。 但是,由于某些原因,小車的沒有取得完美的效果:由于電機(jī)轉(zhuǎn)速控制不當(dāng),小車直線行走效果不佳(參看第條);左轉(zhuǎn)右轉(zhuǎn)不夠準(zhǔn)確,只能依靠調(diào)整函數(shù)補(bǔ)償;算法不夠優(yōu)秀,正在探究更好的算法。這些問題都在努力克服中,我們不會(huì)因?yàn)闄z查完畢就放棄小車的調(diào)試。 三、 項(xiàng)目整體結(jié)構(gòu): MicroMouse102 電腦老鼠,采用美國LuminaryMicro 公司生產(chǎn)的32 位ARM CortexM3處理器LM3S102,控制和檢測紅外傳感器;主CPU 根據(jù)檢測到的傳感信號,控制電機(jī)驅(qū)動(dòng)電路調(diào)整行走路徑,直到到達(dá)終點(diǎn)。 四、 硬件部分介紹: LED 電路 電腦鼠有5 個(gè)獨(dú)立的LED,通過LM3S 系統(tǒng)單片機(jī)的GPIO 口直接控制,如圖 1.6 所示。電路采用了I/O 口灌電流的驅(qū)動(dòng)方式來驅(qū)動(dòng)LED,LM3S 系統(tǒng)單片機(jī)的灌電流為2~8mA(可配置),所以不需要驅(qū)動(dòng)就可以點(diǎn)亮LED。GPIO 引腳輸出高電平時(shí)LED 熄滅,低電平時(shí)LED 點(diǎn)亮。 電機(jī)驅(qū)動(dòng)電路 電機(jī)采用直流減速電機(jī),最高輸出轉(zhuǎn)速為800 轉(zhuǎn)/分鐘,工作電壓為DC3V。電機(jī)驅(qū)動(dòng) 電路采用專用的單相直流電動(dòng)機(jī)橋式驅(qū)動(dòng)芯片。 車速檢測電路 車速檢測用于檢測并記錄車體運(yùn)行的路徑,通過車速檢測記錄車體做迷宮的坐標(biāo),同 時(shí)也起到控制車速和保持左右雙輪的速度一致。 檢測原理:在左輪和右輪的內(nèi)則都貼有的光電碼盤,碼盤由兩種顏色組成白色和黑色。 紅外發(fā)射管安裝在車輪光電檢測碼盤的檢測區(qū)域,當(dāng)紅外發(fā)射與接收管正對著黑色邊時(shí), 紅外線沒有被反射,接收管的電阻很大;當(dāng)紅外發(fā)射與接收管正對著白色邊時(shí),紅外線被 反射,接收管的電阻很小。 紅外檢測電路 紅外檢測電路是用于迷宮擋板的檢測,分為左側(cè)、右側(cè)、前方三個(gè)方向,三個(gè)方向的 檢測原理相同,某一個(gè)方向的檢測電路。 CPU 及晶振電路 電腦鼠的單片機(jī)、晶體振蕩器和LDO輸出原理如圖所示。該單片機(jī)選用LM3S102 微處理器。 五、 軟件部分介紹: 一體化紅外接收頭工作原理 一體式紅外線接收傳感器IRM8601S,它內(nèi)部集成自動(dòng)增益控制電路、帶通濾波電路、 解碼電路及輸出驅(qū)動(dòng)電路。當(dāng)連續(xù)收到38KHz 的紅外線信號時(shí),將產(chǎn)生脈寬10ms 左右的 低電平。如果沒有收到信號,便立即輸出高電平。Send 為發(fā)射控制端,高 電平時(shí)發(fā)射38KHz 的紅外信號。Out 為接收輸出端,低電平表示收到信號。 檢測障礙物的軟件設(shè)計(jì) 根據(jù)接收頭是否檢測到經(jīng)過反射的紅外線信號,就可以判斷是否存在障礙物。由于接 收頭檢測到信號時(shí)只產(chǎn)生一個(gè)負(fù)脈沖,所以只需要在檢測時(shí)使能紅外線發(fā)射,一次檢測結(jié) 束后使能無效,程序設(shè)計(jì)參考流程圖如圖2.5 所示。 接收頭有一定的 響應(yīng)時(shí)間 開始發(fā)送38KHz 的紅外線 迷宮擋板檢測 調(diào)制信號產(chǎn)生 本設(shè)計(jì)中采用定時(shí)器1 產(chǎn)生38KHz 的調(diào)制信號,由PB5 輸出,該端口連接到圖2.3 中 的Pulse 端口。在中斷中翻轉(zhuǎn)PB5 輸出信號,所以要產(chǎn)生頻率為f 的脈沖,定時(shí)器的頻率 要為2f。在本設(shè)計(jì)中要產(chǎn)生38KHz 的頻率,定時(shí)器中斷頻率為76KHz。 程序清單 3.1 為定時(shí)器1 的初始化函數(shù),程序清單 3.2 為中斷服務(wù)函數(shù),在這里翻轉(zhuǎn) PB5 口輸出狀態(tài)。 程序清單 3.1 定時(shí)器1 初始化 void PULSEIni(void) { GPIODirModeSet(GPIO_PORTB_BASE, SEND | PULSE, GPIO_DIR_MODE_OUT); // 設(shè)置為輸 出 GPIOPinWrite( GPIO_PORTB_BASE,SEND | PULSE,0); // 紅外線初始時(shí)停止發(fā)射 SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER1 ); // 使能定時(shí)器1 外設(shè) TimerConfigure(TIMER1_BASE, TIMER_CFG_32_BIT_PER); // 設(shè)置定時(shí)器1 為周期觸發(fā) TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet()/76000); // 設(shè)置定時(shí)器裝載值 TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT); TimerEnable(TIMER1_BASE, TIMER_A); IntEnable(INT_TIMER1A); } 程序清單 3.2 定時(shí)器1 服務(wù)函數(shù) void Timer1A_ISR(void) { TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT); // 清除定時(shí)器1 中斷 GPIOPinWrite(GPIO_PORTB_BASE, PULSE,GPIOPinRead(GPIO_PORTB_BASE, PULSE) ^ PULSE); // 翻轉(zhuǎn)GPIO B5 端口 } 抗干擾處理 紅外線在空氣中傳播和反射受外界的干擾,如果測量距離剛好處在能夠檢測到信號的 臨界狀態(tài),保持距離不變,傳感器輸出信號也可能不確定。這樣就需要在軟件中進(jìn)行抗干 擾處理。參考程序如程序清單3.3 所示。 程序清單3.3 抗干擾處理程序 GPIOPinWrite( GPIO_PORTB_BASE,SEND , SEND); // 發(fā)送脈沖 Delay(150); // 延時(shí) for(i=0,j=0;i<10;i++) // 檢測接收信號 { if(GPIOPinRead(GPIO_PORTA_BASE, OUT_L)==0) j++; } GPIOPinWrite( GPIO_PORTB_BASE,SEND , ~SEND); // 停止發(fā)送 if(j>5) // 左邊存在擋板 { } else // 左邊存在支路 { } 圖3.1 為抗干擾程序在Micromouse 中運(yùn)行后用邏輯分析儀抓到的波形圖,Pulse 為 38KHz 的輸出信號,Send 高電平有效,有效時(shí)發(fā)送紅外線脈沖,OUT 為一體化接收頭輸 …… …… 出端,該圖所示為接收頭探測到障礙物,軟件在Send 信號無效(下降沿)前完成檢測OUT 輸出信號,從圖中可以看出,此時(shí)正處于OUT 有效信號的中間,所以軟件里延時(shí)參數(shù)能 保證正確檢測到信號。 圖3.1 傳感器檢測波形圖 軟件設(shè)計(jì)參考 為用一組紅外實(shí)現(xiàn)兩組參數(shù)(是否存在擋板和是否太接近擋板)的檢測流程圖。在Micromouse 中,用到了三組(左、前、右)反射式紅外檢測傳感器,左邊和右邊的傳感器各自都需要檢測兩組參數(shù),而前方的傳感器只需要探測有無擋板,存在擋板就必須根據(jù)策略轉(zhuǎn)換行進(jìn)方向,若不存在就可以繼續(xù)前進(jìn)。如圖3.3 所示為Micromouse 紅外檢測的程序設(shè)計(jì)流程圖。紅外檢測參考程序見程序清單 3.4 所示,該程序中使用了五個(gè)LED 用來指示傳感器檢測的狀態(tài),由于這幾個(gè)LED 硬件上連接到JTAG,關(guān)于如何切換GPIO和JTAG功能參見6 使用JTAG 引腳作GPIO。 此頻率僅作為參考,要根據(jù)實(shí)際檢測距離來確定。結(jié)合可調(diào)電阻R1 變可以實(shí)現(xiàn)擋板和防碰撞的檢測。 程序清單 3.4 Micromouse 紅外檢測函數(shù)(見附錄) 電機(jī)的調(diào)速 電機(jī)的調(diào)速 直流電機(jī)的轉(zhuǎn)速控制在本設(shè)計(jì)中通過PWM來控制,LM3S102 單片機(jī)則剛有兩路PWM 輸出,非常適合用于控制兩個(gè)電機(jī)的轉(zhuǎn)速。 兩路PWM 是LM3S102 通用定時(shí)器0(Timer0)的三種工作模式之一,16 位PWM 模 式。該模式是將一個(gè)32 位的定時(shí)器,折分成兩個(gè)16 位的定時(shí)器TimerA 和TimerB。這些 定時(shí)器為計(jì)數(shù)寄存器(GPTMTnR)遞減計(jì)數(shù),遞減到0 時(shí)自動(dòng)加載預(yù)裝載值(GPTMTnILR)。 當(dāng)然預(yù)裝載值也是由用戶設(shè)定,該直也就決定了定時(shí)周期,也即PWM 的輸出周期。 當(dāng)計(jì)數(shù)器的值與預(yù)裝載值相等時(shí),輸出PWM 信號有效,當(dāng)計(jì)數(shù)器的值與匹配寄存器 (GPTMnMATCHR)的值相等時(shí),輸出PWM 信號失效。通過軟件可以設(shè)定PWM 輸?shù)男?/font> 號有效和信號無效的電平狀態(tài)。當(dāng)GPTMCTL 寄存器的TnPWML 位值為0 時(shí),信號有效 為高電平,信號無效為低電平;TnPWML 位值為1 時(shí),則反之。如圖 4.1 所示。 輸出信號 計(jì)數(shù) 0x411A 0xC350 TnPWML=0 TnPWML=1 TnEN置位 GPTMTnR=GPTMnMR GPTMTnR=GPTMnMR 時(shí)間 圖 4.1 16 位PWM 模式輸出 占空比的約定:占空比為在一個(gè)周期內(nèi),輸出有信號有效電平占整個(gè)周期時(shí)間的比率。 在這里為以統(tǒng)一軟件控制的約定,用戶API 函數(shù)輸入的占空比值越大,電機(jī)轉(zhuǎn)速越快,正 向運(yùn)行和反向運(yùn)行都一樣。 為了簡化占空比輸出的計(jì)算,將計(jì)數(shù)寄存器與匹配寄存器值相等時(shí),輸出的電平信號 為驅(qū)動(dòng)電機(jī)的有效信號。例如將PWM 周期時(shí)間設(shè)定為60000 個(gè)時(shí)鐘節(jié)拍,需要輸出驅(qū)動(dòng) 電機(jī)的占空比為75%,則設(shè)置匹配寄存器值為75*6000。 由于電機(jī)的轉(zhuǎn)向不一樣,所以電機(jī)驅(qū)動(dòng)的有效電平也需要調(diào)整,通過控制TnPWML 實(shí)現(xiàn)。 2 程序設(shè)計(jì) Timer0 的兩路16 定時(shí)器TimerA 和TimerB 的PWM 輸出引腳分別為PB0 和PB6,PB0 和PB6 分別控制左輪和右輪驅(qū)動(dòng)器TA7291S 的IN1 引腳,而它們的IN2 引腳分別由GPIO 輸出的PA4 和PA5 控制。 左輪的控制函數(shù)如程序清單 4.1 所示。 該函數(shù)的第1 個(gè)參數(shù)sel 為選擇輪子的控制方式:0 為停止,1 為輪子向前,2 為輪子 向后;percen 參數(shù)為占空比,其最大值為99,最小值為1,對于輪子的停止控制該參數(shù)無 效。 程序清單 4.1 左輪控制函數(shù) void LeftWheelRun(int sel,unsigned char percen) { switch(sel) { /*輪子停止轉(zhuǎn)動(dòng)*/ case 0: TimerDisable(TIMER0_BASE,TIMER_A); // 禁止定時(shí)器 GPIOPinWrite(GPIO_PORTA_BASE,LWC2,0xff); // 控制引腳輸出高電平 GPIODirModeSet(GPIO_PORTB_BASE, LWC1, GPIO_DIR_MODE_OUT); // GPIO 輸出 GPIOPinWrite(GPIO_PORTB_BASE,LWC1, 0xff); // GPIO 輸出高電平 break; /*左輪向前*/ case 1: GPIOPinWrite(GPIO_PORTA_BASE,LWC2, 0xff); // PA4 輸出高電平 TimerControlLevel(TIMER0_BASE,TIMER_A,true); // PWM 有效電平方向 GPIODirModeSet(GPIO_PORTB_BASE, LWC1, GPIO_DIR_MODE_HW); // PWM 輸出 TimerMatchSet(TIMER0_BASE,TIMER_A,percen*600); // 設(shè)置占空比 TimerEnable(TIMER0_BASE,TIMER_A); // 使能定時(shí)器 break; /*左輪向后*/ case 2: GPIOPinWrite(GPIO_PORTA_BASE,LWC2, 0); // PA4 輸出低電平 TimerControlLevel(TIMER0_BASE,TIMER_A,false); // PWM 有效電平方向 GPIODirModeSet(GPIO_PORTB_BASE, LWC1, GPIO_DIR_MODE_HW); // PWM 輸出 TimerMatchSet(TIMER0_BASE,TIMER_A,percen*600); // 設(shè)置占空比 TimerEnable(TIMER0_BASE,TIMER_A); // 使能定時(shí)器 break; } } 右輪的控制函數(shù)如程序清單 4.2 所示。 該函數(shù)的第1 個(gè)參數(shù)sel 為選擇輪子的控制方式:0 為停止,1 為輪子向前,2 為輪子 向后;percen 參數(shù)為占空比,其最大值為99,最小值為1,對于輪子的停止控制該參數(shù)無 效。 程序清單 4.2 右輪控制函數(shù) void RightWheelRun(int sel,unsigned char percen) { switch(sel) { /*輪子停止轉(zhuǎn)動(dòng)*/ case 0: TimerDisable(TIMER0_BASE,TIMER_B); // 禁止定時(shí)器 GPIOPinWrite(GPIO_PORTA_BASE,RWC2,0xff); // 控制引腳輸出高電平 GPIODirModeSet(GPIO_PORTB_BASE, RWC1, GPIO_DIR_MODE_OUT); // GPIO 輸出 GPIOPinWrite(GPIO_PORTB_BASE,RWC1,0xff); // GPIO 輸出高電平 break; /*右輪向后*/ case 2: GPIOPinWrite(GPIO_PORTA_BASE,RWC2, 0xff); // PA4 輸出高電平 TimerControlLevel(TIMER0_BASE,TIMER_B,true); // PWM 有效電平方向 GPIODirModeSet(GPIO_PORTB_BASE, RWC1, GPIO_DIR_MODE_HW); // PWM 輸出 TimerMatchSet(TIMER0_BASE,TIMER_B,percen*600); // 設(shè)置占空比 TimerEnable(TIMER0_BASE,TIMER_B); // 使能定時(shí)器 break; /*右輪向前*/ case 1: GPIOPinWrite(GPIO_PORTA_BASE,RWC2, 0); // PA4 輸出低電平 TimerControlLevel(TIMER0_BASE,TIMER_B,false); // PWM 有效電平方向 GPIODirModeSet(GPIO_PORTB_BASE, RWC1, GPIO_DIR_MODE_HW); // PWM 輸出 TimerMatchSet(TIMER0_BASE,TIMER_B,percen*600); // 設(shè)置占空比 TimerEnable(TIMER0_BASE,TIMER_B); // 使能定時(shí)器 break; } } 需要注意的是,當(dāng)PWM 信號禁止后,其輸出引腳的電平狀態(tài)是保持靜止時(shí)的狀態(tài)(可 能為低電平也可能為高電平),導(dǎo)致電機(jī)可能不能停止,所以在制停電機(jī)時(shí),需要將PWM 引腳改為GPIO 輸出,并且出高電平,使電機(jī)剎車停止。 定時(shí)器PWM 初始化函數(shù)如程序清單 4.3 所示。 程序清單 4.3 定時(shí)器PWM 初始化 void PWMTimer0AIni(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // 使能定時(shí)器0 模 塊 GPIODirModeSet(GPIO_PORTB_BASE, LWC1|RWC1 , GPIO_DIR_MODE_OUT); /* 控制引腳輸出*/ GPIOPinWrite(GPIO_PORTB_BASE, LWC1|RWC1 , 0xff); // GPIO 輸出高電 平 GPIODirModeSet(GPIO_PORTA_BASE, LWC2|RWC2 , GPIO_DIR_MODE_OUT); // 控制引腳輸出 GPIOPinWrite(GPIO_PORTA_BASE, LWC2|RWC2 , 0xff); // GPIO 輸出高電 平 /* 定時(shí)器配置*/ TimerConfigure(TIMER0_BASE,TIMER_CFG_16_BIT_PAIR |TIMER_CFG_A_PWM|TIMER_CFG_B_PWM); // 16 位PWM 輸出 TimerControlLevel(TIMER0_BASE,TIMER_A,false); //有效信號為低電 平 TimerControlLevel(TIMER0_BASE,TIMER_B,false); TimerLoadSet(TIMER0_BASE,TIMER_A,60000); // 設(shè)定PWM 頻率 TimerLoadSet(TIMER0_BASE,TIMER_B,60000); } Micromouse 車速檢測 車速檢測程序設(shè)計(jì) 本設(shè)計(jì)中選用了LM3S102 的PA0 和PB1 分別檢測左輪和右輪的下降沿的脈沖個(gè)數(shù), 為了快速向應(yīng)檢測信號,使用了下降沿觸發(fā)中斷。LM3S102 單片機(jī)的特點(diǎn),任何一個(gè)GPIO 引腳都可以配置為中斷輸入,并且可以作任意設(shè)定為高電平觸發(fā)、低電平觸發(fā)、下降沿觸 發(fā)、上升沿觸發(fā)和上升或下降沿觸發(fā)5 種模式。本應(yīng)用中使用下降沿觸發(fā),其初始化如程 序清單 5.1 所示。 程序清單 5.1 輪子脈沖檢測初始化 void WheelPulseIni(void) { // 配置引腳為輸入 GPIODirModeSet(GPIO_PORTA_BASE, PULSE_R, GPIO_DIR_MODE_IN); GPIODirModeSet(GPIO_PORTB_BASE, PULSE_L, GPIO_DIR_MODE_IN); // 配置引腳下降沿觸發(fā)中斷 GPIOIntTypeSet(GPIO_PORTA_BASE,PULSE_R,GPIO_FALLING_EDGE); GPIOIntTypeSet(GPIO_PORTB_BASE,PULSE_L,GPIO_FALLING_EDGE); // 使能引腳輸入中斷 GPIOPinIntEnable(GPIO_PORTA_BASE,PULSE_R); GPIOPinIntEnable(GPIO_PORTB_BASE,PULSE_L); // 使能GPIO PA 口和GPIO PB 口中斷 IntEnable(INT_GPIOA); IntEnable(INT_GPIOB); } 左右輪檢測脈沖中斷處函數(shù)如程序清單 5.2 所示。 程序清單 5.2 左右輪檢測脈沖中斷處函數(shù) //------------------------------------------------------------------------------------ // 函數(shù)名稱: GPIO_Port_A_ISR // 函數(shù)功能: 右輪檢測脈沖中斷處函數(shù) //------------------------------------------------------------------------------------ void GPIO_Port_A_ISR (void) { unsigned char IntStatus; IntStatus = GPIOPinIntStatus(GPIO_PORTA_BASE,true); // 讀PA 口中斷狀態(tài) if(IntStatus&PULSE_R) // 是否為左輪脈沖中斷 { PulCount_R++; if(PulCount_R >= RightPulse) { RightWheelRun(0, 1); WheelStop_R= 1; } GPIOPinIntClear(GPIO_PORTA_BASE,PULSE_R); // 清中斷 } } //------------------------------------------------------------------------------------ // 函數(shù)名稱: GPIO_Port_B_ISR // 函數(shù)功能: 左輪檢測脈沖中斷處函數(shù) //------------------------------------------------------------------------------------ void GPIO_Port_B_ISR (void) { unsigned char IntStatus; IntStatus = GPIOPinIntStatus(GPIO_PORTB_BASE,true); // 讀PA 口中斷狀態(tài) if(IntStatus&PULSE_L) // 是否為右輪脈沖中斷 { PulCount_L++; if(PulCount_L>= LeftPulse) { WheelStop_L= 1; LeftWheelRun(0, 1); } GPIOPinIntClear(GPIO_PORTB_BASE,PULSE_L); // 清中斷 } } 六、 系統(tǒng)DV:參看附件: a) 直線行走3格+右轉(zhuǎn): 該運(yùn)動(dòng)中,小車首先直線行走3格(50CM),然后右轉(zhuǎn),并在碰到障礙物后右轉(zhuǎn),直線行走一格,再右轉(zhuǎn)一次; b) 圍繞小桌運(yùn)動(dòng): 該運(yùn)動(dòng)中,小車圍繞方形小桌繞圈,判斷安全距離、檢測是否存在通路,并自動(dòng)修正方向。 七、 測試情況: 經(jīng)檢測,小車能較好的完成給定的運(yùn)行任務(wù),較為準(zhǔn)確地直走、左右轉(zhuǎn),及180度轉(zhuǎn)。小車完全可以完成探究迷宮、自動(dòng)尋路等任務(wù),并以較短的時(shí)間完成迷宮行走。 但是,小車依舊存在些問題:直走中有擺動(dòng)現(xiàn)象,左右轉(zhuǎn)也做不到90度(大概85度到95度之間),180度更不好;算法不夠優(yōu)秀,時(shí)間依舊較長。雖然這些問題更為瑣碎更為難處理,但我們有信心,暑假間會(huì)完全克服。 八、 曾遇到的問題:
1.車輪行進(jìn)速度不一:
同一函數(shù)中,小車的左右轉(zhuǎn)速相差比較大,我們嘗試采取了以下幾種方式解決
1)。調(diào)占空比:無效,原因不明。在與別的小組交流之后,我們嘗試改寫了原先的驅(qū)動(dòng)函數(shù),使速度函數(shù)與正反轉(zhuǎn)函數(shù)區(qū)分開:
(原函數(shù) & 改進(jìn)后的函數(shù) 請見附錄)
還不太明白是為什么,把兩個(gè)函數(shù)分開寫了之后,發(fā)現(xiàn)有一定效果。
2)。脈沖補(bǔ)償:
這也是演示程序的方法,在執(zhí)行完一次運(yùn)行任務(wù)之后,把相差的脈沖補(bǔ)償?shù)较乱淮稳蝿?wù)的設(shè)定中:
PWMTimer0AIni(); // PWM初始化
PULSEIni(); // 調(diào)制信號初始化
WheelPulseIni(); // 測速初始化
while(1)
{
LeftPulse = 10; // 設(shè)定電機(jī)運(yùn)行任務(wù)
RightPulse = 10;
WheelStop_L = 0; // 清零電機(jī)停止標(biāo)志位
WheelStop_R = 0;
LeftWheelRun(1, 99); // 啟動(dòng)左右電機(jī)
RightWheelRun(1, 99);
while(!(WheelStop_L && WheelStop_R))// 等待運(yùn)行結(jié)束,狀態(tài)在中斷中改變
Check_Infrared(0); // 等待過程中進(jìn)行紅外檢測
PulCount_L -= LeftPulse; // 誤差補(bǔ)償?shù)较乱淮芜\(yùn)動(dòng)中
PulCount_R -= RightPulse;
}
想法很好,實(shí)際行不通。
以最低誤差來算,假設(shè)左輪10個(gè)脈沖,右輪9個(gè),小車明顯走出一條弧線;而當(dāng)下次補(bǔ)償?shù)较麓沃袝r(shí),小車還是先走同樣的路程,然后左輪停轉(zhuǎn),右輪轉(zhuǎn)2個(gè)脈沖(上次誤差+ 這次誤差),表現(xiàn)出了明顯的“一瘸一拐”的情況;而且,在我們的調(diào)試過程中,出現(xiàn)了不穩(wěn)定的左右擺動(dòng),這是由于“半個(gè)脈沖”的問題,小車不能有效識(shí)別比較小的距離差,在最好的狀態(tài)下,小車也存在計(jì)數(shù)的問題,比如,左輪剛轉(zhuǎn)就開始向下的觸發(fā),右輪快轉(zhuǎn)一圈才有第一次的向下觸發(fā)。而且,這種誤差是隨機(jī)的,與小車車輪的起始位置有關(guān),不好避免。
3).從硬件下手:
在左右電機(jī)同加固定電壓時(shí),清楚地看到轉(zhuǎn)速不一樣,因此,最好的辦法還是從硬件上下手,通過串聯(lián)電阻來解決問題。這是我們的一個(gè)想法,還沒開始實(shí)施,準(zhǔn)備在暑假時(shí)再想想軟件解決辦法,不行就改電路。(電機(jī)內(nèi)阻,運(yùn)行時(shí)電流)
2。檢測信號的波形:
受燈光的影響,可以看到,紅外接受得到的波形不時(shí)很好。檢測初速的還好,因?yàn)榉缺容^大,所以沒有誤判的問題;檢測擋板的波形振動(dòng)比較大。按照電路圖,嘗試著變換的電阻,取得不錯(cuò)的效果,以下函數(shù)足夠完成判斷:
( 源程序詳見附錄)
3。編譯器的問題:
大量鐵的事實(shí)證明,crosswork不好用,推薦使用Keil for ARM。前期使用的是crosswork,很多不明就里的問題,換到Keil for ARM就解決了,說明crosswork對小車的支持不夠好。很多函數(shù),在crosswork上,完全起不到效果,跑出來都知道是怎么回事。我們不是在責(zé)怪crosswork不好,但至少說明,不易于上手。
總結(jié)了一些發(fā)現(xiàn)的問題:
1)。不能出現(xiàn)漢字:還好,無非就是存盤載入時(shí)麻煩點(diǎn)。
2)。只能裝C盤:剛開始裝在D盤,整天藍(lán)屏。
3)。頭文件載入:很多頭文件需要手動(dòng)一一載入,還是查百度知道的,說明文件上沒有。
4)。編譯顯示錯(cuò)誤,不顯示為什么錯(cuò):開始時(shí),發(fā)現(xiàn)錯(cuò)誤就在Keil上找錯(cuò)。。。。。。
5)。脫機(jī)運(yùn)行問題:想脫機(jī)運(yùn)行?需要改很多。。。。。。
因此,不推薦用crosswork。
|