?? 從本文開始,在之后的一段時間里,我會通過本系列文章,詳細介紹如何從零開始用51單片機去實作智能小車的控制,本文作為本系列的第一篇文章,主要介紹如何讓小車動起來,
本系列文章鏈接:
-----------------------------------------------------------------------------
?? 詳細介紹如何從零開始制作51單片機控制的智能小車(一)———讓小車動起來
?? 詳細介紹如何從零開始制作51單片機控制的智能小車(二)———超聲波模塊、漫反射光電管、4路紅外傳感器的介紹和使用
?? 詳細介紹如何從零開始制作51單片機控制的智能小車(三)———用超聲波模塊和漫反射光電傳感器實作小車的自動避障
?? 詳細介紹如何從零開始制作51單片機控制的智能小車(四)———通過藍牙模塊實作資料傳輸以及通過手機藍牙實作對小車運動狀態的控制
?? 詳細介紹如何從零開始制作51單片機控制的智能小車(五)———對本系列第四篇文章介紹的手機藍牙遙控加減速例外的錯誤的介紹及糾正
-----------------------------------------------------------------------------
一、硬體的選擇
?? 1、底盤和電機
???底盤的形狀呢,大家可以按照自己的需要自主選取,至于電機關注一下作業電壓,轉速,電機型別就差不多,對于新手,可以嘗試以下樣式(4WD智能小車底盤,附帶4個直流減速電機,電機接線需要自己焊接),也就是本文例子采用的底盤和電機,組裝簡單,使用方便,特別適合新手,

?? 2、電機驅動模塊
??? L298N電機驅動模塊,絕對是新手的首選,但是此系列也包含了很多型別,本文采用的是L298N雙H橋驅動 紅色版 ,除了性能外,我選擇它是因為它具備了5v的輸出介面,可以用來給單片機供電,大家可以用兩個這種驅動,也可以用一個,另一個用個便宜點的,
??? 由于家中有一個如下式樣的L298N驅動,所以為了不讓資源浪費,另一個,我就用如下型號的L298N驅動,
?? 3、單片機最小系統
??? 關于最小系統,大家只要選用自己熟悉的就行了,沒什么特別的講究,我采用的樣式如下(芯片采用的是STC89C52)
?? 4、電源
??? 這一部分大家根據需要自己選擇即可,選的時候注意一下電壓和容量就行,我選用的是常見的 9v 650mAh(容量不是很大,但是這種電池比較常見,充一次電跑2~3小時應該不是問題),我選的是USB充電款,充電很方便,電池盒我選用的是如下的這種拆卸方便的款式,缺點就是不附帶電源開關,
?? 5、杜邦線
??? 這是必備的輔件,就不多說了,公對公,母對母,公對母(這一種一般用的多一些)都要買一些,家里常備物品,
二、硬體的連接
??? 本文涉及到的硬體連接為單片機、電源、 電機、 兩個電機驅動L298N之間的連接,在這里我介紹一種參考的連接方式,大家可以自己設計連接方案
??? 如上圖所示,四個電機的正負極分別接兩個L298N的綠色電機介面,至于到底哪個接正極,哪個接負極,根據你電機安裝的方式而定,建議先把電機的兩根線焊上,然后把底盤安裝起來,這樣電機的安裝方式就確定了,先隨便把兩個L298N的4個綠色電機介面跟電機相接,等到把其他信號線接好后,再判斷對錯并調節,調節方法如下:在程式中讓小車往前跑,觀察車輪的轉向,往前轉的車輪的線不用變,把往后轉的電機對應的L298N綠色介面的兩根線換一下就行了,
???如上圖所示,L298N的左邊數第一個藍色埠 是5V輸出,把其中一個L298N的該介面接到單片機的5v介面上,另一L298N該介面可以空著,左邊數第二個藍色埠是GND需要同時與單片機的GND與電源的負極相接,左邊數第三個藍色埠是L298N的電源輸入埠,與電源的正極相接,我采用的是9v的電源,
???剩下的就是L298N的信號線與單片機的連接了,介紹如上圖所示,在這里我采用的是雙驅的接法,也就是左邊兩個點擊用同一個信號控制,右邊兩個電機用同一個信號控制,單片機的I/O口自行選擇,與程式配合起來就行,我選用的是 ENA接P16 ENB 接P17 IN1接P34 IN2接P35 IN3接P36 IN4接P37 若改為4驅所需的I/O將擴大一倍,
???實物圖片如下:
三、程式的撰寫
?? 1、工程的建立
???編譯環境根據自己習慣和需要選擇,本文以KEIL C51為例,由于本次設計的小車控制并不復雜,所以我把工程中用到的所有頭檔案、函式的定義、sbit定義的位變數都放到了一個頭檔案中,取名為car.h(名字大家隨意取即可),C檔案呢我建議大家把各個部分別寫在不同的檔案中,比如我把與電機驅動有關的函式放到了motor_control.c(名字任意取)檔案中,控制方案和延時函式,中斷函式放到了主函式main.c(名字任意取)檔案中,后續隨著功能增加還會增設其他的C檔案,只要所有的C檔案均包含以上共同的頭檔案car.h,也就互相建立了聯系,
?? 2、根據L298N與單片機的接線,撰寫電機控制函式
???雖然說本文選用的車型四個電機可以獨立控制,但是為了簡單化,方便化,我們讓左邊的兩個電機采用共同的信號控制,右邊的兩個電機采用共同的信號控制,大家若需要可以自主改為4路獨立的信號控制,根據本文第二部分——硬體的連接部分的介紹,我們選用了單片機的P34 P35 I/O口作為左電機的方向控制信號,單片機的P36 P37 I/O口作為右電機的方向控制信號,單片機的P16 I/O口作為左電機的PWM輸出控制信號,單片機的P17 I/O口作為右電機的PWM輸出控制信號,
???以上6個I/O口的位定義如下(為方便各檔案呼叫,我們把它放到統一的h檔案car.h中)
sbit Left_moto_pwm=P1^6 ;
sbit Right_moto_pwm=P1^7;
sbit p34=P3^4;
sbit p35=P3^5;
sbit p36=P3^6;
sbit p37=P3^7;
??? 左右電機的狀態控制函式如下:
void Left_moto_go() //左電機正轉
{p34=0;p35=1;}
void Left_moto_back() //左電機反轉
{p34=1;p35=0;}
void Left_moto_stp() //左電機停轉
{p34=1;p35=1;}
void Right_moto_go() //右電機正轉
{p36=0;p37=1;}
void Right_moto_back() //右電機反轉
{p36=1;p37=0;}
void Right_moto_stp() //右電機停轉
{p36=1;p37=1;}
??4、PWM調速輸出函式的撰寫:
??? 對于新手來說,如果理解不了以下兩個函式,那只需要知道如何使用就行了,即通過修改push_val_left的值就可以調節左電機的轉速,通過修改push_val _right的值就可以調節右電機的轉速,push_val_left和push_val_right的值均位于1到10之間,值越大電機轉速越快
bit Left_moto_stop =1;
bit Right_moto_stop =1;
unsigned char pwm_val_left =0;
unsigned char push_val_left =0;
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;
void pwm_out_left_moto(void) //左電機調速
{
if(Left_moto_stop)
{
if(pwm_val_left<=push_val_left)
Left_moto_pwm=1;
else
Left_moto_pwm=0;
if(pwm_val_left>=10)
pwm_val_left=0;
}
else
Left_moto_pwm=0;
}
void pwm_out_right_moto(void) //右電機調速
{
if(Right_moto_stop)
{
if(pwm_val_right<=push_val_right)
Right_moto_pwm=1;
else
Right_moto_pwm=0;
if(pwm_val_right>=10)
pwm_val_right=0;
}
else
Right_moto_pwm=0;
}
??5、小車姿態控制函式的撰寫:
???理解了 左右電機的狀態控制函式,撰寫小車姿態控制函式就很簡單了,大家稍微想一下小車左右輪的狀態,小車會怎么運行,就理解了,比如 左右電機都正轉,那小車運行狀態肯定是前行,每個函式的前兩行是左右電機轉速的設定,
unsigned char Left_Speed_Ratio; //左電機轉速的設定值
unsigned char Right_Speed_Ratio; //右電機轉速的設定值
void run(void) //小車前行
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_go();
Right_moto_go();
}
void back(void) //小車后退
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_back();
Right_moto_back();
}
void left(void) //小車左轉
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_go();
Left_moto_stp();
}
void right(void) //小車右轉
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_stp();
Left_moto_go();
}
void stop(void) //小車停止
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_stp();
Right_moto_stp();
}
void rotate(void) //小車原地轉圈
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_back();
Right_moto_go();
}
??6、與定時器中斷有關函式的撰寫
void Timer0Init() //定時器初始化函式
{
TMOD|=0X01;//選擇為定時器0模式,作業方式1,僅用TR0打開啟動,
TH0=0XFC; //給定時器賦初值,定時1ms
TL0=0X18;
ET0=1;//打開定時器0中斷允許
EA=1;//打開總中斷
TR0=1;//打開定時器
}
void timer0()interrupt 1 using 2 //定時器中斷函式,此處配置為1ms產生一次中斷,對PWM的輸出進行控制
{
TH0=0XFC; //給定時器賦初值,定時1ms
TL0=0X18;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
??7、延時函式的撰寫
???關于延時函式,大家只要會用就行,可以用單片機小精靈等輔助軟體生成,以下為延時1秒的函式
void delay1s(void)
{
unsigned char a,b,c;
for(c=167;c>0;c--)
for(b=171;b>0;b--)
for(a=16;a>0;a--);
_nop_();
}
??8、主函式內容的撰寫
???關于主函式的內容,首先要呼叫定時器中斷初始化函式,其次要設定左右電機的速度引數,本文的主要內容是讓車動起來,所以主函式內要呼叫本部分第5步中撰寫的小車姿態控制函式,對其進行檢驗,為了便于觀察兩個狀態之間加了5秒的延時,代碼如下:
void main()
{
Timer0Init();
Left_Speed_Ratio=5; //設定左電機車速為最大車速的50%
Right_Speed_Ratio=5; 設定右電機車速為最大車速的50%
while(1)
{
run();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
back();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
left();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
right();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
stop();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
rotate();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
}
}
四、本文例子完整的C檔案和H檔案代碼
?? 1、motor_control.c檔案完整代碼如下:
#include <car.h>
unsigned char pwm_val_left =0;
unsigned char push_val_left =0;
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;
unsigned char Left_Speed_Ratio;
unsigned char Right_Speed_Ratio;
bit Left_moto_stop =1;
bit Right_moto_stop =1;
void Left_moto_go() //左電機正轉
{p34=0;p35=1;}
void Left_moto_back() //左電機反轉
{p34=1;p35=0;}
void Left_moto_stp() //左電機停轉
{p34=1;p35=1;}
void Right_moto_go() //右電機正轉
{p36=0;p37=1;}
void Right_moto_back() //右電機反轉
{p36=1;p37=0;}
void Right_moto_stp() //右電機停轉
{p36=1;p37=1;}
void pwm_out_left_moto(void) //左電機PWM
{
if(Left_moto_stop)
{
if(pwm_val_left<=push_val_left)
Left_moto_pwm=1;
else
Left_moto_pwm=0;
if(pwm_val_left>=10)
pwm_val_left=0;
}
else
Left_moto_pwm=0;
}
void pwm_out_right_moto(void) //右電機PWM
{
if(Right_moto_stop)
{
if(pwm_val_right<=push_val_right)
Right_moto_pwm=1;
else
Right_moto_pwm=0;
if(pwm_val_right>=10)
pwm_val_right=0;
}
else
Right_moto_pwm=0;
}
void run(void) //小車前行
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_go();
Right_moto_go();
}
void back(void) //小車后退
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_back();
Right_moto_back();
}
void left(void) //小車左轉
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_go();
Left_moto_stp();
}
void right(void) //小車右轉
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Right_moto_stp();
Left_moto_go();
}
void stop(void) //小車停止
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_stp();
Right_moto_stp();
}
void rotate(void) //小車原地轉圈
{
push_val_left =Left_Speed_Ratio;
push_val_right =Right_Speed_Ratio;
Left_moto_back();
Right_moto_go();
}
?? 2、main.c檔案完整代碼如下:
#include <car.h>
extern unsigned char Left_Speed_Ratio;
extern unsigned char Right_Speed_Ratio;
unsigned int time=0;
extern unsigned char pwm_val_left;
extern unsigned char pwm_val_right;
void delay1s(void)
{
unsigned char a,b,c;
for(c=167;c>0;c--)
for(b=171;b>0;b--)
for(a=16;a>0;a--);
_nop_();
}
void Timer0Init()
{
TMOD|=0X01;//選擇為定時器0模式,作業方式1,僅用TR0打開啟動,
TH0=0XFC; //給定時器賦初值,定時1ms
TL0=0X18;
ET0=1;//打開定時器0中斷允許
EA=1;//打開總中斷
TR0=1;//打開定時器
}
void timer0()interrupt 1 using 2
{
TH0=0XFC; //給定時器賦初值,定時1ms
TL0=0X18;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
void main()
{
Timer0Init();
Left_Speed_Ratio=5; //設定左電機車速為最大車速的50%
Right_Speed_Ratio=5; 設定右電機車速為最大車速的50%
while(1)
{
run();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
back();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
left();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
right();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
stop();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
rotate();
delay1s(); delay1s(); delay1s(); delay1s(); delay1s();
}
}
?? 3、car.h檔案完整代碼如下:
#ifndef __car_H
#define __car_H
#include <reg52.h>
#include <intrins.h>
sbit Left_moto_pwm=P1^6 ;
sbit Right_moto_pwm=P1^7;
sbit p34=P3^4;
sbit p35=P3^5;
sbit p36=P3^6;
sbit p37=P3^7;
void Left_moto_go() ;
void Left_moto_back() ;
void Left_moto_stp() ;
void Right_moto_go();
void Right_moto_back();
void Right_moto_stp();
void delay(unsigned int k) ;
void delay1s(void) ;
void pwm_out_left_moto(void) ;
void pwm_out_right_moto(void);
void run(void);
void back(void);
void left(void);
void right(void);
void stop(void);
void rotate(void);
五、本文例子實物視頻演示
???????實物視頻演示視頻鏈接
????點擊上面的鏈接即可查看本文介紹內容的視頻演示,內容依次為(即主函式中程式的內容):前進5秒 、后退5秒、左轉5秒、右轉5秒、停轉5秒、轉圈5秒,附視頻網址:
????https://www.bilibili.com/video/bv1N5411x7zL
?? 本文到這里就結束了,本文完整的工程檔案我會放在附件里,需要者自取,我放的時候都是免費的,但是過段時間它會自己漲…需要的在評論區留言我可以直接發給你,歡迎大家繼續閱讀本系列的后續文章“詳細介紹如何從零開始制作51單片機控制的智能小車(二)———超聲波模塊、漫反射光電管、4路紅外傳感器的介紹和使用”
?? 歡迎大家積極交流,本文未經允許謝絕轉載
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/223647.html
標籤:AI
