利用LM293D晶片來控制電機:
為什麼單片機不能控制直流電動機?
能不能驅動是看功bai率的,而不是隻看電壓,還i要看電流呢,單片機的IO頂多輸20mA左右,遠遠驅動了一般的電機,是以要加驅動電路。
可以用三極管或者專用驅動IC。
這裡用的就是四倍高電流的H橋驅動程式
L293D簡介
L293 是提供雙向驅動電流高達 1 A,電壓
是從 4.5 V 至 36 V 的;L293D 提供雙向驅動電流高達 600 毫安,電壓是從 4.5 V 至 36 V 的。兩個裝置是專為驅動等感性
負載繼電器,電磁閥,直流雙極步進和馬達,也可以給其他高電流/高電壓提供電源負載。
相容所有的 TTL 輸入。每個輸出都是推拉式驅動電路,與達林頓三極管和僞達林源。啟用 1,2 EN 驅動器和 3,4 EN 驅動
器。當使能輸入為高電平時,相關聯的驅動器被啟用和他們的
輸出處于活動狀态,并在其輸入端的同相。當使能輸入為低,這些驅動器被禁用
其輸出關閉,在高阻抗狀态。【PS:1,2EN 為 1 和 2 的使能端(高電平使能);3,4EN 同理】用适當的資料輸入端,每對
驅動程式的形式一個完整的 H 橋可逆驅動器适用于電磁閥或電機應用。
L293,外部輸出為高速鉗位二極管,應使用電感的瞬态抑制。VCC1 和 VCC2 分開,提供邏輯輸入,以盡量減少裝置功
耗。L293 和 L293D 的工作溫度是從 0°C 至 70°C
上面簡介有些麻煩,看圖
簡單來說,VCC2和Vcc1接電源即可,接地的接地,1,2EN是1A,2A,1Y,2Y的使能端,當1,2EN為高電平時,1A,2A,1Y,2Y工作,反之,1A,2A,1Y,2Y不工作,右半部分和左半部分一樣,小車制作隻用兩個電機就可以了,是以對于L293來說隻用左半部分即可。
上面說的是L293,其實這次用的是L293D來控制電機,兩個驅動其實大同小異,來看下L293D的圖:
還是需要連電源的和連地的電路都連好了,最主要的是input1和input2來控制電機M1,input3和input4來控制電機M2,ENA和ENB是使能端,ENA來控制input1和input2的正常工作,ENB來控制input3和input4的正常工作。通過控制占空比來控制速度。當input1和inut2一個為1,另一個為0時,電機運轉,至于正轉反轉可以通過調試來确定。
再來說說原理圖中的蜂鳴器部分:
蜂鳴器連接配接一個三級管接地,三級管的基極連通過一個電阻連接配接io口,當這個io口為低電平時,流過發射極的電流為0,電壓也為零,同時流過集電極的電流也為0,電壓也為0,是以相當于蜂鳴器下端接地,蜂鳴器發出叫聲
當io口為1時,集電極和發射極都有點壓,這是蜂鳴器上下端都有電壓,蜂鳴器不叫。
智能小車避障:
這個程式利用了超音波子產品來進行避障,如果監測到有障礙物就往右轉(沒有舵機是以隻能這樣),右轉其實就是令左輪轉動,右輪不動。
主要是超音波測距:
超音波的時序圖:
TR引腳是用來觸發信号,EC是來輸出回響信号,超音波與障礙物會反射回來,根據回響信号的高電平時間就可以算出與障礙物的距離,s=time*速度/2;一來一回是以除以2;如果沒有障礙物,也會有輸出回響信号為高電平,而且會很長一段時間為高電平;
#include<reg52.h>
sbit x1=P0^0;
sbit y1=P0^1;
sbit x2=P0^2;
sbit y2=P0^3;
sbit ena=P0^4;
sbit enb=P0^5;
sbit fm=P0^6;
sbit tr=P1^3;
sbit ec=P1^2;
sbit led=P2^0;
sbit s4=P3^2;
int flag;
void delayu(int xus)
{
int i,j;
for(i=0;i<xus;i++)
{
for(j=0;j<9;j++)
{
}
}
}
void delaym(int xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<112;j++)
{
}
}
}
void right()
{
x1=0;
y1=0;
x2=1;
y2=0;
}
void go()
{
x1=1;
y1=0;
x2=1;
y2=0;
}
void stop()
{
x1=x2=y1=y2=0;
}
void main()
{ double time;
double s;
tr=0;
ena=enb=1;
ec=0;
TMOD=0x01;
TH0=TL0=0;
EA=1;
ET0=1;
while(s4==1);
while(1)
{
tr=1;
delayu(10);
tr=0;
while(ec==0);
TR0=1;
while(ec==1);
TR0=0;
time=TH0*256+TL0;
TH0=TL0=0;
s=time*0.017;
if(s<50)
{ if(flag==0)
stop();
fm=0;
led=0;
delaym(10);
led=1;
right();
delaym(50);
fm=1;
}
else
{
go();
}
}
}
小車遇到障礙物有兩種情況,第一種是小車正直行遇到障礙物,這時需要stop()讓輪子停住,然後再右轉50ms,如果不停的話,可能會造成向右前方前行一段距離以至于撞上障礙物(并不知道右前方的情況)
//第二種情況,正右轉的時候遇到障礙物,不需要停下來再右轉,直接右轉即可,否則會浪費一定的時間先暫停再啟動,前者可以縮短避障時間。
遙控器控制智能小車: 首先,必須要知道的是紅外接收頭怎麼接收,紅外接收頭負責接收紅外信号,程式進行解碼。 https://blog.csdn.net/qq_43743762/article/details/89421704Nec協定進行解碼。
代碼:
#include<reg52.h>
sbit fm=P0^6;
sbit IR=P3^3;
sbit x1=P0^0;
sbit y1=P0^1;
sbit x2=P0^2;
sbit y2=P0^3;
sbit ena=P0^4;
sbit enb=P0^5;
sbit led=P2^0;
unsigned char code smg[]={0x03,0x9F,0x25,0x0D,0x99, //定義數位管顯示資料
0x49,0x41,0x1F,0x01,0x19};
unsigned char f[5];
unsigned char code dat[]={0x45,0x46,0x47,0x44,0x40,0x43,0x07,0x15,0x09};
void delay(int xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<112;j++)
{
}
}
}
void delayu(int xus)
{
int i=xus,j;
while(i--);
{
for(j=0;j<13;j++)
{
}
}
}
void stop()
{led=1;
x1=x2=y1=y2=0;
}
void ll()
{
led=0;
y1=y2=1;
x1=x2=0;
}
void go()
{
x1=x2=1;
y1=y2=0;
}
void left()
{
x1=1;
y1=0;
x2=0;
y2=1;
}
void right()
{
x1=0;
y1=1;
x2=1;
y2=0;
}
void car(int x)
{
switch(x)
{
case 1:
{
stop();
delay(30);
go();
break;
}
case 3:
{
stop();
delay(30);
left();
break;
}
case 4:
{
stop();
break;
}
case 5:
{
stop();
delay(30);
right();
break;
}
case 7:
{
stop();
delay(30);
ll();
break;
}
}
}
void oo() interrupt 2
{
int time=0,i,j;;
delay(5);
if(IR)
{
return ;
}
while(!IR)
{
delayu(1);
/* time++;
if(time>=70)
{
return ;
}*/
}
time=0;
while(IR)
{
delayu(1);
/*time++;
if(time>=70)
{
return ;
} */
}
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
time=0;
while(!IR);
while(IR)
{
delayu(1);
time++;
if(time>=30)
{
return ;
}
}
f[i]>>=1;
if(time>=8)
{ f[i]|=0x80;
}
time=0;
}
}
if(f[2]!=~f[3])
{
return ;
}
for(i=0;i<9;i++)
{
if(dat[i]==f[2])
{
car(i);
}
}
}
void main()
{
EX1=1;
EA=1;
IT1=1;
ena=enb=1;
while(1)
{
/*P2=smg[f[2]/16];
delay(1000);
P2=smg[f[2]%16];
delay(1000);*/
}
}
**這裡讓我一開始最疑惑的是為什麼要不斷的檢查時序每個階段的時間大小,過大就直接退出?後來,才知道,紅外發射的碼有不穩定型,一部分原因是有幹擾,另一部分是長按一個鍵會産生110ms為周期的連續碼,而且時序與一般的指令不一樣,如果不加一個條件來排除一種不穩定的時序,這兩種情況可能會造成程式很長時間卡在一個while(1)裡面,造成程式死掉,是以需要加保護措施,來保證程式的正常進行。**
關于連續碼看這個頁面http://www.taichi-maker.com/homepage/reference-index/arduino-library-index/irremote-library/nec-ir/
藍牙控制智能車:
首先,藍牙子產品,TX口接單片機的RX口,RX口接單片機的TX口;其餘接好即可,
藍牙子產品上電之後,一直閃爍,這時處于自動連接配接狀态,然後用手機的藍牙序列槽助手進行連接配接,(直接用藍牙連連不上,可能是藍牙子產品比較老),連接配接上之後,不再閃爍,這時可以将藍牙子產品接一跟usb轉ttl線插到電腦上,與電腦上的序列槽助手進行序列槽通信,這時就可以對藍牙子產品進行設定,比如更改波特率和名字之類的,具體看https://blog.csdn.net/zy_like_study/article/details/89076506
如何控制小車?
将藍牙子產品插在單片機上,用手機的藍牙序列槽助手對藍牙子產品發送資訊,資訊會從TX端輸出,這時RX接收資料會觸發中斷,在中斷函數裡可以判斷接收到的控制小車。注意:
一:藍牙子產品連接配接上之後可能會發送什麼字元,具體不清楚,是以在代碼裡面需要設定沒有一連接配接上發送的字元。
二:還有就是,單片機和藍牙子產品的波特率必須一緻,也可以使用波特率倍增位置一使波特率倍增。
三:藍牙插入後,序列槽被占用,沒辦法下載下傳程式,程式下載下傳也是用的序列槽。
四:SBUF隻能存一個位元組,字母也是一個位元組,是以,發字元串隻能一位一位發送,且字母是以字元的形式存儲在SBUF而不是以字元串的形式存儲。
比如傳入’A’,存儲的時候也是‘A’。串行發送就是發送的字元,接收到的也是字元,比如發送5,接收到的就是’5’。
代碼:`#include<reg52.h>
sbit x1=P0^0;
sbit y1=P0^1;
sbit x2=P0^2;
sbit y2=P0^3;
sbit ena=P0^4;
sbit enb=P0^5;
void delay(int xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<112;j++)
{
}
}
}
void stop()
{
x1=x2=y1=y2=0;
}
void back()
{
y1=y2=1;
x1=x2=0;
}
void go()
{
x1=x2=1;
y1=y2=0;
}
void left()
{
x1=1;
y1=0;
x2=0;
y2=1;
}
void right()
{
x1=0;
y1=1;
x2=1;
y2=0;
}
void ll() interrupt 4
{
RI=0;
switch(SBUF)
{
case ‘5’:
go();
break;
case ‘l’:
back();
break;
case ‘p’:
right();
break;
case ‘e’:
left();
break;
case ‘f’:
stop();
break;
}
}
void main()
{EA=1;
ES=1;
ET1=1;
TMOD=0X20;
TH1=TL1=0xfa; //産生4800的波特率
TR1=1;
SCON=0x50;
PCON=0x80; //倍增一下成9600
while(1);
}`
尋光程式:
LM393左右兩邊原理一樣,先看左邊,VCC與地之間有兩個電阻分壓,光敏電阻的阻值随着光線的變強阻值減少,分壓減少,可以通過調節W1來調整靈敏度,使的光敏電阻在沒有光線的時候分壓比上面大,這時LM393的OUT處輸出高電平,當一有光線的時候,上面的分壓就比下面光敏電阻的大,這時OUTA輸出低電平。左右兩邊原理一樣,來檢測通過輸出的電平來檢測有沒有光。
關于LM393晶片:
程式設計:
觀察檢測光的兩個電平,如果哪邊有光就往哪邊走,如果都有光就直着走,如果沒光就暫停;
代碼:
*事先調試:
**本程式主要是通過主機闆左右兩個光敏傳感器感應光照 ,當右邊光敏傳感器檢測到光照
而左邊沒有檢測到,小車則向右轉彎,當兩個光敏傳感器同時檢測到光照時,小車則
前進,當關照源移動時,當左邊光敏傳感器檢測到光照,右邊沒有檢測,則小車左轉
,當左右兩個傳感器同時檢測到光照,則小車前進,周而複始。
程式測試方法:打開您的智能手機的手電筒功能,首先確定在沒有開手電筒功能時候,
主機闆左側LED D1和右側LED D2 沒有亮,如果亮了就用一字起把對應的電位器細緻調
節下,直到LED熄滅,然後打開手機的手電筒功能,照一下左右兩個光敏傳感器看是否
會亮,如果不亮說明之前那一步調過頭,那麼你就要再細微調節下,直到亮為止,這樣***
系統測試完畢,就可以正常尋光了;祝你成功!
#include<reg52.h>
sbit x1=P0^0;
sbit y1=P0^1;
sbit x2=P0^2;
sbit y2=P0^3;
sbit ena=P0^4;
sbit enb=P0^5;
sbit lightl=P1^1;
sbit lightr=P1^0;
void delay(int xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<112;j++)
{
}
}
}
void go()
{
x1=x2=1;
y1=y2=0;
}
void stop()
{
x1=x2=y1=y2=0;
}
void left()
{
x1=y1=0;
x2=1;
y2=0;
}
void right()
{
x1=1;
y1=0;
x2=0;
y2=0;
}
void main()
{
ena=enb=1;
while(1)
{
if(lightl==0&&lightr==0)
{
go();
}
else if(lightl==0&&lightr==1)
{
left();
}
else if(lightl==1&&lightr==0)
{
right();
}
else
{
stop();
}
}
}
智能小車紅外避障:
**劃紅線的就是紅外避障也是利用LM393晶片來控制,v7是紅外發射管,v4是紅外接收管,紅外發射後遇到障礙物會發射回來紅外線,如果接收到紅外線,v4的電阻就會減少,相應的電壓也會減少,再根據設計好的電路圖,一旦有近距離障礙物i,INA+的電壓就會小于INA-的電壓,障礙物越近,反射回來的紅外線越強,V4的電阻越小,電壓越小。如果檢測到障礙物,就後退且左轉來避開。注意一點,對于黑色障礙物無法檢測,黑色會吸收紅外光,這一點可以結合超音波避障來消除。
代碼:
`#include<reg52.h>
sbit x1=P0^0;
sbit y1=P0^1;
sbit x2=P0^2;
sbit y2=P0^3;
sbit ena=P0^4;
sbit enb=P0^5;
sbit out=P3^7;
void go()
{
x1=x2=1;
y1=y2=0;
}
void stop()
{
x1=x2=0;
y1=y2=0;
}
void back()
{
x1=x2=0;
y1=y2=1;
}
void right()
{
x1=1;
y1=0;
x2=0;
y2=1;
}
void delay(int xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<112;j++)
{
}
}
}
void main()
{
ena=enb=1;
while(1)
{
if(out==1) //沒有障礙物
{
go();
}
else
{
stop(); // 防止電機反相電壓沖擊 導緻系統複位
delay(300);
back();
delay(300);
stop();
delay(50);
right();
delay(500);
stop();
delay(300);
}
}
}`**
循迹程式:
**循迹也是利用紅外二極管發出紅外線,紅外接收管進行接收,如果接收到說明在地面上,如果接收不到就是不在地面上或者下面是黑色物體。
電路圖:
**
左右兩邊原理一樣,V5發射紅外線,V2如果接收到反射電阻下降,進而導緻電平為低電平,D5發光,P35為低電平,如果是下面是黑色,就會吸收反射光,V2阻值不變,進而P3^5為高電平。
循迹子產品:
那一塊黑色的就是一組發送和接收。
判斷左右兩邊的電平進而控制電機,控制小車的運動一直在黑線上。
代碼:`#include<reg52.h>
sbit x1=P0^0;
sbit y1=P0^1;
sbit x2=P0^2;
sbit y2=P0^3;
sbit ena=P0^4;
sbit enb=P0^5;
sbit lc=P3^5;
sbit lr=P3^6;
void go()
{
x1=x2=1;
y1=y2=0;
}
void stop()
{
x1=x2=0;
y1=y2=0;
}
void back()
{
x1=x2=0;
y1=y2=1;
}
void right()
{
x1=0;
y1=1;
x2=1;
y2=0;
}
void delay(int xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<112;j++)
{
}
}
}
void left()
{
x1=1;
y1=0;
x2=0;
y2=1;
}
void main()
{
ena=enb=1;
while(1)
{
if(lc0&&lr0)
{
go();
delay(10);
stop();
delay(5);
}
else if(lc1&r0)
{
left();
delay(10);
stop();
delay(5);
}
else if(lc0&&lr1)
{
right();
delay(10);
stop();
delay(5);
}
}
}`
一直檢測有沒有檢測到黑線,如果有就說明走歪了再調整一下即可,調整角度還不能過大。整個運作速度也不能過快,是以go()完10ms之後stop()5ms來達到減速。
風扇驅動:
原理圖:
由圖可知,隻要OA和OB一正一負就可以讓風扇轉起來。
LG9110晶片:
根據真值表來驅動風扇即可。
代碼:
#include<reg52.h>
sbit f1=P1^4;
sbit f2=P1^5;
void delay(int xms)
{
int i,j;
for(i=0;i<xms;i++)
{
for(j=0;j<112;j++)
{
}
}
}
void main()
{
f1=0;
f2=1;
delay(1500);
f1=0;
f2=0;
delay(10);
f2=1;
f1=0;
while(1);
}