功能介紹放開頭, 使用便捷無需愁
這是全網最詳細、性價比最高的STM32實戰項目入門教程,通過合理的硬件設計和詳細的視頻筆記介紹,硬件使用STM32F103主控資料多方便學習,通過3萬字筆記、12多個小時視頻、20多章節代碼手把手教會你如何開發和調試。讓你更快掌握嵌入式系統開發。
**V3.3.0-STM32智能小車 **
**視頻: **[https://www.bilibili.com/video/BV16x4y1M7EN/?spm_id_from=333.337.search-card.all.click]
V3:HAL庫開發、功能:PID速度控制、PID循跡、PID跟隨、遙控、避障、PID角度控制、視覺控制、電磁循跡、RTOS等功能。
講解一下我們小車里面的循跡部分,包括紅外基礎使用,無PID循跡和有PID循跡。
第13章-循跡功能
13.1-非PID循跡功能完成
先紅外對管調試
我們這里學習一下,如何實現循跡功能
如何才能讓小車沿著黑線運動、要讓小車感知到黑線的位置,使用這種傳感器就可以反饋黑線是否存在
根據傳感器特性,我們檢測紅外對管DO引腳的電壓就可以知道,下面有沒有黑線
DO 高電平->有黑線 小燈滅
DO低電平->沒有黑線 小燈亮
這是好多地方對這個產品的說明
然后我們組合上面的紅外對管,安裝到小車上,就可以知道小車是否偏離了黑線,
下面我們通過單片機讀取紅外對管DO口的電壓,就知道黑線在小車下面的位置了
STM32初始化
先看原理圖需要初始化那些引腳
把****OUT_1-PA5、OUT_2-PA7、OUT_3-PB0、OUT_4-PB1初始化為輸入模式**
**
重新生成
然后我們在gpio.h 添加讀取GPIO的宏,使得程序更簡潔
#define READ_HW_OUT_1 HAL_GPIO_ReadPin(HW_OUT_1_GPIO_Port,HW_OUT_1_Pin) //讀取紅外對管連接的GPIO電平
#define READ_HW_OUT_2 HAL_GPIO_ReadPin(HW_OUT_2_GPIO_Port,HW_OUT_2_Pin)
#define READ_HW_OUT_3 HAL_GPIO_ReadPin(HW_OUT_3_GPIO_Port,HW_OUT_3_Pin)
#define READ_HW_OUT_4 HAL_GPIO_ReadPin(HW_OUT_4_GPIO_Port,HW_OUT_4_Pin)
根據紅外對管狀態控制電機速度
注意:整個主函數不要加入延時,這樣實時性更高,可以根據紅外對管狀態做出及時控制
if(READ_HW_OUT_1 == 0&&READ_HW_OUT_2 == 0&&READ_HW_OUT_3 == 0&&READ_HW_OUT_4 == 0 )
{
printf("應該前進rn");
motorPidSetSpeed(1,1);//前運動
}
if(READ_HW_OUT_1 == 0&&READ_HW_OUT_2 == 1&&READ_HW_OUT_3 == 0&&READ_HW_OUT_4 == 0 )
{
printf("應該右轉rn");
motorPidSetSpeed(0.5,2);//右邊運動
}
if(READ_HW_OUT_1 == 1&&READ_HW_OUT_2 == 0&&READ_HW_OUT_3 == 0&&READ_HW_OUT_4 == 0 )
{
printf("快速右轉rn");
motorPidSetSpeed(0.5,2.5);//快速右轉
}
if(READ_HW_OUT_1 == 0&&READ_HW_OUT_2 == 0&&READ_HW_OUT_3 == 1&&READ_HW_OUT_4 == 0 )
{
printf("應該左轉rn");
motorPidSetSpeed(2,0.5);//左邊運動
}
if(READ_HW_OUT_1 == 0&&READ_HW_OUT_2 == 0&&READ_HW_OUT_3 == 0&&READ_HW_OUT_4 == 1 )
{
printf("快速左轉rn");
motorPidSetSpeed(2.5,0.5);//快速左轉
}
然后測試
- 測試紅外對管靈敏度,放在有黑線的地上或者紙上,然后把小車黑線比如放到最右邊 及第一個紅外對管,觀察紅外對管小燈變化情況和串口輸出情況,如果小燈沒有滅,就調節紅外對管靈敏度和室內燈光,直到每個紅外對管都可以感應到小燈。
- 然后在黑線上讓小車循跡
然后循跡功能完成
然后放到地上
13.2-加入循跡PID
前面的代碼我們對循跡是判斷的幾個狀態,然后PID控制電機不同速度,但是我們可以使用紅外對管狀態作為PID控制的輸入然后再控制電機。
PID的輸入是紅外對管狀態,我們設計 PID輸入是紅外對管的狀態、然后輸出一個速度值,然后左右電機去加或者減這個值,就可以完成根據紅外對管輸入對電機的差速控制
主函數添加的
extern tPid pidHW_Tracking;//紅外循跡的PID
uint8_t g_ucaHW_Read[4] = {0};//保存紅外對管電平的數組
int8_t g_cThisState = 0;//這次狀態
int8_t g_cLastState = 0; //上次狀態
float g_fHW_PID_Out;//紅外對管PID計算輸出速度
float g_fHW_PID_Out1;//電機1的最后循跡PID控制速度
float g_fHW_PID_Out2;//電機2的最后循跡PID控制速度
然后實現PID循跡控制、注意為了更加快,要減少沒有必要的程序和優化判斷、將沒有必要的輸出都注釋掉
g_ucaHW_Read[0] = READ_HW_OUT_1;//讀取紅外對管狀態、這樣相比于寫在if里面更高效
g_ucaHW_Read[1] = READ_HW_OUT_2;
g_ucaHW_Read[2] = READ_HW_OUT_3;
g_ucaHW_Read[3] = READ_HW_OUT_4;
?
if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0 )
{
//printf("應該前進rn");//注釋掉更加高效,減少無必要程序執行
g_cThisState = 0;//前進
}
else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 1&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0 )//使用else if更加合理高效
{
//printf("應該右轉rn");
g_cThisState = -1;//應該右轉
}
else if(g_ucaHW_Read[0] == 1&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0 )
{
//printf("快速右轉rn");
g_cThisState = -2;//快速右轉
}
else if(g_ucaHW_Read[0] == 1&&g_ucaHW_Read[1] == 1&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 0)
{
//printf("快速右轉rn");
g_cThisState = -3;//快速右轉
}
else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 1&&g_ucaHW_Read[3] == 0 )
{
//printf("應該左轉rn");
g_cThisState = 1;//應該左轉
}
else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 0&&g_ucaHW_Read[3] == 1 )
{
//printf("快速左轉rn");
g_cThisState = 2;//快速左轉
}
else if(g_ucaHW_Read[0] == 0&&g_ucaHW_Read[1] == 0&&g_ucaHW_Read[2] == 1&&g_ucaHW_Read[3] == 1)
{
// printf("快速左轉rn");
g_cThisState = 3;//快速左轉
}
g_fHW_PID_Out = PID_realize(&pidHW_Tracking,g_cThisState);//PID計算輸出目標速度 這個速度,會和基礎速度加減
?
g_fHW_PID_Out1 = 3 + g_fHW_PID_Out;//電機1速度=基礎速度+循跡PID輸出速度
g_fHW_PID_Out2 = 3 - g_fHW_PID_Out;//電機1速度=基礎速度-循跡PID輸出速度
if(g_fHW_PID_Out1 >5) g_fHW_PID_Out1 =5;//進行限幅 限幅速度在0-5之間
if(g_fHW_PID_Out1 < 0) g_fHW_PID_Out1 =0;
if(g_fHW_PID_Out2 >5) g_fHW_PID_Out2 =5;
if(g_fHW_PID_Out2 < 0) g_fHW_PID_Out2 =0;
if(g_cThisState != g_cLastState)//如何這次狀態不等于上次狀態、就進行改變目標速度和控制電機、在定時器中依舊定時控制電機
{
motorPidSetSpeed(g_fHW_PID_Out1,g_fHW_PID_Out2);//通過計算的速度控制電機
}
g_cLastState = g_cThisState;//保存上次紅外對管狀態
在pid.中
tPid pidHW_Tracking;//紅外循跡的PID
?
pidHW_Tracking.actual_val=0.0;
pidHW_Tracking.target_val=0.00;//紅外循跡PID 的目標值為0
pidHW_Tracking.err=0.0;
pidHW_Tracking.err_last=0.0;
pidHW_Tracking.err_sum=0.0;
pidHW_Tracking.Kp=-1.50;
pidHW_Tracking.Ki=0;
pidHW_Tracking.Kd=0.80;
然后就可以跑一下試試了。
可以改進的地方
- 紅外對管影響差速轉向,也影響基礎直行的速度 ,會有更好控制效果,所以可以加入每種紅外對管狀態下對基礎速度的影響。
- 紅外對管的數量越多,效果會越好。
第15章我們會講解手機遙控的功能
審核編輯 黃宇
-
單片機
+關注
關注
6023文章
44378瀏覽量
628569 -
STM32
+關注
關注
2258文章
10828瀏覽量
352535 -
智能小車
+關注
關注
86文章
548瀏覽量
81479 -
算法分析
+關注
關注
0文章
9瀏覽量
7521 -
循跡
+關注
關注
0文章
14瀏覽量
12949
發布評論請先 登錄
相關推薦
評論