|
避障小車程序?qū)崿F(xiàn)功能:
1.藍(lán)牙控制,重力感應(yīng),通過串口通訊實現(xiàn)手機(jī)和藍(lán)牙之間的連接控制用到hc-06模塊
2.循跡壁障,遇見障礙能夠及時躲避,通過舵機(jī)帶動hc-sr04超聲波模塊的左右轉(zhuǎn)動來測量前左右的障礙
3.跟蹤,可以追蹤一個物體,物進(jìn)車進(jìn),物退車退
4.走黑線,不同顏色的物體對光的反射不同
4.pwm速度快慢調(diào)速,通過pwm調(diào)節(jié)l298n產(chǎn)生脈寬調(diào)制
5.開燈,通過手機(jī)控制單片機(jī)的io口輸出高低電頻實現(xiàn)
6.喇叭,高低電頻產(chǎn)生震蕩
********************************************************************************/
/********************************************************************************
避障小車出現(xiàn)的問題:
1.主要是定時器優(yōu)先級別問題,解決辦法調(diào)節(jié)定時器優(yōu)先級別,第一次掌握了定時器二的用法,這是52特有的
2.切記,定時器0不能和定時器1互換,因為定時器1優(yōu)先級沒有0高,互換會導(dǎo)致超聲波測距模塊接受不到數(shù)據(jù)
3.出現(xiàn)模塊從諜,的問題,解決辦法用標(biāo)記把可能出問題模塊一個一個標(biāo)記;最后發(fā)現(xiàn)原來是延時函數(shù)名字相同
4.字符串不能直接比較需要用if(strcmp(字符串,字符串2)==0)如果一樣就返回一個0,如果一比二大就返回
一個正數(shù)否則返回負(fù)數(shù)記住需要包含#include<string.h>頭文件
5.舵機(jī)不能兩個地方同時出現(xiàn)歸中,剛開始以為是定時器優(yōu)先級別的問題,打開定時器1串口通訊就會制動打開
所以我在串口函數(shù)里設(shè)了點亮led燈來測試串口中斷是否自己打開,然后我先是注釋ET1發(fā)現(xiàn)程序正常,
后面又注釋掉中斷3發(fā)現(xiàn)程序正常,說明不是定時器設(shè)置問題, 注釋掉中斷三里的內(nèi)容發(fā)現(xiàn)也正常說明不是中斷引起的
然后注釋掉舵機(jī)pwm調(diào)速,發(fā)現(xiàn)也正常說明不是小車檔位pwm的問題最后注釋掉小車快慢pwm調(diào)速,發(fā)現(xiàn)舵機(jī)函數(shù)有問題
然后注釋掉舵機(jī)pwm調(diào)速里的eles發(fā)現(xiàn)不正常,之后嘗試了改pwm輸出口的名字以及io口發(fā)現(xiàn)都沒用,最后拔掉舵機(jī)信號線
發(fā)現(xiàn)有用,說明舵機(jī)初始化有問題,最后把初始化里的歸中14,該成0,發(fā)現(xiàn)能正常運作,最后把初始化該成14,注釋掉
超聲波次主函數(shù)的歸中發(fā)現(xiàn)能正常運作,說明兩個歸中只能要一個。
結(jié)論;一點要細(xì)致認(rèn)真,勤于思考,碰到問題要迎難而上因為編程本來就是個改錯的過程別碰到問題就想著
問別人,因為自己的程序只有自己最了解,寫代碼一定要規(guī)范,免得到時后亂起來連自己都看不懂。
11月13日,吳才成
下面是制作的避障小車的實物圖:
psb.jpg (29.33 KB, 下載次數(shù): 137)
下載附件
2017-12-5 10:27 上傳
psb (6).jpg (25.11 KB, 下載次數(shù): 131)
下載附件
2017-12-5 10:27 上傳
psb (5).jpg (20.49 KB, 下載次數(shù): 137)
下載附件
2017-12-5 10:27 上傳
psb (4).jpg (24.35 KB, 下載次數(shù): 120)
下載附件
2017-12-5 10:27 上傳
psb (3).jpg (18.53 KB, 下載次數(shù): 121)
下載附件
2017-12-5 10:27 上傳
psb (2).jpg (26.39 KB, 下載次數(shù): 130)
下載附件
2017-12-5 10:27 上傳
psb (1).jpg (25.35 KB, 下載次數(shù): 106)
下載附件
2017-12-5 10:27 上傳
51單片機(jī)避障小車源程序如下:
- #include<AT89X52.H>
- #include<string.h> //字符串比較頭文件
- #include <intrins.h> //nop的頭文件
- #define Left_moto_go {P3_1=1,P3_2=0,P3_3=1,P3_4=0;} //左邊兩個電機(jī)向前走
- #define Left_moto_back {P3_1=0,P3_2=1,P3_3=0,P3_4=1;} //左邊兩個電機(jī)向后轉(zhuǎn)
- #define Left_moto_Stop {P3_1=0,P3_2=0,P3_3=0,P3_4=0;} //左邊兩個電機(jī)停轉(zhuǎn)
- #define Right_moto_go {P1_4=1,P1_5=0,P1_6=1,P1_7=0 ;} //右邊兩個電機(jī)向前走
- #define Right_moto_back {P1_4=0,P1_5=1,P1_6=0,P1_7=1;} //右邊兩個電機(jī)向前走
- #define Right_moto_Stop {P1_4=0,P1_5=0,P1_6=0,P1_7=0;} //右邊兩個電機(jī)停轉(zhuǎn) */
- /***************************************************************/
- //藍(lán)牙的設(shè)置
- /*****************************************************************/
- void zxddc (); //轉(zhuǎn)向燈 后退 剎車指示燈
- void zxdzz (); //轉(zhuǎn)向燈左轉(zhuǎn)
- void zxdyz (); //轉(zhuǎn)向燈右轉(zhuǎn)
- void zxdgd (); //轉(zhuǎn)向燈關(guān)燈
- sbit LEDHZ = P3^5; //轉(zhuǎn)向燈左邊
- sbit LEDHY = P3^6; //轉(zhuǎn)向燈右邊
- sbit LED1 = P1^0 ; //左方向燈
- sbit LED2 = P1^1 ; //右方向燈
- sbit fmq = P1^2 ; //喇叭,蜂鳴器
- int pwmjishu = 0 ; //pwm調(diào)速
- int pushjishu = 0 ; //pwm調(diào)速
- sbit ena1 = P2^7;
- sbit enb1 = P2^6; //l298npwm調(diào)速引腳
- sbit ena2 = P2^5;
- sbit enb2 = P2^4;
- unsigned char data table[4]={ 0,0,0,};//用來裝串口發(fā)送過來的字符串,不包括0
- /***************************************************************/
- //超聲波的設(shè)置
- /*********************************************************/
- #define CSBPWM P2_2 //接舵機(jī)信號端輸入PWM信號調(diào)節(jié)速度
- #define ECHO P2_0 //超聲波接口定義
- #define TRIG P2_1 //超聲波接口定義
- unsigned char disdat[4]={ 0,0,0,0,};
- unsigned char pwm_val_left = 0;//變量定義
- unsigned char push_val_left =0;//14;//舵機(jī)歸中,產(chǎn)生約,1.5MS 信號
- unsigned long S=0;
- unsigned long S1=0;
- unsigned long S2=0;
- unsigned long S3=0;
- unsigned long S4=0;
- unsigned int time=0; //時間變量
- unsigned int timer=0; //延時基準(zhǔn)變量
- unsigned char timer1=0; //掃描時間變量
- void qianj(void) //前進(jìn)
- {
- Left_moto_go ; //左電機(jī)往前走
- Right_moto_go ; //右電機(jī)往前走
- }
- /************************************************************************/
- //全速后退
- void hout(void) //后退
- {
- Left_moto_back ; //左電機(jī)往前走
- Right_moto_back ; //右電機(jī)往前走
- zxddc (); //后退指示燈
- }
- /********************* ***************************************************/
- //左轉(zhuǎn) //左轉(zhuǎn)
- void zuoz(void)
- {
- Left_moto_back ; //左電機(jī)往前走
- Right_moto_go ; //右電機(jī)往前走
- zxdzz (); //左轉(zhuǎn)指示燈
- }
- /************************************************************************/
- //右轉(zhuǎn)
- void youz(void) //右轉(zhuǎn)
- {
- Left_moto_go ; //左電機(jī)往前走
- Right_moto_back ; //右電機(jī)往前走
- zxdyz (); //右轉(zhuǎn)指示燈
- }
- /************************************************************************/
- //STOP
- void tingz(void) //停止
- {
- Left_moto_Stop ; //左電機(jī)停走
- Right_moto_Stop ; //右電機(jī)停走
- zxdgd (); //車子停止指示燈關(guān)閉
- }
- /************************************************************************/
- /************************************************************************/
- void delay1(unsigned int k) //延時函數(shù)
- {
- unsigned int x,y;
- for(x=0;x<k;x++)
- for(y=0;y<2000;y++);
- }
- /******************************//*******************************************/
- void delay_50us(unsigned int z) //延時函數(shù)
- {
- unsigned int x,y;
-
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
-
- }
- /*************************************************/
- void StartModule() //啟動測距信號
- {
- TRIG=1; //給10us以上的高電頻
- _nop_(); //_nop_()一個機(jī)器周期,1us
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- TRIG=0;
- }
- /***************************************************/
- /**************************************************/
- void Conut(void) //計算距離
- {
- while(!ECHO); //當(dāng)RX為零時等待
- TR0=1; //開啟計數(shù)
- while(ECHO); //當(dāng)RX為1計數(shù)并等待
- TR0=0; //關(guān)閉計數(shù)
- time=TH0*256+TL0; //讀取脈寬長度
- TH0=0;
- TL0=0;
- S=(time*1.7)/100; //算出來是CM
- }
- void COMM( void ) //方向計算
- {
- push_val_left=5; //舵機(jī)向左轉(zhuǎn)90度
- timer=0;
- while(timer<=4000); //延時400MS讓舵機(jī)轉(zhuǎn)到其位置
- StartModule(); //啟動超聲波測距
- Conut(); //計算距離
- S2=S;
-
- push_val_left=23; //舵機(jī)向右轉(zhuǎn)90度
- timer=0;
- while(timer<=4000); //延時400MS讓舵機(jī)轉(zhuǎn)到其位置
- StartModule(); //啟動超聲波測距
- Conut(); //計算距離
- S4=S;
- push_val_left=14; //舵機(jī)歸中
- timer=0;
- while(timer<=4000); //延時400MS讓舵機(jī)轉(zhuǎn)到其位置
- StartModule(); //啟動超聲波測距
- Conut(); //計算距離
- S1=S;
- if((S2<20)||(S4<20)) //只要左右各有距離小于20CM小車后退
- {
- hout(); //后退
- timer=0;
- while(timer<=4000);
- }
- if(S2>S4)
- {
- youz(); //車的左邊比車的右邊距離小 右轉(zhuǎn)
- timer=0;
- while(timer<=4000);
- }
- else
- {
- zuoz(); //車的左邊比車的右邊距離大 左轉(zhuǎn)
- timer=0;
- while(timer<=4000);
- }
- }
- /**********************************************************************************
- 舵機(jī)pwm調(diào)速,和小車換擋調(diào)速共用一個定時器
- ***********************************************************************************/
- void pwm_Servomoto()
- {
-
- if(pwm_val_left<=push_val_left)
- CSBPWM=1;
- else
- CSBPWM=0;
- if(pwm_val_left>=200)
- pwm_val_left=0;
- }
- /************************************************************/
- void Delay(unsigned int i)
- {
- char j;
- for(i; i > 0; i--)
- for(j = 200; j > 0; j--);
- }
- /*****************************************************************/
- void fangx() //方向函數(shù)
- {
- if(strcmp(table,"ONA")==0) qianj();//前進(jìn)
- else if(strcmp(table,"ONB")==0) hout();//后退
- else if(strcmp(table,"ONC")==0) zuoz();//左轉(zhuǎn)
-
- else if(strcmp(table,"OND")==0) youz ();//右轉(zhuǎn)
- else tingz();//停止
-
- // if((a[0]=='O')&&(a[1]='N')&&(a[2]=='A')&&(a[3]==0)) qianj();
- /*if(a=="ONA")qianj();//前進(jìn) 總結(jié)字符串不能用==比較需要調(diào)用內(nèi)部庫函數(shù)
- else if(a=="ONB") hout();//后退
- else if(a=="ONC") zuoz();//左轉(zhuǎn)
-
- else if(a=="OND") youz();//右轉(zhuǎn)
-
- else tingz();//停止 */
- }
- /*****************************************************************************/
- void dangwei() //檔位函數(shù)
- {
- if (strcmp(table,"ON1") ==0 )
- pushjishu=0;
- if (strcmp(table,"ON2") ==0 ) //判斷是否按下按鍵
- {
- //pushjishu=pushjishu+10;
- pushjishu+=10; //x+=y;相當(dāng)與x=x+y;這樣使程序更精煉
- while (strcmp(table,"ON2") ==0 ); //當(dāng)按鍵按下的時候進(jìn)入while循環(huán)執(zhí)行分號空語句,
- //當(dāng)按鍵是釋放跳出while循環(huán),很好的使按鍵按下一次執(zhí)行一次,不會跑飛
- }
- if (strcmp(table,"ON3") ==0 )
- {
- //pushjishu=pushjishu-10;
- pushjishu-=10;
- while (strcmp(table,"ON3") ==0 );
- }
- /* if (strcmp(table,"ON4") ==0 )
- pushjishu=105;
- /*if(strcmp(table,"ON5")==0)
- pushjishu=160;
- if(strcmp(table,"ON6")==0)
- pushjishu=200; */
- }
- /**************************************************************************/
- void zxddc () //轉(zhuǎn)向燈 后退 剎車指示燈 。函數(shù)需要在前面聲明,因為電機(jī)函數(shù)定義在此函數(shù)前面,在電機(jī)函數(shù)調(diào)用此函數(shù)會出現(xiàn)錯誤
- {
- LEDHZ = 0;
- LEDHY = 0;
- }
- void zxdzz () //轉(zhuǎn)向燈左轉(zhuǎn)
- {
- LEDHZ = 0;
- LEDHY = 1;
- }
- void zxdyz () //轉(zhuǎn)向燈右轉(zhuǎn)
- {
- LEDHZ = 1;
- LEDHY = 0;
- }
- void zxdgd () //轉(zhuǎn)向燈關(guān)燈
- {
- LEDHZ = 1;
- LEDHY = 1;
- }
- /***************************************************************************/
- void kaideng() //開前大燈燈函數(shù)
- {
- if ( strcmp(table,"ON7") == 0 ) //開燈
- {
- LED1=0;
- LED2=0;
- }
- if ( strcmp(table,"ON8") == 0 )//關(guān)燈
- {
- LED1=1;
- LED2=1;
- }
- }
- /*************************************************************************/
- void laba()
- {
- if(strcmp(table,"ON9")==0)
- {
- fmq = 1; //給高電平
- Delay(5); //延時
- fmq = 0; //給低電平
- Delay(5);
- }
- }
- /**********************************************************/
- void pwm(void)//小車快慢pwm調(diào)速,是通過l298n完成的
- {
- if(pwmjishu<=pushjishu)
- {
- ena1 = 0;
- enb1 = 0;
- ena2 = 0;
- enb2 = 0; //l298n,實現(xiàn)pwm調(diào)速,當(dāng)給高電頻的時候io引腳有效,給低電平時無效
- }
- else
- {
- ena1 = 1 ;
- enb1 = 1 ;
- ena2 = 1 ;
- enb2 = 1 ;
- }
- if(pwmjishu >= 200)
- pwmjishu = 0;
- }
- /*******************************************************************************
- 超聲波魔術(shù)手程序
- *******************************************************************************/
- void moss ()
- {
- Delay (100);
- push_val_left=14; //舵機(jī)歸中
- while(1) /*無限循環(huán)*/
- {
- dangwei();//檔位
- if(strcmp(table,"ON6")==0) //判斷按鍵 是否按下如果按下就退出csbmian函數(shù),return結(jié)束函數(shù)
- return;
- if(timer>=1000) //100MS檢測啟動檢測一次
- {
- timer=0;
- StartModule(); //啟動檢測
- Conut(); //計算距離
- if(S<10) //距離小于20CM
- hout(); //小車停止
- if(20>S&&S>10) //距離小于20CM
- tingz();
- if(30>S&&S>20) //距離大于,30CM往前走
- qianj();
- else
- if(S>35)
- tingz();
- }
- }
- }
- /****************************************
- 超聲波壁障主函數(shù)
- /***************************************************************/
- /* delay_50us(500);
- TMOD=0X11;
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- TH0=0;
- TL0=0;
- TR1= 1;
- ET1= 1;
- ET0= 1;
- EA = 1; */
- void csbmian ()
- {
- timer=0;
- push_val_left=14; /*舵機(jī)歸中,在初始化的時候歸要不在這歸中,如果兩個地方貴在程序就會出現(xiàn)毛病 兩個地方
- 同時歸中串口中斷無緣無辜的會打開,導(dǎo)致車子不能串口通訊, */
- delay1(50);
- while(1) //無限循環(huán)//
- {
- dangwei();//檔位
- kaideng(); //開燈函數(shù)
- laba(); //鳴笛函數(shù)
-
- if(strcmp(table,"ON6")==0) //判斷按鍵 是否按下如果按下就退出csbmian函數(shù),return結(jié)束函數(shù)
- return;
-
- if(timer>=1000) //100MS檢測啟動檢測一次
- {
- timer=0;
- StartModule(); //啟動檢測
- Conut(); //計算距離
- if(S<45) //距離小于20CM
- {
- hout();
- hout(); //剎車
- hout();
- tingz(); //小車停止
- COMM(); //方向函數(shù)
- }
- else
- if(S>45) //距離大于,30CM往前走
- qianj();
- }
- }
- }
-
- /**********************************************************/
- void main()
- {
- T2CON=0x30; //設(shè)置定時器二為串口波特率模式
- SCON=0x50; //設(shè)置串口方式為1
- RCAP2H=0xff;
- RCAP2L=0xdc; //定時器二自動裝初值16位
- TH2=0xff;
- TL2=0xdc; //定時器二
- TR2=1; //啟動定時器2
- ES=1; //打開串口中斷
- PS=1; //串口優(yōu)先級設(shè)置為最高
- TMOD=0X11; //打開定時器0和定時器1,工作做方式一
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- ET1=1 ; //打開定時器一中斷
- TR1=1 ; //啟動定時器一
- TH0=0; //定時器0初始化
- TL0=0; //切記定時器0不能和定時器一互換,因為定時器0優(yōu)先級比1高,如果換了以后就不能接收超聲波了
- ET0=1; //打開定時器0中斷
- EA=1; //打開總中斷
-
-
-
- /* T2CON=0x30;
- SCON=0x50; //設(shè)置串口方式為1
- RCAP2H=0xff;
- RCAP2L=0xdc;
- TH2=0xff;
- TL2=0xdc;
- TMOD=0X11; //打開定時器0和定時器1,工作做方式一
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- TH0=0; //定時器0初始化
- TL0=0;
- ET1=1 ;
- ET0= 1; //打開定時器0中斷
- TR2=1;
- ES=1;
- PS=1;
- EA=1;
- /*******************************************/
- /* TMOD=0X11;
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- TH0=0;
- TL0=0;
- TR1= 1;
- ET1= 1;
- ET0= 1;
- EA=1; //總開關(guān)
- /******************************************/
- //單獨藍(lán)牙的串口設(shè)置
- /******************************************/
- /*TMOD=0x21;//定時器1工作方式2,8位自動重裝
- TH0=(65536-100)/256; //100US定時
- TL0=(65536-100)%256;
- TH1=0xFd; //11.0592M晶振,9600波特率
- TL1=0xFd;
- PS=1;
- ET0=1 ;
- TR0=1 ;
- TR1=1 ;//打開定時器1
- SM0=0 ;//串口方式1 SM0 SM1 01 允許接收
- SM1=1 ;//SMOD=0 16分頻
- REN=1 ;
- ES=1 ;//打開串口中斷
- EA=1;//開總中斷 */
- //以上跟串口通信初始化有關(guān)
- while(1)
- {
- dangwei();//檔位
- fangx(); //方向函數(shù)
- kaideng(); //開燈函數(shù)
- laba(); //鳴笛函數(shù)
- if(strcmp(table,"ON5")==0)//判斷是否按下第五個按鍵,按下則啟動超聲波模式
- csbmian (); //超聲波模塊的主函數(shù)
- if(strcmp(table,"ON4")==0)//判斷是否按下第四個按鍵,按下則啟動超聲波魔術(shù)手
- moss (); //超聲波魔術(shù)手模塊的主函數(shù)
- }
- }
- /***************************************************/
- ///*TIMER1中斷服務(wù)子函數(shù)產(chǎn)生PWM信號*/
- void pwmdins()interrupt 3 //定時器一,優(yōu)先級別最低
- {
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- pwmjishu++; // 小車快慢的pwm調(diào)速
- pwm(); //小車快慢的pwm函數(shù)
- timer++; //超聲波的基準(zhǔn) 定時器100US為準(zhǔn)。在這個基礎(chǔ)上延時
- pwm_val_left++; //舵機(jī)的pwm調(diào)速基準(zhǔn)時間
- pwm_Servomoto(); //舵機(jī)pwm調(diào)速函數(shù)
- }
- /***************************************************/
- ///*TIMER0中斷服務(wù)子函數(shù)產(chǎn)生PWM信號*/
- void timer0()interrupt 1 //因為串口優(yōu)先級別變最高所以定時器0位第二高
- {
- }
- /***************************************************/
- void serial() interrupt 4 //中斷子函數(shù) //ps=1;使之優(yōu)先級最高
- {
- int i;
- ES=0; //關(guān)閉串口中斷,其實不關(guān)也沒影響
- table[i++]=SBUF; //數(shù)組下標(biāo)加一,把字符串變成字符字單個取出存入數(shù)組,使之成為一元素
- if(i==3) //字符串有三個字符,不包括標(biāo)志位0
- i=0; //使之清零以便下次從收
- RI=0; //串口標(biāo)志位硬件制一,手動清零
- ES=1; //打開串口
- …………
- …………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
原理圖: 無
仿真: 無
代碼:
寶馬自動駕駛.zip
(53.9 KB, 下載次數(shù): 509)
2017-12-5 10:29 上傳
點擊文件名下載附件
程序帶詳細(xì)注解 下載積分: 黑幣 -5
|
評分
-
查看全部評分
|