LabVIEW Arduino無線藍牙遙控智能車(項目篇—2)
1
項目概述
智能小車是以輪子作為移動機構(gòu),并且能夠?qū)崿F(xiàn)自主行駛的機器人,又被稱為輪式機器人。由于具有智能化的特點,可以應(yīng)用于不適合人類工作的環(huán)境中,例如災(zāi)難救援、戶外探險等。智能小車有別于遙控小車,因為后者需要操作人員來控制其轉(zhuǎn)向、啟停和前進后退,以及控制其速度,常見的模型小車,都屬于這類遙控車。智能小車,則可以通過計算機編程來實現(xiàn)其對行駛方向、啟停以及速度的控制,無須人工干預(yù),也可以通過修改智能小車的程序來改變它的行駛方式。
智能小車的典型特點有:
1、擁有至少一個微控制器,通過微控制器來實現(xiàn)對行駛方向、啟停和速度的控制。
2、擁有多個各種功能的傳感器,以獲取外界環(huán)境的情況,以供控制器做出準確的決策。
2
項目架構(gòu)
本節(jié)將要介紹一種基于Arduino與LabVIEW的無線遙控智能小車,可以實現(xiàn)自主(巡線和避障)與遙控兩種功能,并且可以在兩種功能之間進行切換。智能小車采用Arduino作為控制核心,上位機軟件采用LabVIEW,兩者通過APC220無線數(shù)傳模塊實現(xiàn)無線通信。無線遙控智能小車總體框圖如下圖所示:
智能小車的車體采用兩個驅(qū)動輪、一個萬向輪的三輪式小車模型,驅(qū)動電機采用直流減速電機,電機驅(qū)動模塊采用VNH2SP30模塊,循跡傳感器采用OPENJUMPER紅外巡線傳感器OJ-CG307,避障傳感器采用OPENJUMPER紅外避障傳感器OJ-CG303。
智能小車的巡線場地為白底黑線,線寬約10mm,場地大小約為200cm×300cm。
3
傳感器和控制器
3.1、傳感器
本節(jié)介紹的無線遙控智能小車,可以實現(xiàn)自主與遙控兩種功能,并且可以在兩種功能之間進行切換。當小車處于遙控狀態(tài)時,操作者通過操作LabVIEW上位機軟件,利用APC220串口無線模塊向小車上的Arduino控制器發(fā)送遙控指令,從而使小車做出指定的行為動作。而當小車處于自主狀態(tài)時候,小車上的Arduino控制器通過四個紅外巡線傳感器和一個紅外避障傳感器獲取小車相對于黑線的位置和前面是否有障礙物的信號,并根據(jù)程序中設(shè)置的邏輯來控制直流減速電機,以實現(xiàn)巡線和避障的功能。
紅外巡線傳感器模塊是利用紅外對管檢測模塊本身發(fā)出的紅外線的反射光(深色反射弱,淺色反射強),來為循跡機器人提供白線或者黑線的跟蹤,既可以檢測白底中的黑線,也可以檢測黑底中的白線,若檢測到白線則輸出高電平,若檢測到黑線則輸出低電平。
紅外避障傳感器****紅外線并根據(jù)反射回來的紅外光判斷前方是否存在障礙物,無障礙物時輸出高電平,有障礙時輸出低電平,在信號輸出同時有指示燈指示狀態(tài),無障礙物時LED為綠,有障礙物時為紅。同時內(nèi)置38kHz的信號發(fā)生器,抗干擾能力強。通過調(diào)節(jié)模塊上的2KΩ電位器,可以調(diào)節(jié)傳感器的探測距離。
紅外巡線傳感器模塊如下圖所示:
紅外避障傳感器模塊如下圖所示:
3.2、控制器
一般情況下,直流電機需要很大的驅(qū)動電流,而像Arduino之類的控制器輸出的邏輯電平無法直接驅(qū)動直流電機,特別是大功率的減速電機,所以就需要通過驅(qū)動器件給直流電機提供工作電流。
Arduino愛好者常用的直流電機驅(qū)動模塊主要有L298模塊和VNH2SP30模塊。
L298電機驅(qū)動模塊價格較為便宜,而且單個L298芯片可以同時驅(qū)動兩路直流電機,所以在Arduino愛好者制作機器人小車時使用較多,但是其轉(zhuǎn)化效率較低,發(fā)熱量較大,不適合驅(qū)動大電流直流電機,當驅(qū)動大電流電機時容易發(fā)生芯片"假死"等故障。
VNH2SP30模塊具有驅(qū)動電流大、轉(zhuǎn)換效率高等優(yōu)點但是單個VNH2SP30芯片只能驅(qū)動一路直流電機,如果驅(qū)動兩路直流電機則需要兩個VNH2SP30芯片。
為了使得遙控智能小車具有良好的動力系統(tǒng),具有一定的載重能力,此處選用直流減速電機作為整個遙控智能小車的動力來源,并選用顆粒輪胎,以提高抓地能力。
4
硬件環(huán)境
將兩個直流減速電機的兩端分別接至VNH2SP30電機驅(qū)動模塊上的OUT1A、OUT1B和OUT2A、OUT2B,無正負極和電機轉(zhuǎn)向之分。若電機轉(zhuǎn)向相反,則在調(diào)試過程中將電機的連接線對調(diào)連接。將VNH2SP30電機驅(qū)動模塊的+5V (IN)、GND分別接至Arduino Uno控制板上的+5V、GND,為電機驅(qū)動模塊提供工作電壓。
將VNH2SP30電機驅(qū)動模塊的1INA、1INB、1PWM分別接至Arduino Uno控制板上的數(shù)字端口D7、D6、D5,為電機1提供轉(zhuǎn)向和調(diào)速控制信號;將VNH2SP30電機驅(qū)動模塊的2INA、2INB、2PWM分別接至Arduino Uno控制板上的數(shù)字端口D4、D2、D3,為電機2提供轉(zhuǎn)向和調(diào)速控制信號。需要注意的是,1PWM和2PWM需要接在具有模擬輸出(PWM)功能的數(shù)字端口。
Arduino控制器與驅(qū)動及電機部分的硬件連接,如下圖所示:
將一個APC220模塊與Arduino Uno控制板相連接,連接方式如下:
APC220 TXD→Arduino Uno控制板RXD,APC220 RXD→Arduino Uno控制板TXD,APC220 VCC→Arduino Uno控制板5V,APC220 GND→Arduino Uno控制板GND。
將另一塊APC220模塊通過FT232RL轉(zhuǎn)接板相連接,連接方式如下:
APC220 TXD→FT232RL轉(zhuǎn)接板RXD,APC220 RXD→FT232RL轉(zhuǎn)接板TXD,APC220 VCC→FT232RL轉(zhuǎn)接板5V,APC220 GND→FT232RL轉(zhuǎn)接板GND。
將四個紅外巡線傳感器依次連接至Arduino Uno控制板的數(shù)字端口D8、D9、D10、D11,并在將紅外巡線傳感器安裝至智能小車底盤時,對應(yīng)于左2、左1、右1和右2。將紅外避障傳感器連接至Arduino Uno控制板的數(shù)字端口D12,并將其安裝在小車車頭的前端。
5
Arduino功能設(shè)計
4個紅外巡線傳感器在智能小車底盤上的安裝示意圖如下圖所示:
初始狀態(tài)為黑線位于左1和右1傳感器之間,表明小車處于黑線中間部分;當左1傳感器檢測到黑線時,表明小車相對于黑線略微偏向右側(cè),需要小幅度左轉(zhuǎn)以修正偏差;當左2傳感器檢測到黑線時,表明小車相對于黑線偏向右側(cè)較多,需要大幅度左轉(zhuǎn)以修正偏差;當右1傳感器檢測到黑線時,表明小車相對于黑線略微偏向左側(cè),需要小幅度右轉(zhuǎn)以修正偏差;當右2傳感器檢測到黑線時,表明小車相對于黑線偏向左側(cè)較多,需要大幅度右轉(zhuǎn)以修正偏差。
遙控部分的調(diào)速將速度分為5檔,分別為低速、中低速、中速、中高速和高速,通過VNH2SP30電機驅(qū)動模塊的PWM輸入信號實現(xiàn)在五檔之間切換與調(diào)速。
Arduino Uno控制器程序代碼如下所示:
#define forward_command 0x00 //前進命令#define back_command 0x10 //后退命令#define left_command 0x20 //左轉(zhuǎn)命令#define right_command 0x30 //右轉(zhuǎn)命令#define stop_command 0x40 //停止命令 #define speed_1 0x50 //低速命令#define speed_2 0x60 //中低速命令#define speed_3 0x70 //中速命令#define speed_4 0x80 //中高速命令#define speed_5 0x90 //高速命令 byte comdata[3]={0}; //定義數(shù)組數(shù)據(jù),用于存放串口命令數(shù)據(jù)int flag = 0; //遙控/自動標志位,默認為遙控模式 int INA1 = 7;int INB1 = 6;int PWM1 = 5; //定義電機1的轉(zhuǎn)向和速度的控制引腳int INA2 = 4;int INB2 = 2;int PWM2 = 3; //定義電機2的轉(zhuǎn)向和速度的控制引腳 int Trace_sensor_X1=8;int Trace_sensor_X2=9;int Trace_sensor_Y1=10;int Trace_sensor_Y2=11; //定義四個紅外循跡傳感器的引腳int Avoidance_sensor=12; //定義紅外避障傳感器的引腳 void receive_data(void); //接收串口命令數(shù)據(jù)void test_do_data(void); //測試串口命令數(shù)據(jù)是否正確,并執(zhí)行命令 void forward(void); //前進子函數(shù)void back(void); //后退子函數(shù)void turn_Left(void); //左轉(zhuǎn)子函數(shù)void turn_Right(void); //右轉(zhuǎn)子函數(shù)void stop_car(void); //停止子函數(shù) void Automatic_mode(void); //自動模式子函數(shù) void setup(){ Serial.begin(9600); //初始化串口波特率為9600 pinMode(INA1, OUTPUT); pinMode(INB1, OUTPUT); pinMode(PWM1, OUTPUT); //設(shè)置電機1的控制引腳為輸出狀態(tài) pinMode(INA2, OUTPUT); pinMode(INB2, OUTPUT); pinMode(PWM2, OUTPUT); //設(shè)置電機2的控制引腳為輸出狀態(tài) pinMode(Trace_sensor_X1, INPUT); pinMode(Trace_sensor_X2, INPUT); pinMode(Trace_sensor_Y1, INPUT); pinMode(Trace_sensor_Y2, INPUT); //設(shè)置紅外循跡傳感器的控制引腳為輸入狀態(tài) pinMode(Avoidance_sensor,INPUT); //設(shè)置紅外避障傳感器的控制引腳為輸入狀態(tài) analogWrite(PWM1,150); //left motor analogWrite(PWM2,150); //ringt motor //將電機速度設(shè)置為中速檔位} void loop(){ if (Serial.available() > 0) //不斷檢測串口是否有數(shù)據(jù) { receive_data(); //從串口緩沖區(qū)接收串口命令數(shù)據(jù) test_do_data(); //測試串口命令數(shù)據(jù)是否正確并執(zhí)行命令 } if(flag==1) //判斷是否為自動模式狀態(tài) { Automatic_mode(); //執(zhí)行自動模式 analogWrite(PWM1,150); //left motor analogWrite(PWM2,150); //ringt motor //將電機速度切換至中速檔位 }} void receive_data(void) //從串口緩沖區(qū)接收串口命令數(shù)據(jù){ int i ; for(i=0;i<3;i++) //命令長度為3個字節(jié),每次讀取3個字節(jié) { comdata[i] =Serial.read(); //讀取一個字節(jié)的數(shù)據(jù) //延時一會,讓串口緩存準備好下一個字節(jié),不延時可能會導致數(shù)據(jù)丟失, delay(2); }} void test_do_data(void) //測試串口命令數(shù)據(jù)是否正確并執(zhí)行命令{ if(comdata[0] == 0x55) //0x55為命令幀頭,判斷幀頭是否正確 { if(comdata[1] == 0xAA) //0xAA為遙控模式命令 { flag=0; //切換至遙控模式 switch (comdata[2]) //匹配遙控模式中的具體命令 { case forward_command: //前進命令 forward(); break; case back_command: //后退命令 back(); break ; case left_command: //左轉(zhuǎn)命令 turn_Left(); break ; case right_command: //右轉(zhuǎn)命令 turn_Right(); break ; case stop_command: //停止命令 stop_car(); break ; case speed_1: //低速命令 analogWrite(PWM1,50); analogWrite(PWM2,50); break; case speed_2: //右轉(zhuǎn)命令 analogWrite(PWM1,100); analogWrite(PWM2,100); break ; case speed_3: //右轉(zhuǎn)命令 analogWrite(PWM1,150); analogWrite(PWM2,150); break ; case speed_4: //右轉(zhuǎn)命令 analogWrite(PWM1,200); analogWrite(PWM2,200); break ; case speed_5: //右轉(zhuǎn)命令 analogWrite(PWM1,250); analogWrite(PWM2,250); break ; } } if(comdata[1] == 0xFF) //0xFF為自主模式命令 { flag=1; //切換至自主模式 comdata[2] = 0; //清空命令數(shù)據(jù) } }} void Automatic_mode(void) //自主模式,循跡和避障{ int State_value=0; if(digitalRead(Avoidance_sensor)==0) //避障功能,有障礙物則后退左轉(zhuǎn) { back(); delay(1000); turn_Left(); delay(500); } //讀取紅外循跡傳感器組的狀態(tài) State_value=digitalRead(Trace_sensor_X2)*8+digitalRead(Trace_sensor_X1)*4+digitalRead(Trace_sensor_Y1)*2+digitalRead(Trace_sensor_Y2); switch (State_value) //匹配狀態(tài),并調(diào)整位置 { case 8: //大幅度偏左,大角度右轉(zhuǎn) turn_Right(); delay(200); break; case 4: //小幅度偏左,小角度右轉(zhuǎn) turn_Right(); delay(100); break ; case 2: //小幅度偏右,小角度左轉(zhuǎn) turn_Left(); delay(100); break ; case 1: //大幅度偏右,大角度左轉(zhuǎn) turn_Left(); delay(200); break ; default: //其他狀態(tài),前進 forward(); break; } } void forward(void) //前進{ digitalWrite(INA1, LOW); digitalWrite(INB1, HIGH); digitalWrite(INA2, LOW); digitalWrite(INB2, HIGH); }void back(void) //后退{ digitalWrite(INA1, HIGH); digitalWrite(INB1, LOW); digitalWrite(INA2, HIGH); digitalWrite(INB2, LOW); }void turn_Left(void) //左轉(zhuǎn){ digitalWrite(INA1, LOW); digitalWrite(INB1, HIGH); digitalWrite(INA2, HIGH); digitalWrite(INB2, LOW); }void turn_Right(void) //右轉(zhuǎn){ digitalWrite(INA1, HIGH); digitalWrite(INB1, LOW); digitalWrite(INA2, LOW); digitalWrite(INB2, HIGH); }void stop_car(void) //停止{ digitalWrite(INA1, LOW); digitalWrite(INB1, LOW); digitalWrite(INA2, LOW); digitalWrite(INB2, LOW); }
6
LabVIEW功能設(shè)計
LabVIEW上位機部分需要完成以下功能:
1、當從遙控狀態(tài)切換至自主狀態(tài)時,向下位機Arduino控制器發(fā)送自主狀態(tài)命令,Arduino控制器通過讀取紅外巡線傳感器和紅外避障傳感器,以實現(xiàn)巡線和避障的功能。
2、當從自主狀態(tài)切換至遙控狀態(tài)時,向下位機Arduino控制器發(fā)送遙控狀態(tài)命令,Arduino控制器通過讀取LabVIEW軟件發(fā)來的操作命令,并實現(xiàn)指定的動作和行為,包括前進、后退、左轉(zhuǎn)、右轉(zhuǎn)、停止和調(diào)速。
6.1、前面板設(shè)計
LabVIEW前面板分為遙控模式和模式切換兩個部分,遙控模式部分用于控制小車的運行狀態(tài),包括前進、后退、左轉(zhuǎn)、右轉(zhuǎn)、停止和調(diào)速;模式選擇部分用于切換遙控模式和自主模式。
無線遙控智能小車的LabVIEW上位機前面板,如下圖所示:
6.2、程序框圖設(shè)計
LabVIEW上位機主程序的結(jié)構(gòu)為順序結(jié)構(gòu)+While循環(huán)+事件結(jié)構(gòu)。首先,通過設(shè)置的串口號來初始化串口通信;然后,程序進入While循環(huán)和事件結(jié)構(gòu),不斷地檢測是否有事件得到響應(yīng)并執(zhí)行;事件結(jié)構(gòu)有“模式選項"、“前進”、“后退”、“左轉(zhuǎn)"、“右轉(zhuǎn)"、“停止"和“"調(diào)速"。最后,關(guān)閉串口通信。在程序框圖中,我們需要對串口進行配置,并將根據(jù)不同的按鍵按下通過串口發(fā)出不同的命令,下位機Arduino Uno收到串口收據(jù),解析出其中的命令代碼后執(zhí)行相應(yīng)的命令。
為了更好地實現(xiàn)通信,制定如下的通信協(xié)議:幀頭+命令碼+操作碼。0x55為幀頭,0xAA為遙控命令,0xFF為自主命令,遙控命令的操作碼:0x00為前進,0x10為后退,0x20為左轉(zhuǎn),0x30為右轉(zhuǎn),0x40為停止,0x50為速度檔1,0x60為速度檔2,0x70為速度檔3,0x80為速度檔4,0x90為速度檔5。
在“模式選項”事件中,通過讀取當前選擇的模式,向Arduino控制器分別發(fā)送0x55AA和Ox55FF,分別表示切換至遙控模式和自主模式?!澳J竭x項”值改變事件程序框圖如下圖所示:
在“前進"事件中,通過串口向Arduino控制器發(fā)送0x55AA00,Arduino控制器將兩個直流減速電機均設(shè)置為前進方向?!扒斑M"值改變事件程序框圖如下圖所示:
在“后退"事件中,通過串口向Arduino控制器發(fā)送0x55AA10,Arduino控制器將兩個直流減速電機均設(shè)置為后退方向。“后退"值改變事件程序框圖如下圖所示:
在“左轉(zhuǎn)"事件中,通過串口向Arduino控制器發(fā)送0x55AA20,Arduino控制器將右側(cè)電機設(shè)置為前進方向、左側(cè)電機設(shè)置為后退方向,從而實現(xiàn)左轉(zhuǎn)?!白筠D(zhuǎn)"值改變事件程序框圖如下圖所示:
在“右轉(zhuǎn)”事件中,通過串口向Arduino控制器發(fā)送0x55AA30,Arduino控制器將右側(cè)電機設(shè)置為后退方向、左側(cè)電機設(shè)置為前進方向,從而實現(xiàn)右轉(zhuǎn)?!坝肄D(zhuǎn)"值改變事件程序框圖如下圖所示:
均在“停止"事件中,通過串口向Arduino控制器發(fā)送0x55AA40,Arduino控制器將左、右兩個電機均設(shè)置為停止狀態(tài),從而實現(xiàn)小車的停止?!巴V?quot;值改變事件程序框圖如下圖所示:
在“速度檔位"值改變事件中,通過讀取當前選擇的速度檔位,向Arduino控制器分別發(fā)送0x55AA50、0x55AA60、0x55AA70、0x55AA80、0x55AA90,分別表示低速、中低速、中速、中高速和高速。“速度檔位"值改變事件的程序框圖如下圖所示:
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。