新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 用Pic單片機(jī)控制8路MG995舵機(jī)(servo motor)的實(shí)現(xiàn)方法

用Pic單片機(jī)控制8路MG995舵機(jī)(servo motor)的實(shí)現(xiàn)方法

作者: 時(shí)間:2016-11-18 來(lái)源:網(wǎng)絡(luò) 收藏
一個(gè)PIC16F877A單片機(jī)有1個(gè)16位定時(shí)器TIMER1,我們用來(lái)制8個(gè)舵機(jī)(即順序脈沖輸出),這樣一個(gè)單片機(jī)就可以控制8個(gè)舵機(jī)。用8個(gè)IO口來(lái)控制舵機(jī),舵機(jī)控制的信號(hào)周期為20mS,而正脈沖最大只有2.5mS,這樣有17.5mS是空的??梢圆捎眠@種方法:在RD0口輸出一個(gè)0.5~2.5mS的脈沖,控制一號(hào)舵機(jī)。完成后,用端口RD1口輸出另外一個(gè)脈沖,控制2號(hào)舵機(jī),就這樣下去.....在一號(hào)舵機(jī)需要第二個(gè)脈沖之前,可以輸出 20/2.5=8個(gè)脈沖,可以用來(lái)控制8個(gè)舵機(jī),當(dāng)然,需要用8個(gè)IO口。但是一般來(lái)說(shuō)不可能正好有8個(gè)2.5mS的脈沖來(lái)填滿20mS,這樣就需要對(duì)輸出脈沖的總寬度進(jìn)行累加補(bǔ)償,然后再用低電平填滿20mS中剩下的時(shí)間。一個(gè)周期讓timer1工作8~9次,前8次每次根據(jù)不同舵機(jī)的脈寬要求進(jìn)行定時(shí),每次都對(duì)不同的IO口輸出脈沖.第九個(gè)定時(shí)是用來(lái)填滿20mS的剩余時(shí)間的. 每個(gè)口在輸完脈沖后,置0 ,然后單片機(jī)就不用管他,可以進(jìn)行下一個(gè)IO口的脈沖輸出了. 這樣一個(gè)單片機(jī)順序?qū)?個(gè)IO口進(jìn)行脈沖輸出. 雖然每個(gè)舵機(jī)的脈沖時(shí)間有一點(diǎn)延遲,但是不超過(guò)20mS,這對(duì)于舵機(jī)這種低速運(yùn)行器件來(lái)說(shuō)是完全感覺(jué)不出來(lái)的。仿真如下圖:

本文引用地址:http://butianyuan.cn/article/201611/315939.htm

下面就用這種方法進(jìn)行編程。
#include
unsigned char servo_angle_H[8];
unsigned char servo_angle_L[8];

unsigned char compensate_TL;
unsigned char compensate_TH;

unsigned char p;


void set_servo (unsigned char angle0,unsigned char angle1,
unsigned char angle2,unsigned char angle3,
unsigned char angle4,unsigned char angle5,
unsigned char angle6,unsigned char angle7)
{
unsigned int temp,temp0,value[8];
unsigned char i;

for(i=0;i<8;i++){
servo_angle_H[i]=64468/256;
servo_angle_L[i]=64468%256;
}

compensate_TL=50268%256;
compensate_TH=50268/256;

temp = angle0+angle1+angle2+angle3+angle4+angle5+angle6+angle7;
value[0]=65068-(100*angle0)/9;
value[1]=65068-(100*angle1)/9;
value[2]=65068-(100*angle2)/9;
value[3]=65068-(100*angle3)/9;
value[4]=65068-(100*angle4)/9;
value[5]=65068-(100*angle5)/9;
value[6]=65068-(100*angle6)/9;
value[7]=65068-(100*angle7)/9;
for(i=0;i<8;i++){
servo_angle_H[i]=value[i]/256;
servo_angle_L[i]=value[i]%256;
}

temp0=46068+(100*temp)/9;
compensate_TL=temp0%256;
compensate_TH=temp0/256;

}
//主程序***********************************************************************
void main(void)
{unsigned int a;unsigned int b;
INTCON=0;
GIE=1;//;打開(kāi)總中斷
PEIE=1;//;打開(kāi)外部中斷使能位
TMR1IE=1;//;打開(kāi)TMR1中斷

TRISD=0X00;
PORTD= 0X00;//脈沖波形起始狀態(tài)
T1CON=0x01;//設(shè)置TMR1的控制字

TMR1IF=0;

unsigned char i;


set_servo (13,34,56,87,80,123,156,13);
while(1){;}

}
//中斷服務(wù)程序*************************************************************
void interrupt timer1(void)
{
TMR1IF=~TMR1IF;

switch(p){
case 0:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0X01;
break;
case 1:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00000010;
break;
case 2:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00000100;
break;
case 3:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00001000;
break;
case 4:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00010000;
break;
case 5:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B00100000;
break;
case 6:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B01000000;
break;
case 7:TMR1L=servo_angle_L[p];TMR1H=servo_angle_H[p];PORTD=0B10000000;
break;
default:TMR1L=compensate_TL;TMR1H=compensate_TH;PORTD=0B00000000;p=0;
break;
}
p++;
}



關(guān)鍵詞: Pic單片機(jī)控MG995舵

評(píng)論


技術(shù)專(zhuān)區(qū)

關(guān)閉