舵機(jī)的控制方式
舵機(jī)的種類有很多,下面我所展示的是非常常見(jiàn)的SG90舵機(jī)(下面簡(jiǎn)稱“舵機(jī)”),也是我們這次實(shí)驗(yàn)室考核所使用的舵機(jī)。
篇幅有限,這里只簡(jiǎn)單介紹了SG90舵機(jī),想深入研究的同學(xué)可以自己去查閱資料。
我們先來(lái)了解一下SG90舵機(jī)
SG90舵機(jī)有三根線:GND、VCC和信號(hào)線:
GND(負(fù)極)和VCC(正極)都是電源線,可以接在開(kāi)發(fā)板相同標(biāo)識(shí)的排針或與開(kāi)發(fā)板相同的電源上,注意GND要與單片機(jī)共地(接在同一個(gè)負(fù)極上)。
信號(hào)線接在單片機(jī)的IO口上,我們使用IO口輸出PWM來(lái)控制舵機(jī)。
在對(duì)舵機(jī)進(jìn)行控制時(shí),像控制LED燈直接對(duì)信號(hào)線輸出1和0是不能夠正常控制的,要使用PWM進(jìn)行控制:
↑不正確的控制方法,可能是醬紫的
↑使用PWM控制,能隨意改變角度
那么下面我們進(jìn)入正題:使用PWM對(duì)舵機(jī)進(jìn)行控制。
舵機(jī)能在其旋轉(zhuǎn)范圍內(nèi)(0°~180°)旋轉(zhuǎn)至任意角度,但注意,這不是指能夠連續(xù)轉(zhuǎn)圈圈,而是像一把量角器,假設(shè)設(shè)置了30°,那么舵機(jī)就會(huì)旋轉(zhuǎn)至30°的位置并停下,而不是在原來(lái)的位置疊加上30°。
舵機(jī)的旋轉(zhuǎn)角度是通過(guò)PWM的占空比來(lái)調(diào)節(jié)的,PWM的周期一般為20ms,它們的關(guān)系如下表所示:
可以發(fā)現(xiàn),要舵機(jī)停在0°的位置并不能將IO口直接置0,180°也不能直接置1。
示例程序
舵機(jī)的控制程序其實(shí)和LED亮度調(diào)節(jié)、呼吸燈的程序基本一致,都是使用PWM控制,只不過(guò)占空比有范圍而已。
下面的程序是在我之前發(fā)的PWM的程序上稍作修改得到的,PWM部分就不再解釋了,只解釋舵機(jī)的控制部分。
#include < reg52.h >
#define PWM_T 200 //產(chǎn)生中斷的時(shí)間,因?yàn)槭?4MHz,200即100微妙(0.1毫秒)
int PWM_count0 = 0; //進(jìn)入中斷的次數(shù)
int PWM_count1 = 0; //與上面的類似,用于計(jì)數(shù)
int PWM_F = 0; //一個(gè)用于計(jì)時(shí)的標(biāo)志,作用類似定時(shí)器的TF0、TF1
sbit servo = P2^0; //舵機(jī)信號(hào)線所連接的IO口
void PWM_Start() //PWM初始化函數(shù),打開(kāi)了定時(shí)器0
{
EA = 1;
ET0 = 1;
TMOD |= 0x01;
TR0 = 1;
TH0 = (65536-PWM_T)/256;
TL0 = (65536-PWM_T)%256;
}
int PWM(int PWM_value) //控制PWM輸出的子函數(shù)
{
if(PWM_count0 <= PWM_value)
{
return 1;
}
else
{
return 0;
}
}
void main()
{
PWM_Start(); //PWM開(kāi)始運(yùn)行
while(1)
{
while(1)
{
servo = PWM(5); //旋轉(zhuǎn)至0°
if(PWM_F == 1) //判斷標(biāo)志是否為1,是則代表著過(guò)了1秒
{
PWM_F = 0; //將標(biāo)志歸零
break; //過(guò)了1秒,退出循環(huán)
}
}
while(1)
{
servo = PWM(10); //旋轉(zhuǎn)至45°
if(PWM_F == 1)
{
PWM_F = 0;
break;
}
}
while(1)
{
servo = PWM(15); //旋轉(zhuǎn)至90°
if(PWM_F == 1)
{
PWM_F = 0;
break;
}
}
while(1)
{
servo = PWM(20); //旋轉(zhuǎn)至135°
if(PWM_F == 1)
{
PWM_F = 0;
break;
}
}
while(1)
{
servo = PWM(25); //旋轉(zhuǎn)至180°
if(PWM_F == 1)
{
PWM_F = 0;
break;
}
}
}
}
void Timer0() interrupt 1
{
TH0 = (65536-PWM_T)/256;
TL0 = (65536-PWM_T)%256;
PWM_count0++;
if(PWM_count0 == 200) //過(guò)了20ms,完成了一個(gè)PWM周期
{
PWM_count0 = 0; //清零,重新開(kāi)始計(jì)數(shù)
PWM_count1++;
if(PWM_count1 == 50) //PWM_count0清零了50次,也就是說(shuō)過(guò)了20ms*50=1000ms=1s
{
PWM_count1 = 0; //清零,重新開(kāi)始計(jì)數(shù)
PWM_F = 1; //標(biāo)志置1,說(shuō)明已經(jīng)過(guò)了2s
}
}
}
我在程序中并沒(méi)有使用軟件延時(shí)(delay()函數(shù)),這在PWM那篇文章中也說(shuō)過(guò)了,軟件延時(shí)期間無(wú)法改變IO口的高低電平輸出,PWM也就失效了。
我的做法是設(shè)置一個(gè)標(biāo)志PWM_F(也可以直接判斷PWM_count1的值),當(dāng)達(dá)到設(shè)定的時(shí)間就退出循環(huán),否則就回到循環(huán)進(jìn)行PWM輸出。
如果你覺(jué)得這樣做比較麻煩,也可以調(diào)用另一個(gè)定時(shí)器來(lái)計(jì)時(shí),不過(guò)定時(shí)器的數(shù)量是有限的(51只有兩個(gè),52、STC15F2K60S2有三個(gè))。
在寫(xiě)PWM的程序時(shí),可以參考我上面的做法,每0.1ms進(jìn)入一次中斷,進(jìn)入200次(20ms)就完成一次PWM中斷,對(duì)應(yīng)著舵機(jī)所要求的PWM周期長(zhǎng)度,控制起來(lái)也會(huì)方便很多。
另外,頭文件建議使用與單片機(jī)型號(hào)所匹配的,上面例程中包含reg52.h是為了有較高的兼容性,但這樣就有一些資源無(wú)法調(diào)用。例如STC15F2K60S2,P4引腳(如P47)只有在包含STC15F2K60S2.h時(shí)才能被調(diào)用。
假如你的舵機(jī)不能正常運(yùn)行,可能是下面的原因:
1.單片機(jī)晶振或定時(shí)器沒(méi)有設(shè)置正確,例如上面例程對(duì)應(yīng)的是24MHz的頻率,下載時(shí)選擇了默認(rèn)的11.0592MHz;
2.電源供電不足,可以使用充電寶供電試試。
總結(jié)
學(xué)會(huì)PWM后,舵機(jī)的控制其實(shí)非常容易,稍作一下改動(dòng)就行。對(duì)舵機(jī)感興趣的同學(xué)可以去了解一下其他類型的舵機(jī),使用PWM控制的只是其中一種。
-
51單片機(jī)
+關(guān)注
關(guān)注
274文章
5704瀏覽量
123745 -
PWM控制
+關(guān)注
關(guān)注
7文章
194瀏覽量
26316 -
舵機(jī)
+關(guān)注
關(guān)注
17文章
270瀏覽量
41076 -
GND
+關(guān)注
關(guān)注
2文章
539瀏覽量
38766 -
SG90
+關(guān)注
關(guān)注
0文章
9瀏覽量
11517
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論