專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> Arduino >> 瀏覽文章

arduino驅(qū)動(dòng)舵機(jī)步進(jìn)電機(jī)與超聲波程序

作者:huqin   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年04月26日   【字體:
         外國人都很喜歡給產(chǎn)品起很厲害的名字,比如藍(lán)牙,不過就是個(gè)近距離數(shù)據(jù)傳輸技術(shù),比如wifi,一樣的,其實(shí)是無線網(wǎng)絡(luò)通信技術(shù)的一種,但是看起來名字酷帥狂拽的那種。
       這次給瓦力配的大腦是 ardiuno ,是不是聽起來很高貴冷的樣子,其實(shí)就是一塊avr單片機(jī)而已.....

arduino是意大利人發(fā)明的,把底層的代碼全部都封裝好了,所以程序?qū)懫饋砭透罘e木一樣,灰常簡(jiǎn)單明了,沒有電子基礎(chǔ)的人都能用的來。而且它是開源的,人家寫好的東西很多可以直接用,翻個(gè)墻還可以看到很多好東西,不過妥妥的注釋全是英文,這個(gè)時(shí)候就很明顯看到了國內(nèi)國外在個(gè)人做電設(shè)上的差距,先不說人家的模塊各種高大上,也不說人家的比賽各種多各種神奇,技術(shù)上咱們比不上人家。只是光是拿做模型模具的條件來說,國內(nèi)的發(fā)展水平差太多了,木有辦法,神馬機(jī)械條件的使用都是要錢滴。
       扯偏了,我給兒子duby一號(hào)初步要實(shí)現(xiàn)的功能是,語音識(shí)別,語音播放,超聲避障。暫時(shí)使用的模塊是LD3320語音識(shí)別,WTV020-SD語音播放,HC-SR04超聲測(cè)距,以及電機(jī)驅(qū)動(dòng),兩個(gè)直流減速電機(jī)和三個(gè)舵機(jī),用的是 arduino nano V3.0控制器,arduino家族里面最小的一款,因?yàn)槲覂鹤訉?shí)在太小了放不下太多東西......還好性能不錯(cuò)。
        想做個(gè)兒子純粹是心血來潮= = ,有人證。。〔皇菫榱伺萱ず脝。
        許久沒有碰過電設(shè)了,連中斷定時(shí)器IO口神馬的知識(shí)都忘得差不多了。而且還腦殘選的一款木有很熟悉的單片機(jī),要用的模塊也是一個(gè)都沒上手過,好吧,真的是一切從頭開始。依稀記得去年搭過一輛會(huì)唱歌的車子,用的也是arduino ,依稀記得當(dāng)時(shí)用的代碼好像也是這里抄抄那里抄抄......結(jié)果本來想實(shí)現(xiàn)能寫字功能的沒實(shí)現(xiàn)就送掉了 因?yàn)閼械谜{(diào)參數(shù)
        demo,這次造兒子要認(rèn)真一點(diǎn),不可以再那么隨便。
        接下來是技術(shù)貼,先上舵機(jī)程序,arduino有自己的庫,灰常簡(jiǎn)單好用,去官網(wǎng)上看了人家的技術(shù)手冊(cè),拿過來改改就可以用了。
#include<Servo.h>
char buffer[10];
Servo servo1;
void setup()
{
servo1.attach(5);
Serial.begin(9600);                                          //波特率不是高頻通信時(shí)9600足矣
Serial.flush();
servo1.write(90);                        // 舵機(jī)打到90度!get !是不是很方便!!!
Serial.println("starting.....");

}
void loop()
{
if(Serial.available()>0)
{
int index=0;
delay(100);
int numchar=Serial.available();
if(numchar>10)
{
numchar=10;
}
while(numchar--)
{
buffer[index++]=Serial.read();

}spliString(buffer);
}
}
void spliString(char*data)
{
Serial.print("Data entered:");
Serial.println(data);
char*parameter;
parameter=strtok(data,",");
while(parameter!=NULL)
{
setServo(parameter);
parameter=strtok(NULL,",");                   //long int strtol(const char *nptr,char **endptr,int base); 我一直覺得這種突然出現(xiàn)的
                                                                                      自帶函數(shù)都是來給我添堵的。
這個(gè)函數(shù)會(huì)將參數(shù)nptr字符串根據(jù)參數(shù)base來轉(zhuǎn)換
                                                                                    成長(zhǎng)整型數(shù)。  新函數(shù)!get!
 }
for(int x=0;x<9;x++)
{
buffer[x]='\0';

}
Serial.flush();
}
void setServo(char*data)
{
if((data[0]=='L')||(data[0]=='l'))
{
int firstval=strtol(data+1,NULL,10);
firstval=constrain(firstval,0,180);                              // 限制!
servo1.write(firstval);
Serial.print("Servo1 is set to:");
Serial.println(firstval);
}
if((data[0]=='R')||(data[0]=='r'))
{
int secondval=strtol(data+1,NULL,10);
secondval=constrain(secondval,0,255);
servo1.write(secondval);
Serial.print("servo1 is set to:");
Serial.println(secondval);
}
}
       這是控制單個(gè)舵機(jī)的程序,通過串口通信在PC端控制舵機(jī)。紅色線接6V電源,褐色線接地,橙色信號(hào)線接在D5口,因?yàn)橐敵龅氖荘WM信號(hào),在nano中只有3,5,6,9,10,11和13腳具有該功能,可以輸出模擬量,即固定脈沖。舵機(jī)轉(zhuǎn)動(dòng)范圍是0~180度,現(xiàn)在的程序是上電時(shí)直接打到90度的位置。
我用兩個(gè)18650供電,7806和7805穩(wěn)壓。
       改完這個(gè)程序瞬間覺得成就感滿滿有木有,接著就準(zhǔn)備弄電機(jī)。我買的是uln2003,三毛五一片,用不起八塊一片的mos。依稀記得我很久很久以前用uln2003成功驅(qū)動(dòng)過,所以我把自己給坑了。芯片搭好以后特么的就是木有輸出,查了各種之后,我笑了。它確實(shí)是能驅(qū)動(dòng)....可是這玩意只適合驅(qū)動(dòng)步進(jìn)電機(jī).....驅(qū)動(dòng)直流電機(jī)的話只能走一個(gè)方向和停止,不能反轉(zhuǎn).....要想反轉(zhuǎn)要用三極管加兩個(gè)臂,構(gòu)成類似H橋的東西,或者是用它兩個(gè)口的反相器構(gòu)建。早知這么麻煩,當(dāng)時(shí)一定會(huì)買一個(gè)別的現(xiàn)成的,比如L298n.... 這是亂憑經(jīng)驗(yàn)的教訓(xùn)。
      ULN2003的接法為,8腳接地,9腳懸空,其他是input和outpu,一共七路,負(fù)載一端接電源,另一端接輸出。好像原理是集電極開路導(dǎo)通神馬的= = ,原諒我當(dāng)年模電沒學(xué)好.......
      程序木有寫,因?yàn)榫鸵痪鋎igitalWrite(x,HIGH或者LOW)
       x是arduino的信號(hào)輸出腳,輸出的是數(shù)字量,控制通斷。HIGH對(duì)應(yīng)的是51里的高電平1,LOW對(duì)應(yīng)的是低電平0,注意是要大寫。補(bǔ)充一點(diǎn),所有的口都可以做數(shù)字口,都可以輸出HIGH 或者LOW。并不是標(biāo)著A就只能做模擬口,模擬口只是那個(gè)腳特有的功能。
      池老師突然覺得這篇日志好適合入門......
      (⊙_⊙),困了,明天再寫。
     昨天說到被電機(jī)驅(qū)動(dòng)坑了,今天去實(shí)驗(yàn)室轉(zhuǎn)悠的時(shí)候小城給了一個(gè)我心心念念的L298n,妥妥的正傳反轉(zhuǎn)180度360度隨意轉(zhuǎn)了好嗎。附程序:
int a1=3;
int b1=5;
int zuo1=0;
int zuo2=1;
int you1=2;
int you2=4;
void setup()
{
pinMode(0,OUTPUT);
pinMode(1,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
}
void loop()
{
qianjin(100,100,8000);
tingzhi();
houtui(100,100,8000);
tingzhi();
}
void qianjin(int zuo,int you,int chang)
{
  digitalWrite(zuo1,HIGH);
  digitalWrite(you1,HIGH);
  digitalWrite(zuo2,LOW);
  digitalWrite(you2,LOW);
  analogWrite(a1,zuo);
analogWrite(b1,you);
delay(chang);
}
void tingzhi()
{analogWrite(a1,0);
analogWrite(b1,0);
digitalWrite(zuo1,LOW);
  digitalWrite(you1,LOW);
  digitalWrite(zuo2,LOW);
  digitalWrite(you2,LOW);
  delay(1000);
}
void houtui(int zuo,int you,int chang)
{
 digitalWrite(zuo1,LOW);
  digitalWrite(you1,LOW);
  digitalWrite(zuo2,HIGH);
  digitalWrite(you2,HIGH);
  analogWrite(a1,zuo);
analogWrite(b1,you);
delay(chang);
}
void zuozhuan(int zuo)
{
analogWrite(b1,0);
 digitalWrite(you2,LOW);
  digitalWrite(you1,LOW);
   digitalWrite(zuo1,HIGH);
 digitalWrite(zuo2,LOW);
  analogWrite(a1,100);
  delay(zuo*50);
  tingzhi();
}
void youzhuan(int you)
{
analogWrite(a1,0);
 digitalWrite(zuo2,LOW);
  digitalWrite(zuo1,LOW);
   digitalWrite(you1,HIGH);
 digitalWrite(you2,LOW);
  analogWrite(b1,100);
  delay(you*50);
  tingzhi();
}
這個(gè)程序毫無修飾一看就知道是我寫的.....粗糙得一逼啊。
L298N可以驅(qū)動(dòng)兩路直流電機(jī)或者步進(jìn)電機(jī),程序中a1,b1對(duì)應(yīng)為模塊上的使能端A,B,使用pwm口輸出可以控制電機(jī)轉(zhuǎn)動(dòng)的速度(即車速) ,值0~255,255代表5V,0代表0V,加1時(shí)步長(zhǎng)為0.02V增量,此處取100可改。zuo1,zuo2和you1,you2是兩個(gè)電機(jī)各自的方向控制口,兩相不同時(shí)電機(jī)正反轉(zhuǎn),同為低電平時(shí)電機(jī)不轉(zhuǎn)。
小記:nano 板上 pwm輸出口只有 3,5,6,7,9,10,11,13 ,用analogWrite()函數(shù)輸出,板上所有口均可做數(shù)字口輸出。
電機(jī)舵機(jī)這兩部分木有難的地方,畢竟這玩意上電就可以動(dòng)彈。
 接著我就開搞超聲波檢測(cè)距離的模塊。
 
      
這東西長(zhǎng)這樣,五塊一個(gè)。
這東西原理是,我們聲音發(fā)出去是會(huì)彈回來的對(duì)吧,就是基于這個(gè)原理。
控制口發(fā)一個(gè)10US 以上的高電平,就可以在接收口等待高電平輸出.一有輸出就可以開定時(shí)器計(jì)時(shí),當(dāng)此口變?yōu)榈碗娖綍r(shí)就可以讀定時(shí)器的值,此時(shí)就為此次測(cè)距的時(shí)間,方可算出距離.如此不斷的周期測(cè),就可以達(dá)到你移動(dòng)測(cè)量的值了。
找到的參考例程都是51之類的,還好這東西原理不難,憑我這樣子半吊子水平還能改改用,上程序
#define ECHOPIN 8                       
#define TRIGPIN 9 
void setup()
{
Serial.begin(9600);
pinMode(ECHOPIN, INPUT);
pinMode(TRIGPIN, OUTPUT);
void loop()
{
digitalWrite(TRIGPIN, LOW);
delayMicroseconds(2);                           //制造脈沖
digitalWrite(TRIGPIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGPIN, LOW);
float distance = pulseIn(ECHOPIN, HIGH);
distance= distance/58;
Serial.println(distance);
delay(500);
}
} 

這東西一共四個(gè)腳 ,一個(gè)是5V電源,一個(gè)是地,一個(gè)是ECHO一個(gè)是TRIG,這兩個(gè)是數(shù)據(jù)的收發(fā)口,連到單片機(jī)上。我們通過TRIG發(fā)送一個(gè)10us以上的脈沖,就是一個(gè)有高有低的方波,然后就可以檢測(cè)ECHO口的返回?cái)?shù)據(jù)了,我們不用關(guān)心超聲波是如何發(fā)送又是如何接收的,只要知道我們給一個(gè)脈沖,就可以在ECHO口守株待兔,讀到一個(gè)高電平為止,然后把這中間的時(shí)間拿去處理就對(duì)了。
我們看到一個(gè)函數(shù): 

pulseIn()函數(shù)用來讀取一個(gè)引腳的脈沖(HIGH或LOW)。例如,如果value是HIGH,pulseIn()會(huì)等待引腳變?yōu)镠IGH,開始計(jì)時(shí),再等待引腳變?yōu)長(zhǎng)OW并停止計(jì)時(shí)。返回脈沖的長(zhǎng)度,單位毫秒。如果在指定的時(shí)間內(nèi)無脈沖函數(shù)返回。
計(jì)時(shí)范圍從10微秒至3分鐘。(1秒=1000毫秒=1000000微秒)
語法:
pulseIn(pin, value) 
pulseIn(pin, value, timeout)
參數(shù):
pin:你要進(jìn)行脈沖計(jì)時(shí)的引腳號(hào)(int)。 
value:要讀取的脈沖類型,HIGH或LOW(int)。 
timeout (可選):指定脈沖計(jì)數(shù)的等待時(shí)間,單位為微秒,默認(rèn)值是1秒(unsigned long) 
這是一個(gè)灰常方便的函數(shù),我愛arduino。
讀到的東西是英寸單位,所以要除以58,這樣一來就能化成厘米了,數(shù)據(jù)手冊(cè)是這么說的,別問我為什么。得出來的數(shù)據(jù)通過串口監(jiān)視器可以查看,精度不是很高,超過四米基本瞎了,低于二十厘米反應(yīng)也遲鈍了。但是用來做避障神馬的妥妥地足夠了,預(yù)計(jì)日后會(huì)用舵機(jī)配合它進(jìn)行組合掃描探測(cè),現(xiàn)在先放著吧。
然后就剩兩個(gè)模塊了,下次再來。
關(guān)閉窗口

相關(guān)文章