zs5577517 发表于 2011-5-6 11:01:11

使用STC89C52控制舵机实现平稳旋转

请教下使用STC89C52控制舵机实现平稳旋转需要将定时定在多少us合适呢?。。我用的是辉胜9g舵机。很便宜的那种。现在定时100us..只能以9度/100us来运动。感觉动作非常不流畅。。想降低定时的时间。。如果定时在20us的话会不会加大单片机的负载呢?我需要控制6路这种舵机(正在自制双足机器人).希望大家多多指教啊

xinzhi1986 发表于 2011-5-6 11:15:38

#include<REG52.h>
#define uint8unsigned char
#define uint16 unsigned int


sbit key1=P3^0;
sbit key2=P3^1;
sbit key3=P3^2;
sbit key4=P3^3;

//PWM的输出端口
sbit PWM_OUT0=P1^0;
sbit PWM_OUT1=P1^1;
sbit PWM_OUT2=P1^2;
sbit PWM_OUT3=P1^3;
sbit PWM_OUT4=P1^4;
sbit PWM_OUT5=P1^5;
sbit PWM_OUT6=P1^6;
sbit PWM_OUT7=P1^7;


//PWM的数据值
uint16 PWM_Value={1960,1455,1455,1000,1750,2000,2500,2000};

uint8 order1;//定时器扫描序列
/*===================================================================================
    定时器T0的中断服务程序
    一个循环20MS= 8*2.5ms
=====================================================================================*/
void timer0(void) interrupt 1 using 1
{
switch(order1)
{
case 1:PWM_OUT0=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 2:PWM_OUT0=0;      
              TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
case 3:PWM_OUT1=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 4:PWM_OUT1=0;
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
case 5:PWM_OUT2=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 6:PWM_OUT2=0 ;
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
case 7:PWM_OUT3=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 8:PWM_OUT3=0;
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
case 9:PWM_OUT4=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 10: PWM_OUT4=0;
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
case 11: PWM_OUT5=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 12: PWM_OUT5=0;
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
case 13: PWM_OUT6=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 14: PWM_OUT6=0;
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
case 15: PWM_OUT7=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 16: PWM_OUT7=0;
          order1=0;
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          order1=0;
          break;
          default : order1=0;
    }
    order1++;
}

/*===================================================================================
初始化中断
=====================================================================================*/
void InitPWM(void)
{
   order1=1;

   TMOD |=0x11;
   TH0=-1500/256;
   TL0=-1500%256;
   EA=1;
   EX0=0;
   ET0=1; TR0=1;PT0=1;PX0=0;
}


void delay(void)
{
uint16 i=100;

while(i--);

}


void main(void)
{

InitPWM();
    while(1)
    {

if(key1==0)
{
    if(PWM_Value<2200)
       PWM_Value+=2;
   }

   if(key2==0)
{
    if(PWM_Value>1000)
       PWM_Value-=2;
}

    if(key3==0)
{
    if(PWM_Value<2100)
       PWM_Value+=2;
   }

   if(key4==0)
{
    if(PWM_Value>850)
       PWM_Value-=2;
}
   delay();
    }
}

zs5577517 发表于 2011-5-6 12:17:01

谢谢大哥。。这个想法很独特啊。。和我写的程序思想完全不一样啊。。刚仿真试了下貌似还比较流畅。。准备实物测试下

zs5577517 发表于 2011-5-6 15:12:29

回复【1楼】xinzhi1986 信志
#include&lt;reg52.h&gt;
#define uint8unsigned char
#define uint16 unsigned int
sbit key1=p3^0;
sbit key2=p3^1;
sbit key3=p3^2;
sbit key4=p3^3;
//pwm的输出端口
sbit pwm_out0=p1^0;
sbit pwm_out1=p1^1;
sbit pwm_out2=p1^2;
sbit pwm_out3=p1^3;
sbit pwm_out4=p1^4;
sbit pwm_out5=p1^5;
sbit pwm_out6=p1^6;
sbit pwm_out7=p1^7;
//pwm的数据值
uint16 pwm_value={1960,1455,1455,1000,1750,2000,2500,2......
-----------------------------------------------------------------------

看了半天还是不太清楚为什么能实现平稳旋转唉、、和我自己弄的程序效果差太远了...希望能再指点下..
   #include <reg52.h>       
   #define uchar unsigned char
   #define uint unsigned int
   #define timer_data (256-50)
   sbit PWM1=P1^0;
   sbit PWM2=P1^1;
           sbit PWM3=P1^2;
             sbit PWM4=P1^3;
                   sbit PWM5=P1^4;
                     sbit PWM6=P1^5;
//sbit ENA=P2^3;
   uchar num,a,flag,kind,n,keys=0;
   uint time_count=0,time_count2=0,PWM_t1=0,PWM_t2=0,PWM_t3=0,PWM_t4=0,PWM_t5=0,PWM_t6=0,set=0,d,p=0,k=0,T0time=0,t1,t2,t3,zhuansu=0,setting=0,x=0,mode=0;
   void delay(uchar t)
   {uint x,y;
   for(x=110;x>0;x--)
   for(y=t;y>0;y--)        ;
   }
   

void timer_init()
{       TMOD=0x20;                                                //定时器1为模式2(8位自动重装)
                TF1=0;                                                       //清中断标志
                TH1=timer_data;                                        //保证定时时长为0.2ms
                TL1=TH1;
                ET1=1;                                                        //允许T0中断
                TR1=1;                                                       
                EA=1;                                                        //中断允许
       
                                                                   //开始计数       
}
voidmotor_init()
{PWM_t1=18;
PWM_t2=18;
PWM_t3=18;
PWM_t4=18;
PWM_t5=18;
PWM_t6=18;
delay(200);
}
void qianjin()
{PWM_t1=12;
PWM_t2=16;
PWM_t3=16;
PWM_t4=16;
PWM_t5=16;
PWM_t6=18;

}
void zhuan16()
{PWM_t1=19;
PWM_t6=19;
delay(1);
PWM_t1=20;
PWM_t6=20;
delay(1);
PWM_t1=21;
PWM_t6=21;
delay(1);
PWM_t1=22;
PWM_t6=22;
delay(1);


}
void fzhuan16()
{
PWM_t1=21;
PWM_t6=21;
delay(1);
PWM_t1=20;
PWM_t6=20;
delay(1);
PWM_t6=19;
PWM_t1=19;               
delay(1);
PWM_t6=18;
PWM_t1=18;
delay(1);

}
void zhuan116()
{PWM_t6=17;
PWM_t1=17;
delay(1);
PWM_t6=16;
PWM_t1=16;
delay(1);
PWM_t1=15;
PWM_t6=15;
delay(1);
PWM_t1=14;
PWM_t6=14;
delay(1);
}
void fzhuan116()
{
PWM_t1=15;
PWM_t6=15;
delay(1);
PWM_t1=16;
PWM_t6=16;
delay(1);
PWM_t1=17;
PWM_t6=17;
delay(1);
PWM_t1=18;
PWM_t6=18;
delay(1);

}

void zhuan2345()
{PWM_t3=17;
PWM_t4=19;
PWM_t5=19;
PWM_t2=17;
delay(100);

}
void zhuan5432()
{PWM_t4=18;
PWM_t3=18;
PWM_t2=18;
PWM_t5=18;
delay(100);
PWM_t4=17;
PWM_t3=19;
PWM_t2=19;
PWM_t5=19;
delay(100);


}
void fhuan34()
{
PWM_t1=20;
delay(100);
PWM_t1=19;
delay(100);

}
void zhuan25()
{
PWM_t5=19;
PWM_t2=17;
PWM_t3=19;
PWM_t4=19;
delay(100);

}
void fhuan25()
{

PWM_t5=17;
delay(100);


}

void main()
{ n=0;

timer_init();
motor_init();
delay(200);
while(1)
{
flag=1;
zhuan16();          
fzhuan16();
zhuan116();
fzhuan116();

} }
void IntTime1()interrupt 3        using        2
{
      time_count++;               
                if(flag==1)                                       
           {                                                                                               
              if(time_count<PWM_t1)
              {PWM1=1;}
              else
              {PWM1=0;}        
                        if(time_count<(PWM_t2))
              {PWM2=1;}
              else
              {PWM2=0;}                               
                        if(time_count<PWM_t3)
              {PWM3=1;}
              else
              {PWM3=0;}

                        if(time_count<PWM_t4)
              {PWM4=1;}
              else
              {PWM4=0;}

                        if(time_count<PWM_t5)
              {PWM5=1;}
              else
              {PWM5=0;}

                        if(time_count<PWM_t6)
              {PWM6=1;}
              else
              {PWM6=0;}
                                               
                       
                }
       
      if(time_count >=251)                          //每输出一个PWM波计数器清一次零,也即PWM波周期长度
      {
         time_count=0;
      }
}

killin 发表于 2011-5-6 16:53:46

标记一下,多路舵机控制基本都是二楼的思路,PPM调制脉宽不超过2.5mS,周期为20mS,所以一个周期内可以输出8个脉冲用于控制8路舵机。一楼的程序先在第一路输出脉冲,等到2.5mS后,开始第二路输出脉冲,其他各路依次输出。舵机平稳旋转就需要每次按键脉宽增量比较小,脉宽变化也不能太快。像一楼的程序脉宽增量差不多是1/500,而楼主的程序差不多是1/10.

zs5577517 发表于 2011-5-6 18:06:28

回复【4楼】killin
-----------------------------------------------------------------------

谢谢大哥哇。。就是这个程序里
case 1:PWM_OUT0=1;
          TH0=-PWM_Value/256;
          TL0=-PWM_Value%256;
          break;
case 2:PWM_OUT0=0;      
          TH0=-(2700-PWM_Value)/256;
          TL0=-(2700-PWM_Value)%256;
          break;
这个地方if(PWM_Value<2200)
         PWM_Value+=2;
是不是每次比较的时候如果还没有到预定的角度就在定时器初值里面把初值再加个2呢?
这一截程序就是高电平延时的时间吗?    TH0=-PWM_Value/256;
                                       TL0=-PWM_Value%256;
2700是不是表示就是2.5ms的脉宽呀
想想这种程序和自己写的不是一个级别的。看都要琢磨半天。。差距也太大了哎

killin 发表于 2011-5-8 02:36:06

基本上就是你楼上说的那样

STC89C55 发表于 2011-5-8 08:52:15

好啊……

zs5577517 发表于 2011-5-10 09:58:18

东西基本上弄出来了。。老师说最好能上斜坡和爬楼梯。。对于只有6个关节的舵机的双足结构很有难度哎

killin 发表于 2011-5-10 10:13:23

你们老师也真能扯,能自动平衡,独立行走就很了不起了。

xiaolei0428 发表于 2011-5-10 13:05:47

mark

zs5577517 发表于 2011-6-8 10:08:29

http://cache.amobbs.com/bbs_upload782111/files_40/ourdev_646721GZLDOK.jpg
(原文件名:20110608529.jpg)

http://cache.amobbs.com/bbs_upload782111/files_40/ourdev_646722VP6RMX.jpg
(原文件名:20110608530.jpg)

http://cache.amobbs.com/bbs_upload782111/files_40/ourdev_646723JR0166.jpg
(原文件名:20110608531.jpg)

zs5577517 发表于 2011-6-8 10:10:45

暂时只能实现前进后退和原地转方向。。红外遥控控制。。结构全是用AB胶,万能版和木头粘接而成。。算是就地取材了。哈哈

gale 发表于 2011-6-8 10:16:08

做到5us已经足够了,10us就可以比较流畅了,100us是在太低了。用定时器做,不要用PWM。

wso75839840 发表于 2011-6-14 00:16:03

mark
页: [1]
查看完整版本: 使用STC89C52控制舵机实现平稳旋转