论坛风格切换切换到宽版
  • 3874阅读
  • 2回复

新搞的servo控制算法 [复制链接]

上一主题 下一主题
离线XLDZZ
 
发帖
443
只看楼主 倒序阅读 0楼 发表于: 2010-07-18
新搞的servo控制算法
基于pic16,比较简单的滤波算法和pid算法。

因为只用了积分所以大大降低了难度,输出为频率脉冲。
其实是个数字化的vf变换器。

过几天到机床上去试试效果,在确定系数k和相关的参数。
程序如下,以供参考。

#include<pic.h>
__config(0x3b32);
#define uchar unsigned char
#define uint unsigned int
uint ad_val();
void init();
void int_init();
void delay(uint x);
const uchar table[]={0xd7,0x12,0xcb,0x5b,0x1e,0x5d,0xdd,0x13,0xdf,0x5f};
void dsp(uchar num1,uchar num2,uchar num3);
void sc();
void vf();
uint lednum;
int adval,val;
uint adtemp,advaltemp;
uchar adcunt,adflg;
uchar bai,shi,ge,dlv;
uint time_cunt;//vf变换时间
uchar flg_ad_en;//ad标记
uchar flg_pid_en;//pid标记
uchar flg_vf_en;//vf变换标记
uchar flg_dl_en;//数字滤波标志
uchar flg_ch;
uchar pid_cunt;
float fval;//ad值
int pid_val_g;//给定
int pid_val_b;//反馈
int d_fadval;
int fa,fb,fc,fd;
uint a1,a2,a3,a4 ;
void main()
{
init();//io初始化
int_init();//中断初始化
adtemp=0;//清寄存器
dlv=20;//数字滤波器赋值
time_cunt=10 ;
while(1)
{
 
  if(flg_ad_en==1)
  {
  rc1=0;
  flg_ad_en=0;//表示ad采样结束
  val=adresh;
  adval=val<<8|adresl;
  fval=adval/1023*50;
//******如果flg_ad_en标记为1,那么求ad转换的值***//  
  if(5<=fval<20)//此处20为分压所得的数据
    {
      d_fadval=d_fadval+fval;//浮点数累加
      dlv--;
      if(dlv==0)
      {
      dlv=20;
      d_fadval= d_fadval/20;//求平均数
      pid_val_b=d_fadval*2;//补偿分压值
      d_fadval=0;//累加数归零
      flg_pid_en=1;//pid允许位
      }  
    }
  }
//******以上为数字滤波程序**************//

  if(flg_pid_en==1)
    {
    pid_cunt=1;
    flg_pid_en=0;//允许位归零
   
    pid_val_g=16;
 
    fa=pid_val_g-pid_val_b;
    fb=fa*4;
   
   
      }

}
             

 
   
}












void interrupt time2()//中断处理
{

if(tmr2if==1)
{
  tmr2if=0;
  time_cunt--;

   
    if(time_cunt==0)
  {
   
    time_cunt=100-fb;//16*16*0.4us*5,这里需要设置变量
    if(rc0==1)
      {
      rc0=0;
      }
    else
      {
      rc0=1;  
      }
  }
 
}

if(adif==1)
{
  adif=0;
  flg_ad_en=1;
  adgo=1;
  rc1=1;
}


}

void init()
{
trisa=0x01;
trisb=0;
trise=0;
trisd=0;
trisc=0;
porte=0;
portd=0;
portb=0;
porta=0;
porte=0x06;
delay(2);
porte=0;

cmcon=0x07;//关比较器
adcon0=0x81;//1/64,ch0,power on
adcon1=0xce;//数据右对齐an0为模拟输入。
adgo=1;
//-----ad初始化----------
}
void int_init()
{
gie=1;//开总中断
adie-1;//开ad中断
peie=1;//开外围中段
tmr2ie=1;//开定时器2中断

t2con=0x2a;//前后分频5/1(5*4),定时器2电源关闭。
tmr2if=0;//清中断标志位
tmr2on=1;//开定时器2
pr2=0x01;//十进制数20(5*4*50=1000us)
}

void dsp(uchar num1,uchar num2,uchar num3)
{
portb=table[num1];//显示第一个数码管
portd=0x04;
sc();
delay(2);
portb=table[num2];//显示第二个数码管
portd=0x02;
sc();
delay(2);
portb=table[num3];//显示第三个数码管
portd=0x01;
sc();
delay(2);
}

void sc()//数据所存
{
porte=0;
delay(2);
porte=0x06;
delay(2);
porte=0;
delay(2);
}


void delay(uint x)//延时程序
{
uint a,b;
for(a=x;a>0;a--)
  for(b=110;b>0;b--);
}
离线BD4XR
发帖
8746
只看该作者 1楼 发表于: 2010-07-18
很好。。 响应速度怎么样呢?
离线XLDZZ
发帖
443
只看该作者 2楼 发表于: 2010-07-18
响应速度一般,在10ms级别的。
太快的话机床的刚性达不到,反而会振荡。