提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔


文章目錄

  • 前言
  • 一、整體思路及器件
  • 二、主要程序
  • 1.自動避障函數
  • 2.舵機超聲波掃描函數
  • 3.數據處理函數
  • 4.超聲波觸發及超時處理函數
  • 5.小車控制程序
  • 三.手機APP
  • 總結
  • 效果視頻
  • 完整代碼



前言

本項目實現超聲波舵機自動避障,手機連接藍牙控制小車運動、調速兩個功能並實現兩個功能的切換。

一、整體思路及器件

整體思路:
1.T1作為串口的波特率發生器,串口連接HC06藍牙模塊(從機)與手機連接,手機發送數據後對數據進行判斷執行對應程序,包括藍牙模式和自動避障模式的切換。
2.T0作為電機的PWM控制(精度0.1%),程序設置6個檔速(0%,20%,40%,60%,80%,100%),通過輸出對應占空比的PWM控制。
3.T2複用為超聲波模塊高電平時間計數和舵機的特定PWM輸出,通過不同時間執行不同的初始化函數實現對超聲波和舵機的操作。
4.利用舵機和超聲波模塊對不同角度測距,順序為0>45>90>-45>-90,按照這個順序如果檢測到無障礙則後面的不再測距,並進行對應的運動。
5.超聲波模塊採集7個數據(延時足夠時間採集數據),進行選擇排序後去除最大最小值,將剩下的數據求平均值與閾值比較(直行70cm,其他方向50cm),可在頭文件修改。
5.通過超聲波的時序觸發超聲波測距,但由於距離太短時會延遲甚至卡住,因此進行了超時設置,80ms未觸發超聲波測距則進行小車後退操作。
6.具體思路請看項目文件
器件:
STC89C52RC最小核心板,SG90舵機,HC-SR04超聲波模塊,HC06藍牙模塊(從機),L298N電機驅動,小車套件。

二、主要程序

1.自動避障函數

/** 
  * @brief   通過超時波測距控制小車避障            
  * @param  無
  * @retval 無
  */
void auto_control(void)
{
	unsigned char test=0;//存儲距離平均值
	test=obstacle_scan();//距離採樣
	
	//與對應位置對比,執行操作
	if(timeout==1)//超聲波超時執行後退(需要掃描完全部角度再執行)
	{
		car_start();car_back();Delay(30);car_stop();logo=0;timeout=0;
	}
	
	else if(test&0x04)//直行
	{
		car_start();car_forward();Delay(10);//停車操作在obstacle_scan()函數,遇到前方有阻礙會執行本文件38行
	}
	else if(test&0x02)//前進右轉(小幅度轉彎)
	{
		car_start();car_forward_right();Delay(50);car_stop();
	}
	else if(test&0x01)//前進右轉(較大幅度轉彎,通過延時設定小車向右轉動90度,但不準確,要按需調製延時時間)
	{
		car_start();car_forward_right();Delay(80);car_stop();
	}
	else if(test&0x08)//前進左轉(小幅度轉彎)
	{
		car_start();car_forward_left();Delay(50);car_stop();
	}
	else if(test&0x10)//前進左轉(較大幅度轉彎,通過延時設定小車向左轉動90度,但不準確,要按需調製延時時間?
	{
		car_start();car_forward_left();Delay(80);car_stop();
	}
	else if(test==0)//前方左右都有阻礙,掉頭,通過延時設定小車掉頭,但不準確,要按需調試延時時間
	{
		car_start();car_forward_left();Delay(120);car_stop();
	}
	else//意料之外的情況,返回藍牙模式
	{
		SBUF='\a';while(TI==0);TI=0;control_mode=1;
	}
}

2.舵機超聲波掃描函數

/** 
  * @brief  利用舵機和超聲波對不同位置測距,順序為0>45>90>-45>-90, 小車執行順序也是如此              
  * @param  無
  * @retval place:位置數據 有阻礙:0,無阻礙:1
						第1位:90
						  2  :45
							3  :0
							4  :-45
							5  :-90
  */
unsigned char obstacle_scan(void)
{
	//清零
	place=0;
	average=0;
	
	//0度採樣
	SG90_turn(0);	//舵機轉到0度位置
	Timer2_SG90_Init();//初始化舵機定時器2設置
	Delay(1);//等待轉到特定位置
	Timer2_Init();//重新初始化定時器2,為超聲波測距準備
	Delay(70);//延時,採樣
	average=distance_average();//對採樣數據(5個)求平均值
	if(average>forward_standard)//平均值與設定閾值比較
	{
		place|=0x04;//如果無阻礙則對應位置設置為1,反之為0
		return place;
	}
	average=0;//清零
	
	//如果測到前方有阻礙,則減速停車,防止下面測其他位置時車還在跑
	car_back();
	Delay(1);
	car_stop();
	
	//45度採樣
	SG90_turn(45);
	Timer2_SG90_Init();
	Delay(10);
	Timer2_Init();
	Delay(70);
	average=distance_average();
	if(average>standard)
	{
		place|=0x02;
		return place;
	}
	average=0;
	
	//90度採樣
	SG90_turn(90);
	Timer2_SG90_Init();
	Delay(1);
	Timer2_Init();
	Delay(70);
	average=distance_average();
	if(average>standard)
	{
		place|=0x01;
		return place;
	}
	average=0;

	//-45度採樣
	SG90_turn(-45);	
	Timer2_SG90_Init();
	Delay(1);
	Timer2_Init();
	Delay(70);
	average=distance_average();
	if(average>standard)
	{
		place|=0x08;
		return place;
	}
	average=0;

	//-90度採樣
	SG90_turn(-90);
	Timer2_SG90_Init();
	Delay(1);
	Timer2_Init();
	Delay(70);
	average=distance_average();
	if(average>standard)
	{
		place|=0x10;
		return place;
	}
	average=0;
	
	return 0;
}

3.數據處理函數

/** 
  * @brief   求平均數               
  * @param  	無
  * @retval 	無
  */
unsigned int distance_average(void)
{
	unsigned int distance_number=0;
	unsigned int linshi=0;
	unsigned char xiabiao;
	unsigned char i;
	unsigned char j;
	
	for(i=0;i<6;i++)//選擇排序:從大到小
	{
		xiabiao=i;
		for(j=i+1;j<7;j++)
		{
			if(distance[xiabiao]<distance[j])
			{
				xiabiao=j;			
			}
		}
		if(i!=xiabiao)
		{
			linshi=distance[i];
			distance[i]=distance[xiabiao];
			distance[xiabiao]=linshi;
		}
	}

	for(i=1;i<6;i++)//採取1-5的數據,去除最大最小值
	{
		distance_number+=distance[i];
	}
	Delay(1);
	
	return (distance_number/5);
}

4.超聲波觸發及超時處理函數

/** 
  * @brief  計算超聲波模塊高電平時間                
  * @param  無
  * @retval 無
  */
unsigned int ultrasound(void)
{	
	if(Echo==0)//低電平時計算距離
	{	
		if(i>7)//存儲5個數值,用來求平均數
		{
			i=0;
		}
		if(logo==0&&count<38)//前面超聲波啓動測距過才計算和超時數值(38ms)
		{
			distance[i]=count*340/20;//計算距離,單位:cm count:17cm,
			i++;
		}
		logo++;//超聲波啓動失敗次數+1
		if(logo>80)//超聲波啓動失敗次數
		{
			timeout=1;//超聲波超時,執行對應運動
		}
		//觸發超聲波模塊發送超聲波
		count=0;
		Trig=0;	
		Trig=1;
		Delay(1);//模塊至少需要10us觸發

	}
	else//高電平時定時器計算
	{
		logo=0;//超聲波啓動成功
		count++;//每增加1時間增加1ms
		if(count>38)//防止超時
		{
			return 1;
		}
	}
 	 
	return 0;

}

5.小車控制程序

//電機A停止
void motorA_stop(void)
{
	ENA_control=0;
}

//電機A啓動
void motorA_start(void)
{
	ENA_control=1;
}

//電機A正轉
void motorA_reverse(void)
{
	ENA_control=1;
	IN1=1;
	IN2=0;
}

//電機A反轉
void motorA_forward(void)
{
	ENA_control=1;
	IN1=0;
	IN2=1;

}

//電機B停止
void motorB_stop(void)
{
	ENB_control=0;
}

//電機B啓動
void motorB_start(void)
{
	ENB_control=1;
}

//電機B正轉
void motorB_forward(void)//正轉
{
	ENB_control=1;
	IN3=1;
	IN4=0;
}

//電機A反轉
void motorB_reverse(void)//反轉
{
	ENB_control=1;
	IN3=0;
	IN4=1;
}

//小車停止
void car_stop(void)
{
	motorA_stop();
	motorB_stop();
}

//小車啓動
void car_start(void)
{
	motorB_start();
	motorA_start();
}

//小車後退
void car_back(void)
{
	motorA_reverse();
	motorB_reverse();
}

//小車前進
void car_forward(void)
{
	motorA_forward();
	motorB_forward();
}

//小車前進右轉
void car_forward_right(void)
{
	 motorA_stop();
	 motorB_forward();
}

//小車前進左轉
void car_forward_left(void)
{
	 motorB_stop();
	 motorA_forward();
}

//小車後退右轉
void car_back_right(void)
{
	 motorA_stop();
	 motorB_reverse();
}

//小車後退左轉
void car_back_left(void)
{
	 motorB_stop();
	 motorA_reverse();
}

三.手機APP

APP界面:

android 控制 舵機_#c語言

註明:這個APP是某位博主分享出來的,具體忘記是誰了,敬請原諒,後面會給我的鏈接。

總結

本項目能較好實現上述的功能,但由於硬件的一些限制還是會有一點問題。就這些問題進行如下説明:
1.通過延時實現小車轉動90,掉頭等動作會因小車的區別而不同,需要根據實際情況調製延時函數參數,不過萬向輪也會影響。
2.本項目在運行是會發現小車直行時偏向左/右邊,排除程序問題,初步判定是小車萬向輪偏置導致(如有解決辦法請告知本人,謝謝)。
3.因超聲波模塊的硬件限制,在對條狀物體的測距數據會不準確或者判斷為無障礙。
4.因小車運動過程中,測距需要一定時間導致小車過於靠近物體時,測距時間會延遲甚至卡在哪裏(預測是給超聲波用到定時器2定時時間太大(1ms),因距離太近,超聲波高電平時間太短導致還沒輪詢到就變為低電平,count為0,數據不存儲到數組),如果用外部中斷觸發可能可以避免。
解決方法:設置超聲波超時時間80ms(timeout,logo變量控制),超過時間執行後退,但仍需超聲波模塊掃描所有角度後才執行,不過延遲時間還是有點長但有所改善且不會卡在哪裏。

PS:第一次寫文章,如有錯誤,望讀者指正

效果視頻


51智能小車效果視頻


特別説明:小車直行走歪是因為後面的萬向輪喜歡偏向一邊,還有超聲波觸發超時的後退效果也是因為萬向輪的支柱那裏會卡着萬向輪轉動所影響,如果誰有辦法解決麻煩告訴一下我。

完整代碼

完整項目鏈接:

鏈接:https://pan.baidu.com/s/1bl1Y7Khw_wWOs6SlqCGAxQ
提取碼:xikd

APP鏈接:

鏈接:https://pan.baidu.com/s/10W6NuANZr1kCNk3GbCk6Og
提取碼:xikd