? ? ? ? 大家好偷拔!這是小編第二次做小項(xiàng)目~
? ? ? ? 小編目前專業(yè)是電氣自動(dòng)化的廓块,不搞點(diǎn)硬件方面的東西蚌堵,不學(xué)點(diǎn)控制技術(shù)买决,有點(diǎn)對(duì)不起自己所學(xué)的專業(yè)沛婴。
? ? ? ? 小編這次打算做arduino多功能智能小車~
? ? ? ? 首先,為啥選擇arduino電路板督赤?
? ? ? ? 這個(gè)是由于小編還沒學(xué)過單片機(jī)啊~還沒有弄過其他的嘁灯,比如stm32單片機(jī)。因?yàn)檫@些學(xué)習(xí)起來躲舌,對(duì)于初學(xué)者來說丑婿,比較困難,需要花時(shí)間没卸。而arduino入門確實(shí)簡單羹奉,特別適合初學(xué)者,而且arduino源碼開源的约计,特別的人性化诀拭。其實(shí),arduino也是單片機(jī)煤蚌,但是它是經(jīng)過二次開發(fā)的耕挨,有很多的庫函數(shù)。
1.所需材料
底盤2個(gè)? ? 電機(jī)4個(gè)? ? 輪胎4個(gè)? ? arduino uno板1個(gè)
電機(jī)驅(qū)動(dòng)板1個(gè)? ? 杜邦線若干? ? 電池盒1個(gè)? ? 5號(hào)電池4節(jié)
USB數(shù)據(jù)線1根? ? 藍(lán)牙模塊? ? USB 轉(zhuǎn)TTL數(shù)據(jù)線
? ? ? ? 如果這是讀者第一次做尉桩,沒有什么DIY經(jīng)驗(yàn)的話筒占,可以自己在網(wǎng)上買套裝元件,網(wǎng)上關(guān)于這些東西很多魄健,可以滿足我們的制作材料的要求赋铝。當(dāng)然插勤,對(duì)于有一定基礎(chǔ)的讀者沽瘦,會(huì)設(shè)計(jì)原理圖,完全可以用AltiumDesigner軟件农尖,繪制一個(gè)屬于自己的PCB板析恋,這樣對(duì)于自己有很大的提高。我在網(wǎng)上看的意大利進(jìn)口PCB板盛卡,感覺挺精致的助隧,奈何出于經(jīng)濟(jì)原因,就買了套件滑沧。
2.編程軟件
本人使用官方的免費(fèi)IDE編程環(huán)境并村,下載地址與安裝教程見官網(wǎng)
這個(gè)軟件的詳細(xì)教程參考地址arduino IDE教程
3.制作過程
首先,小編先介紹一下小車的結(jié)構(gòu):
1.電機(jī)驅(qū)動(dòng)模塊:這是控制小車電機(jī)轉(zhuǎn)動(dòng)的模塊滓技,在模塊的電源部分哩牍,有VMS、VCC(5v)令漂、GND3個(gè)接口膝昆。電源正極接VMS丸边,電源負(fù)極接GND,這樣就給電機(jī)驅(qū)動(dòng)模塊上電了荚孵。MotorA和MotorB的四個(gè)接口妹窖,分別接電機(jī)的線。ENA和ENB分別是使能端收叶,接Arduino的PWM接口骄呼,用于電機(jī)的調(diào)速。IN1判没、IN2谒麦、IN3和IN4分別接Arduino的數(shù)字接口。
2.Arduino單片機(jī):可以說是智能小車的“大腦”哆致,也就是說這是小車的核心绕德。在后面,我們要將我們編好的程序?qū)氲絘rduino中摊阀,就可以控制小車了~
? ? ? ? 在我制作小車的時(shí)候耻蛇,我在網(wǎng)上了解到arduino單片機(jī)供電方式,這里就不在闡述了 胞此,具體見網(wǎng)址:
3.藍(lán)牙模塊:這是通信模塊臣咖,控制著手機(jī)與arduino單片機(jī)之間的通信。藍(lán)牙模塊上共有6個(gè)引腳漱牵,我們?cè)谶@里要用到4個(gè)引腳夺蛇,分別是RX、TX酣胀、VCC和GND刁赦,藍(lán)牙模塊的RX接arduino的TX,藍(lán)牙模塊的TX接arduino的RX闻镶,VCC接VCC甚脉,GND接GND。當(dāng)然铆农,藍(lán)牙模塊在使用之前牺氨,需要進(jìn)行調(diào)試,我們需要下載串口調(diào)試助手墩剖,進(jìn)行以下操作:(藍(lán)牙模塊的初始密碼為1234)
給藍(lán)牙模塊命名猴凹,將串口波特率改成115200
然后根據(jù)指令,測(cè)試一下藍(lán)牙的通信狀況岭皂。
4.電源模塊:其實(shí)就是四節(jié)電池郊霎,主要是給arduino單片機(jī)和電機(jī)驅(qū)動(dòng)模塊供電。
詳見圖片:
4.代碼展示
首先蒲障,說一下編程思路:
setup()函數(shù)里主要配置一些小車的參數(shù)歹篓。
loop()函數(shù)里瘫证,先接收手機(jī)通過藍(lán)牙發(fā)出的指令,并通過傳參調(diào)用小車電機(jī)驅(qū)動(dòng)函數(shù)庄撮,實(shí)現(xiàn)藍(lán)牙控制功能背捌。
#define STOP 0x03
#define FORWARD 0x02
#define BACKWARD 0x08
#define TURN_LEFT 0x06
#define TURN_RIGHT 0x07
int PWMLeft = 3;//左輪速度
int PWMRight = 5;//右輪速度
int MotorLeft1 = 7;//左前輪方向
int MotorLeft2 = 8;//左后輪方向
int MotorRight1 = 12;//右前輪方向
int MotorRight2 = 13;//右后輪方向
void setup()
{
? Serial.begin(115200);
? pinMode(PWMLeft, OUTPUT);
? pinMode(PWMRight, OUTPUT);
? pinMode(MotorLeft1, OUTPUT);
? pinMode(MotorLeft2, OUTPUT);
? pinMode(MotorRight1, OUTPUT);
? pinMode(MotorRight2, OUTPUT);
? delay(10);
}
void loop(){
if(Serial.available()>0)
? {
? ? char cmd=Serial.read();
? ? Serial.print(cmd);
? ? motorRun(cmd);
? ? delay(10);
? }
}
void motorRun(int cmd)
{
? ? switch(cmd){
? ? ? case FORWARD:
? ? ? Serial.println("FORWARD");
? ? ? analogWrite(PWMLeft, 180);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 200);? //PWM調(diào)速
? ? ? digitalWrite(MotorLeft1,HIGH);
? ? ? digitalWrite(MotorLeft2,LOW);
? ? ? digitalWrite(MotorRight1,LOW);
? ? ? digitalWrite(MotorRight2,HIGH);
? ? ? break;
? ? ? case BACKWARD:
? ? ? Serial.println("BACKWARD");
? ? ? analogWrite(PWMLeft, 180);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 200);? //PWM調(diào)速
? ? ? digitalWrite(MotorLeft1,LOW);
? ? ? digitalWrite(MotorLeft2,HIGH);
? ? ? digitalWrite(MotorRight1,HIGH);
? ? ? digitalWrite(MotorRight2,LOW);
? ? ? break;
? ? ? case TURN_LEFT:
? ? ? Serial.println("TURN_LEFT");
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 240);? //PWM調(diào)速
? ? ? digitalWrite(MotorRight1,LOW);
? ? ? digitalWrite(MotorRight2,HIGH);
? ? ? delay(500);
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? ? ? break;
? ? ? case TURN_RIGHT:
? ? ? Serial.println("TURN_RIGHT");
? ? ? analogWrite(PWMLeft, 200);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? ? ? digitalWrite(MotorLeft1,HIGH);
? ? ? digitalWrite(MotorLeft2,LOW);
? ? ? delay(500);
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? ? ? break;
? ? ? case STOP:
? ? ? Serial.println("STOP");
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? }
}
5.功能演示
功能:通過藍(lán)牙控制(手機(jī)APP)小車的前進(jìn)、后退洞斯、左轉(zhuǎn)毡庆、右轉(zhuǎn)等相關(guān)指令的執(zhí)行。
這里烙如,有點(diǎn)不好意思么抗,我也不知道為啥格式工廠不好弄分辨率更大的視頻轉(zhuǎn)GIF功能,總是出錯(cuò)~
在這里亚铁,小編再推薦藍(lán)牙控制手機(jī)APP軟件蝇刀,在應(yīng)用市場(chǎng)里搜索藍(lán)牙智能小車
藍(lán)牙手機(jī)APP控制界面:
軟件說明:
6.代碼分析
電機(jī)驅(qū)動(dòng)函數(shù):
void motorRun(int cmd)
{
? ? switch(cmd){
? ? ? case FORWARD:
? ? ? Serial.println("FORWARD");
? ? ? analogWrite(PWMLeft, 180);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 200);? //PWM調(diào)速
? ? ? digitalWrite(MotorLeft1,HIGH);
? ? ? digitalWrite(MotorLeft2,LOW);
? ? ? digitalWrite(MotorRight1,LOW);
? ? ? digitalWrite(MotorRight2,HIGH);
? ? ? break;
? ? ? case BACKWARD:
? ? ? Serial.println("BACKWARD");
? ? ? analogWrite(PWMLeft, 180);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 200);? //PWM調(diào)速
? ? ? digitalWrite(MotorLeft1,LOW);
? ? ? digitalWrite(MotorLeft2,HIGH);
? ? ? digitalWrite(MotorRight1,HIGH);
? ? ? digitalWrite(MotorRight2,LOW);
? ? ? break;
? ? ? case TURN_LEFT:
? ? ? Serial.println("TURN_LEFT");
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 240);? //PWM調(diào)速
? ? ? digitalWrite(MotorRight1,LOW);
? ? ? digitalWrite(MotorRight2,HIGH);
? ? ? delay(500);
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? ? ? break;
? ? ? case TURN_RIGHT:
? ? ? Serial.println("TURN_RIGHT");
? ? ? analogWrite(PWMLeft, 200);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? ? ? digitalWrite(MotorLeft1,HIGH);
? ? ? digitalWrite(MotorLeft2,LOW);
? ? ? delay(500);
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? ? ? break;
? ? ? case STOP:
? ? ? Serial.println("STOP");
? ? ? analogWrite(PWMLeft, 0);? //PWM調(diào)速
? ? ? analogWrite(PWMRight, 0);? //PWM調(diào)速
? }
}
這里,小車前進(jìn)徘溢、后退吞琐、左轉(zhuǎn)、右轉(zhuǎn)和停止分別用FORWARD然爆、BACKWARD掠械、TURN_LEFT包各、TURN_RIGHT和STOP來定義吴超。用switch條件選擇語句來表示小車的五種狀態(tài)庄呈,這里小編以小車前進(jìn)為例,加以分析剖张。
Serial.println("FORWARD");這一句是將FORWARD打印在串口監(jiān)視器上切诀。我們?cè)谇捌跍y(cè)試手機(jī)與藍(lán)牙的通信時(shí),如果測(cè)試結(jié)果正確地出現(xiàn)在串口監(jiān)視器上修械,表明通信成功趾牧。
如何調(diào)節(jié)電機(jī)轉(zhuǎn)速检盼?
analogWrite(PWMLeft, 180);
analogWrite(PWMRight, 200);
這兩句時(shí)PWM調(diào)速語句肯污。何為PWM(脈沖寬度調(diào)制)?簡單來說吨枉,就是改變脈沖方波的占空比蹦渣,比如一個(gè)5V的電源,怎么獲得3v的電壓貌亭,傳統(tǒng)的觀點(diǎn)是我們串聯(lián)1個(gè)可調(diào)電阻進(jìn)行分壓柬唯。但,我們現(xiàn)在可以在單位時(shí)間內(nèi)圃庭,3/5的時(shí)間里輸出高電平锄奢,2/5的時(shí)間里輸出低電平失晴,這樣就可以得到3v的電壓了~這里PWM數(shù)值取0~255之間。
有讀者會(huì)問了拘央,怎么左輪和右輪的PWM的數(shù)值不一樣涂屁。這是因?yàn)椋總€(gè)電機(jī)的性能有些差異灰伟,雖然都是一起買來的拆又。大家可以根據(jù)實(shí)際情況調(diào)節(jié)小車的PWM的數(shù)值。
? ? ? 如何調(diào)節(jié)電機(jī)的轉(zhuǎn)向栏账?
? ? ? digitalWrite(MotorLeft1,HIGH);
? ? ? digitalWrite(MotorLeft2,LOW);
? ? ? digitalWrite(MotorRight1,LOW);
? ? ? digitalWrite(MotorRight2,HIGH);
這里帖族,我還是要強(qiáng)調(diào)一下電機(jī)的接線,電機(jī)驅(qū)動(dòng)模塊有4個(gè)電機(jī)接口挡爵,每一個(gè)接口接其中一個(gè)電機(jī)的上面接口和另外一個(gè)電機(jī)的下面一個(gè)接口竖般。這樣只要通過1個(gè)電機(jī)驅(qū)動(dòng)模塊就可以控制四個(gè)電機(jī)了~如果你覺得這樣不好,那你可以用兩個(gè)電機(jī)驅(qū)動(dòng)模塊茶鹃,來控制四個(gè)電機(jī)捻激。
藍(lán)牙部分:
? if(Serial.available()>0)
? {
? ? char cmd=Serial.read();
? ? Serial.print(cmd);
? ? motorRun(cmd);
? ? delay(10);
? }
Serial.available() 的意思是:返回串口緩沖區(qū)中當(dāng)前剩余的字符個(gè)數(shù)。一般用這個(gè)函數(shù)來判斷串口的緩沖區(qū)有無數(shù)據(jù)前计,當(dāng)Serial.available()>0時(shí)胞谭,說明串口接收到了數(shù)據(jù),可以讀饶需尽丈屹;
Serial.read()指從串口的緩沖區(qū)取出并讀取一個(gè)Byte的數(shù)據(jù),比如有設(shè)備通過串口向Arduino發(fā)送數(shù)據(jù)了伶棒,我們就可以用Serial.read()來讀取發(fā)送的數(shù)據(jù)旺垒。
定義與初始化部分:
#define STOP 0x03
#define FORWARD 0x02
#define BACKWARD 0x08
#define TURN_LEFT 0x06
#define TURN_RIGHT 0x07
這個(gè)宏定義是為了藍(lán)牙通信的,具體見手機(jī)APP說明肤无,通過藍(lán)牙發(fā)送1個(gè)字符先蒋,arduino就可以接收到相應(yīng)的數(shù)據(jù)。
int PWMLeft = 3;//左輪速度
int PWMRight = 5;//右輪速度
int MotorLeft1 = 7;//左前輪方向
int MotorLeft2 = 8;//左后輪方向
int MotorRight1 = 12;//右前輪方向
int MotorRight2 = 13;//右后輪方向
這個(gè)是定義小車PWM調(diào)速端接口和電機(jī)接口的宛渐。arduino單片機(jī)上有"~"字樣的接口是PWM信號(hào)接口竞漾,其他的是數(shù)字接口。
void setup()
{
? Serial.begin(115200);
? pinMode(PWMLeft, OUTPUT);
? pinMode(PWMRight, OUTPUT);
? pinMode(MotorLeft1, OUTPUT);
? pinMode(MotorLeft2, OUTPUT);
? pinMode(MotorRight1, OUTPUT);
? pinMode(MotorRight2, OUTPUT);
? delay(10);
}
藍(lán)牙的串口波特率從初始值9600調(diào)整為115200窥翩,然后定義小車PWM調(diào)速端接口和電機(jī)接口為輸出端业岁。? delay(10);起緩沖作用。
7.制作小車過程中遇到的問題
在小車制作前寇蚊,自己沒有DIY經(jīng)驗(yàn)笔时,只知道一些電子元件方面的基礎(chǔ)知識(shí),在編程方面仗岸,自己在大學(xué)學(xué)過C語言的課程允耿,僅此而已借笙。以下小編將從組裝,接線较锡,編程3個(gè)方面來闡述制作過程中的問題:
在小車組裝方面提澎,我們要有安裝的次序,首先應(yīng)該先將電機(jī)的接線接線接好念链,然后再將電機(jī)固定在底盤上盼忌,這樣電機(jī)上的線容易接。還有掂墓,我要提醒的是如果你想做其他功能的小車谦纱,例如避障小車,應(yīng)該先將舵機(jī)固定在底盤上一層上君编,然后再安裝跨嘉,這樣容易擰螺絲。arduino單片機(jī)和電機(jī)驅(qū)動(dòng)模塊都放在上面一層吃嘿。自己當(dāng)時(shí)沒有經(jīng)驗(yàn)祠乃,拆拆裝裝,挺耗時(shí)間的兑燥。
接線時(shí)亮瓷,盡量排布整齊一些,這樣既讓接線變得清晰明了降瞳,又使得小車美觀大方嘱支。而小編自己在排線方面也沒有做到很好。
編程方面挣饥,其實(shí)arduino開源代碼很多除师,可以借鑒性學(xué)習(xí)。當(dāng)時(shí)扔枫,我的問題出在藍(lán)牙接收數(shù)據(jù)方面汛聚,原因是藍(lán)牙串口調(diào)試時(shí),沒有設(shè)置好波特率短荐,總是接收不到數(shù)據(jù)倚舀。當(dāng)然,后來找了實(shí)驗(yàn)室的學(xué)長搓侄,才弄好的瞄桨。