微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 用Pic单片机控制8路MG995舵机(servo motor)的实现方法

用Pic单片机控制8路MG995舵机(servo motor)的实现方法

时间:11-18 来源:互联网 点击:
一个PIC16F877A单片机有1个16位定时器TIMER1,我们用来制8个舵机(即顺序脉冲输出),这样一个单片机就可以控制8个舵机。用8个IO口来控制舵机,舵机控制的信号周期为20mS,而正脉冲最大只有2.5mS,这样有17.5mS是空的。可以采用这种方法:在RD0口输出一个0.5~2.5mS的脉冲,控制一号舵机。完成后,用端口RD1口输出另外一个脉冲,控制2号舵机,就这样下去.....在一号舵机需要第二个脉冲之前,可以输出 20/2.5=8个脉冲,可以用来控制8个舵机,当然,需要用8个IO口。但是一般来说不可能正好有8个2.5mS的脉冲来填满20mS,这样就需要对输出脉冲的总宽度进行累加补偿,然后再用低电平填满20mS中剩下的时间。一个周期让timer1工作8~9次,前8次每次根据不同舵机的脉宽要求进行定时,每次都对不同的IO口输出脉冲.第九个定时是用来填满20mS的剩余时间的. 每个口在输完脉冲后,置0 ,然后单片机就不用管他,可以进行下一个IO口的脉冲输出了. 这样一个单片机顺序对8个IO口进行脉冲输出. 虽然每个舵机的脉冲时间有一点延迟,但是不超过20mS,这对于舵机这种低速运行器件来说是完全感觉不出来的。仿真如下图:

下面就用这种方法进行编程。
#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;//;打开总中断
PEIE=1;//;打开外部中断使能位
TMR1IE=1;//;打开TMR1中断

TRISD=0X00;
PORTD= 0X00;//脉冲波形起始状态
T1CON=0x01;//设置TMR1的控制字

TMR1IF=0;

unsigned char i;

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

}
//中断服务程序*************************************************************
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++;
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top