CW32循跡小車.zip_免費高速下載|百度網(wǎng)盤-分享無限制
一、概述
CW32循跡、遙控小車具有循跡和遙控兩種功能,小車的硬件模塊由CW32F030C8T6小藍板、智能小車控制底板、BT04-E 藍牙模塊、OLED屏幕、TB6612和紅外循跡模塊組成,電源采用可充電鋰電池供電,建議不要使用 1.5V 干電池供電。
圖1 CW32小車
二、硬件部分
2.1主控板
小車主控板由小藍板和控制底板組成,小藍板通過排母與控制底板相連,控制底板上還預(yù)留了按鍵等功能。主控板的原理圖分別如下:
圖2-1 小車控制底板原理圖1
圖2-2 小車控制底板原理圖2
2.2藍牙模塊
藍牙模塊采用 BT04-E 模塊,為單獨小板,通過排母插在小車主控板上:
圖2-3 BT04-E 模塊
通過模塊背面絲印可以確定與主控板的連接線序,主控板上為藍牙預(yù)留的位置如下:
圖2-4 主控板藍牙位置
查找CW32F030的數(shù)據(jù)手冊可知 PA2 和 PA3 為其串口2,調(diào)用串口2對其發(fā)送信息即可通過串口藍牙助手接收對應(yīng)的消息。
2.3循跡模塊
循跡模塊通過排線與主控底板相連,參考原理圖里的紅外對管接口所對應(yīng)的引腳。
圖2-5 循跡模塊
循跡模塊的工作原理:傳感器的紅外發(fā)射二極管不斷發(fā)射紅外線,當發(fā)射出的紅外線沒有被反射回來或被反射回來但強度不夠大時,紅外接收管一直處于關(guān)斷狀態(tài),此時模塊的 CH 端為高電平,通過比較器后輸出為低電平,指示 LED 被點亮; 當被檢測物體出現(xiàn)在檢測范圍內(nèi)時,紅外線被反射回來且強度足夠大,紅外接收管飽和,此時模塊的輸出端為低電平,經(jīng)過比較器后輸出為高電平,LED 燈熄滅。由于黑色會吸收紅外線,所以總結(jié)為:檢測到黑線--燈亮、輸出低電平;未檢測到黑線--燈滅、輸出高電平。
圖2-6 循跡模塊原理圖
2.4TB6612芯片
TB6612是一款常用的雙路直流電機驅(qū)動器芯片,常用于控制小型電動機或機器人的運動。該芯片具有高效、可靠和靈活的特點,適用于各種電氣控制應(yīng)用。
圖2-7 TB6612 和控制底板
TB6612芯片具有以下主要特性:
雙路驅(qū)動:TB6612可以控制兩個直流電機的轉(zhuǎn)動,支持正轉(zhuǎn)、反轉(zhuǎn)和停止功能。因此,它可以同時控制兩個電機的運動,實現(xiàn)平穩(wěn)的雙輪驅(qū)動或其他雙電機配置。
高電流輸出:該芯片能夠提供高達1.2A的持續(xù)輸出電流,并且具有1.5A的瞬時峰值電流能力。這使得TB6612在控制較大功率電機時表現(xiàn)出色,適用于一些對功率要求較高的應(yīng)用場景。
低功耗:TB6612在待機模式下的功耗非常低,可以有效延長電池壽命,適用于依賴電池供電的設(shè)備和機器人。
內(nèi)置保護功能:芯片內(nèi)部集成了過溫保護、過電流保護和欠壓鎖定等保護功能,可以保護電機和芯片本身免受損壞或過載的風險。
靈活的控制接口:TB6612支持多種控制接口,包括PWM控制、頻率鎖定和直接控制模式等,可以根據(jù)具體需求選擇合適的控制方式。
TB6612 可以控制兩路電機,分別由 AIN1、AIN2、PWMA、BIN1、BIN2、PWMB組成,下面是AIN和BIN不同輸入時控制電機的轉(zhuǎn)動方向真值表。PWMA 和 PWMB 輸入不同占空比的 PWM 波可以控制電機的轉(zhuǎn)速快慢。
IN1 | IN2 | 電機狀態(tài) |
0 | 0 | 制動 |
0 | 1 | 正轉(zhuǎn) |
1 | 0 | 反轉(zhuǎn) |
1 | 1 | 制動 |
三、軟件部分
3.1循跡模塊檢測判斷
循跡模塊檢測,根據(jù) 4 個燈的亮滅情況共有 16 種狀態(tài),每種狀態(tài)對應(yīng)小車在黑線上的一種情況,根據(jù)不同的情況有不同的控制策略。
void IR_Check(void) { IR_Sensor[0] = GPIO_ReadPin(CW_GPIOB,GPIO_PIN_12); //存放循跡模塊輸入值 IR_Sensor[1] = GPIO_ReadPin(CW_GPIOB,GPIO_PIN_13); IR_Sensor[2] = GPIO_ReadPin(CW_GPIOB,GPIO_PIN_14); IR_Sensor[3] = GPIO_ReadPin(CW_GPIOB,GPIO_PIN_15); /*********************************只有一個燈亮****************************/ if(IR_Sensor[0] == 1 && IR_Sensor[1] == 1 && IR_Sensor[2] == 0 && IR_Sensor[3] == 1) //略微偏離道路 偏左,需要右轉(zhuǎn) { Road_Error = 10; Flag_BaseSpeed = 10; } else if(IR_Sensor[0] == 1 && IR_Sensor[1] == 0 && IR_Sensor[2] == 1 && IR_Sensor[3] == 1) //略微偏離道路 偏右,需要左轉(zhuǎn) { Road_Error = -10; Flag_BaseSpeed = 10; } else if(IR_Sensor[0] == 1 && IR_Sensor[1] == 1 && IR_Sensor[2] == 1 && IR_Sensor[3] == 0) //較大偏離道路 偏左,需要右轉(zhuǎn) { Road_Error = 20; Flag_BaseSpeed = 20; } else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 1 && IR_Sensor[2] == 1 && IR_Sensor[3] == 1) //較大偏離道路 偏右,需要左轉(zhuǎn) { Road_Error = -20; Flag_BaseSpeed =20; } /*********************************兩個燈亮****************************/ else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 0 && IR_Sensor[2] == 1 && IR_Sensor[3] == 1) //需要左轉(zhuǎn) { Road_Error = -40; Flag_BaseSpeed = 100; } else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 1 && IR_Sensor[2] == 0 && IR_Sensor[3] == 1) //直行 { Road_Error = 0; Flag_BaseSpeed = 0; } else if(IR_Sensor[0] == 1 && IR_Sensor[1] == 1 && IR_Sensor[2] == 0 && IR_Sensor[3] == 0) //需要右轉(zhuǎn) { Road_Error = 40; Flag_BaseSpeed = 100; } else if(IR_Sensor[0] == 1 && IR_Sensor[1] == 0 && IR_Sensor[2] == 1 && IR_Sensor[3] == 0) //直行 { Road_Error = 0; Flag_BaseSpeed = 0; } else if(IR_Sensor[0] == 1 && IR_Sensor[1] == 0 && IR_Sensor[2] == 0 && IR_Sensor[3] == 1) //未偏離道路 { Road_Error = 0; Flag_BaseSpeed = 0; } else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 1 && IR_Sensor[2] == 1 && IR_Sensor[3] == 0) //保持之前的操作 { Road_Error = 0; Flag_BaseSpeed = 0; } /*********************************三個燈亮****************************/ else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 0 && IR_Sensor[2] == 0 && IR_Sensor[3] == 1) //需要左轉(zhuǎn) { Road_Error = -40; Flag_BaseSpeed = 100; } else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 0 && IR_Sensor[2] == 1 && IR_Sensor[3] == 0) //需要右轉(zhuǎn) { Road_Error = 20; Flag_BaseSpeed = 0; } else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 1 && IR_Sensor[2] == 0 && IR_Sensor[3] == 0) //需要左轉(zhuǎn) { Road_Error = -20; Flag_BaseSpeed = 0; } else if(IR_Sensor[0] == 1 && IR_Sensor[1] == 0 && IR_Sensor[2] == 0 && IR_Sensor[3] == 0) //需要右轉(zhuǎn) { Road_Error = 40; Flag_BaseSpeed = 100; } /*********************************零、四個燈亮****************************/ else if(IR_Sensor[0] == 1 && IR_Sensor[1] == 1 && IR_Sensor[2] == 1 && IR_Sensor[3] == 1) //沒有檢測到線,保持之前的操作 ; else if(IR_Sensor[0] == 0 && IR_Sensor[1] == 0 && IR_Sensor[2] == 0 && IR_Sensor[3] == 0) //全是線,說明在十字路口,保持之前的操作 ; }
3.2PID計算控制
PID 計算控制根據(jù)紅外循跡模塊的亮滅情況,分別控制小車的基速和差速,從而控制小車運動的方向。
/** * @brief PID基速控制 * @param Encoder:Flag_BaseSpeed ,Target:0 * @return 基速 PID 計算值 */ int PID_BaseSpeed(int Encoder,int Target) { float V_Base_Kp = 30,V_Base_Kd = 100; //Kp、Kd static float Bias,PID,Last_Bias; //本次偏差、PID計算值、上次偏差 Bias = Encoder - Target; //計算本次偏差 PID = MAXOUTPUT - V_Base_Kp * Bias + V_Base_Kd * (Bias - Last_Bias); //PID計算 Last_Bias = Bias; //存儲偏差 return PID; } /** * @brief PID差速控制 * @param Encoder:Road_Error ,Target:0 * @return 差速 PID 計算值 */ int PID_DiffSpeed(int Encoder,int Target) { float V_Diff_Kp = 80,V_Diff_Ki = 0.08,V_Diff_Kd = 100;//Kp、Ki、Kd static float Bias_D,PID_D,Integral_Bias,Last_Bias_D; //本次偏差、PID計算值、積分累計值、上次偏差 Bias_D = Encoder - Target; //計算本次偏差 Integral_Bias += Bias_D; //積累偏差 PID_D = V_Diff_Kp * Bias_D + V_Diff_Ki * Integral_Bias + V_Diff_Kd * (Bias_D - Last_Bias_D);//PID計算 Last_Bias_D = Bias_D; //存儲偏差 return PID_D; } /** * @brief 小車控制 * @param 無 * @return 無 */ void Car_Control(void) { OUTPUT_Left = PID_BaseSpeed(Flag_BaseSpeed,0) + PID_DiffSpeed(Road_Error,0); //左輪占空比計算 OUTPUT_Right = PID_BaseSpeed(Flag_BaseSpeed,0) - PID_DiffSpeed(Road_Error,0); //右輪占空比計算 if(OUTPUT_Left > MAXOUTPUT)OUTPUT_Left = MAXOUTPUT; //限制大小 else if(OUTPUT_Left < 0)OUTPUT_Left = 0; if(OUTPUT_Right > MAXOUTPUT)OUTPUT_Right = MAXOUTPUT; else if(OUTPUT_Right < 0)OUTPUT_Right = 0; GTIM_SetCompare3(CW_GTIM1,OUTPUT_Left); //左輪 GTIM_SetCompare4(CW_GTIM1,OUTPUT_Right); //右輪 }
3.3遙控部分
遙控部分其實就是,通過串口藍牙接收信息并向?qū)?yīng)的方向運動,下面是藍牙串口的中斷服務(wù)程序:
// 串口2中斷處理函數(shù) void UART2_IRQHandler(void) { unsigned char TxRxBuffer; if (USART_GetITStatus(CW_UART2, USART_IT_RC) != RESET) { USART_ClearITPendingBit(CW_UART2, USART_IT_RC); // 清除中斷標志位 TxRxBuffer = USART_ReceiveData_8bit(CW_UART2); // 將接收到的數(shù)據(jù)放入TxRxBuffer USART2_RX_BUF[rx2Index] = TxRxBuffer; // 將接收到的數(shù)據(jù)放入緩沖區(qū) if (rx2Index < USART2_REC_LEN - 1) // 做數(shù)據(jù)長度的限制,留一個字節(jié)用于結(jié)束字符或者溢出檢測 { // 接收到的字符包含 n 或者 r 結(jié)束接收 if (USART2_RX_BUF[rx2Index - 1] == 'n' || USART2_RX_BUF[rx2Index - 1] == 'r') { USART2_RX_BUF[rx2Index] = ''; // 在最后一個字節(jié)加上空字符,表示字符串結(jié)束 } else rx2Index++; } if(USART2_RX_BUF[0] == 't')Flag_Mode = 1 - Flag_Mode; //發(fā)送字符 ‘t’來切換模式 if(Flag_Mode == 0) { if(USART2_RX_BUF[0] == '1')Flag_Start = 1; else Flag_Start = 0; } else if(Flag_Mode == 1) { if(USART2_RX_BUF[0] == 'w')Flag_Direction = 1; else if(USART2_RX_BUF[0] == 's')Flag_Direction = 2; else if(USART2_RX_BUF[0] == 'a')Flag_Direction = 3; else if(USART2_RX_BUF[0] == 'd')Flag_Direction = 4; else Flag_Direction = 9; } rx2Index = 0; // 清除數(shù)據(jù)標志 } }
四、調(diào)試
4.1調(diào)試場地
調(diào)試場地對小車的要求包括直角、交叉點、彎道等,具體如下圖所示:
圖4-1 智能小車巡線賽道
4.2調(diào)試提示
小車運動主要由基速環(huán)和差速環(huán)的 PID 控制,可以先將差速環(huán)的 PID 參數(shù)整定下來,再調(diào)基速環(huán)的參數(shù)。
循跡模塊受到環(huán)境光的影響較大,最好在光線均勻和充足的環(huán)境下調(diào)試。
電池電壓同樣會影響循跡模塊的性能,建議不要使用 1.5V 干電池調(diào)試,而是使用鋰電池。在電池接近沒電時循跡模塊不能正常工作。
在彎道處如果小車不能及時轉(zhuǎn)向,可以適當降低速度和增大差速環(huán)的 Kp 值。
小車在交叉點處的循跡受到速度影響較大,較低的速度可能會使小車無法按照規(guī)定路線循跡,可以提高車速或者更換具有編碼器的電機做輪式里程計來對該點做預(yù)判。
審核編輯 黃宇
-
遙控小車
關(guān)注
2文章
30瀏覽量
18412 -
藍牙模塊
+關(guān)注
關(guān)注
30文章
573瀏覽量
55719 -
循跡小車
+關(guān)注
關(guān)注
42文章
65瀏覽量
68598 -
CW32
+關(guān)注
關(guān)注
1文章
203瀏覽量
613
發(fā)布評論請先 登錄
相關(guān)推薦
評論