OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3697|回复: 1

步进电机精确控制

[复制链接]

32

主题

883

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4036
金钱
4036
注册时间
2015-11-14
在线时间
545 小时
发表于 2016-7-21 11:11:34 | 显示全部楼层 |阅读模式
1金钱
请教大家步进电机控制的问题,驱动芯片是ULN2003,5线4相得步进电机,步距角是1.8度,驱动的IO都有PWM的功能,也就是可以细分,现在遇到个问题,就是电机在启动的时候会抖动几下才能够平稳的转,有什么办法不要电机下启动的时候抖动,因为电机要一直正反转,正反转在交替的时候就会抖动,这个问题有什么好的方法解决呢?

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

507

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3347
金钱
3347
注册时间
2013-4-10
在线时间
333 小时
发表于 2016-7-21 11:27:01 | 显示全部楼层
/*********************************************************************************************
程序名:    FL-08 电机MCPU主程序
编写人:    李坤学
编写时间:  2010年10月1日
硬件支持:  STC11F04 12MHz
接口说明:  P1口接电机输出线,
控制标说明:   01:电机走一步
              02:按步数工作用加减速操作
              03:电机复位工作
              04:关电机输出并设置电机工作速度
修改日志:   (1); 2010年10月6号完成
              (2); 2010年10月18号增加了读取内部坐标的功能
              (3); 2010年10月19号增加了T轴电机连续旋转的功能
              (4); 2010年12月09号增加了电机坐标处理函数
              (5); 2011年02月03日,重写部份工作函数
              (6); 2011年05月24日,加入电机加速时间控制
/*********************************************************************************************/
#include <STC11Fxx.H> //STC11系列头文件
#include <absacc.h> //绝对地址的访问
#define M_data P1 //定义电机输出口
idata unsigned int RDDH=0;
data unsigned int  Mo_data=0;//定义电机坐标变量
data unsigned char Motor_t=0;//定义电机编码变量
data unsigned char CBB=0;//定交电机半流时间变量
data unsigned char CMM=0;//定义电机速度变量,初值设为01
data unsigned char MTdata =0; //定义同花参数变量
data unsigned char Mii =1;    //定义电机标志
data unsigned char Mx  =6;    //电初加速初始速度
data unsigned char SP_dat;    //定义SP值副本值
bdata bit MIIM=0;             //定义电机脉冲输出标志
bdata bit Mot=1;              //定义电机方向标志位,并付初值为1 电机正转
bdata bit Moc=1;              //定义通信标志
bdata bit MOTT=1;             //定义计数中断标志位
sbit MRET = P1^0;             //光电信号输入口
//sbit BF   = P3^7;           //应答信号线,数据接收标志
sbit RW   = P3^3;             //MCPU选通线
sbit MBB  = P3^4;             //电机脉冲输出线
sbit LED  = P1^2;             //工作指示灯
sbit MOIC = P1^3;             //电机电流控制线
sbit CLK  = P3^0;             //时钟线
sbit IO_data = P3^1;          //读写控制线,及数据线
sbit RETI = P3^2;             //外中断复位线
alien void MOTOR_RETI();      //定义复位汇编函数
void MOTOR();                 //电机走一步子函数
void MOTORDEL(unsigned int a);//步进电机加减速工作函数
void MOTORH(void);            //电机复位函数
/****************************************************************************************************
函数名:延时函数
调  用:DELAYR (?);
参  数:
返回值:无
结  果:占用CPU方式延时与参数数值相同的毫秒时间
/****************************************************************************************************/
void DELAY (unsigned int j)
            {
            while(j)j--;
            }
/***************************************************************************************************
函数名:步进电机正反转一步
调  用:MOTOR()
参  数:Mot=0,电机反转一步 ,Mot=1电机正转
返回值:无
结  果:电机坐标 Motor 自动加一或减一,电机走一步
***************************************************************************************************/
void MOTOR(void){   //步进电机正反转一步子程序
           code unsigned char MOTOR_DB[]={0x00,0xb0,0x90,0xd0,0x50,0x70,0x60,0xe0,0xa0,0x00};//定义电机输出编码
           unsigned char i;
           MOIC=0;   //开电机电流
           i=0;      //电机输出编码初值设00
           CBB=10;   //设减小电机电流时间设为10
           if(Mot==1)Mo_data++;
           else{if(Mo_data!=0)Mo_data--;}//如果电机反转,并且当前电机坐标不小于1时,坐标减一
           while(1)
                {
                if(Mot)Motor_t ++;//当前电机输出编码加一指向下一编码
                else Motor_t --;//电机输出编码减一
                i=MOTOR_DB[Motor_t]; //取电机输出编码
                if(i!=0)break;
                else{
                    if(Mot)Motor_t=0;
                    else Motor_t=9;
                    }
                }
           i=i&0xf8; //屏蔽低3位,高5位不变
           M_data=M_data&0x07;//屏蔽P1口的高5位,低3位不变
           M_data=M_data|i; //高5位送P1口,P1口的低3位不变
           }
/*******************************************************************************************
函数名:MEdelayr 步进电机加减速延时函数
调  用:MEdelayr(k,i);
参  数:k电机编号,i加速指针
返回值:无
结  果:步进电机工作延时
/*******************************************************************************************/
void MEdelayr(unsigned int j) //起动定时器1子函数
             {
             code unsigned int MOTOR_DB1[]={  //步进电机工作加减速时间表
             600,600,590,590,580,580,570,570,560,560,550,550,540,540,530,530,520,520,510,510, //1
             500,500,490,490,480,480,470,470,460,460,450,450,440,440,430,430,420,420,410,410, //2
             400,395,390,385,380,375,370,365,360,355,350,345,340,335,330,325,320,315,310,305, //3
             301,298,295,292,289,286,283,280,277,274,271,268,265,262,259,256,253,250,247,244, //4
             240,237,234,231,228,225,222,219,216,213,210,207,204,201,198,195,192,189,186,183, //5
             180,177,174,171,168,165,162,159,156,153,150,150,147,144,141,138,135,132,130,128, //6
             126,124,122,120,119,118,117,116,115,114,113,112,111,110,109,108,108,108,108,108, //7
             107,107,106,106,105,105,104,104,103,103,102,102,102,101,101,101,100,100,100,100, //8
             99,99,98,98,97,96,96,96,95,95,95,94,94,94,94,93,93,93,92,92, //9
             92,91,91,91,90,90,90,89,89,89,88,88,88,87,87,87,86,86,86,85, //10
             85,85,85,84,84,84,83,83,83,82,82,82,81,81,81,80,80,80,79,79, //11
             79,78,78,78,76,76,76,75,75,75,74,74,74,73,73,73,72,72,72,71, //12
             71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66, //13
             66,66,66,65,65,65,65,64,64,64,64,63,63,63,63,62,62,62,62,60, //14
             60,60,60,60,60,60,60,60,60,60,59,59,59,59,59,59,59,59,59,59, //15
             59,59,59,59,59,59,59,59,59,59,58,58,58,58,58,58,58,58,58,58, //16
             58,58,58,58,58,58,58,58,58,58,57,57,57,57,57,57,57,57,57,57, //17
             57,57,57,57,57,57,57,57,57,57,56,56,56,56,56,56,56,56,56,56, //18
             };
             j=MOTOR_DB1[j]+CMM; //查表取加速时间与电机设定速度值相加
             MOTOR();//步进电机走一步
             if(MIIM)MBB=0;  //输出脉冲
             for(;j>0;j--);
             MBB =1;          //复位电机脉冲
             }
/*******************************************************************************************
函数名:MOTOR_ttz T轴与Z轴,步进电机按坐标加减速方试工作
调  用:MOTOR_ttz(k,a)
参  数:MDATA 是电机工作参数
返回值:无
结  果:电机坐标自动加一或减一,电机走一步
*******************************************************************************************/
void MOTORDEL(unsigned int dat){//步进电机加减速工作子程序
               unsigned int k1,k2,k3,k4;        //定义加速总步数,减速总步数变,及加速指针变量
               if(dat<5){k1=0;k3=0;k2=dat;}
               else{
                   if(dat>680){k1=340;k3=340;k2=dat-680;}//电机步数大于加减速步数的情况
                   else{k1=dat/2;k2=0;k3=dat-k1;}//电机步数小于或等于加减速步数的情况
                   }
               k4=0;//加速指针初值设为0
               for(;k1>0;k1--){MEdelayr(k4);k4++;} //加速工作
               for(;k2>0;k2--){MEdelayr(k4);}      //恒速工作
               for(;k3>0;k3--){MEdelayr(k3);}      //减速工作
               CMM=0; //电加速时间清零
               }
/***************************************************************************************************
函数名:步进电机复位子程序
调  用:MOTORH ()
参  数:k,电机标志.x,同花位移参数,如果等于100,则不作同花调整
返回值:无
结  果:处理电机复位工作
备  注:检测光电输出信号,完成电机坐标初始化工作
MTdata 同花参数变量
Mii 电机标志
/**************************************************************************************************/
void Motorh(void){
            unsigned int k,a;
            MRET=1;//初始化复位检测线
            DELAY(1000);
            if(Mii==1) //如果是T电机标志
              {
              k= Mo_data % 800; //取T轴电机位置坐标
              a= MTdata+5; //计算检测位置偏移量
              if(k>400)
                {
                Mot=1; //设电机正转
                MOTORDEL((800-k)+a);//电机正转走到零坐标
                while(MRET==0)MEdelayr(0); //电机走到检测点上
                }
              else{
                  if(k>a)
                    {
                    Mot=0;//设电机反转
                    MOTORDEL((k-a)-5); //电机反转走到零坐标
                    while(MRET==0)MEdelayr(0); //电机走到检测点上
                    }
                  else{
                      Mot=1; //设电机正转
                      while(MRET==0)MEdelayr(0); //电机走到检测点上
                      }
                  }
              Mot=0;//设电机反转   
              while(MRET==1)MEdelayr(0);//电机反转离开测试点
              for(k=a;k>0;k--)MEdelayr(0);//电机反转,走到完同花位移参数
              }
            else{
                if(Mo_data>20){Mot=0; MOTORDEL(Mo_data-15);} //电机走到复位点减15步的坐标上
                Mot=0;//设电机反转  
                while(MRET==0)MEdelayr(0);//电机反转复位
                }
            Mo_data=0;//电机坐标清零,完电机电机复位工作
            }
/***************************************************************************************************
函数名:工作函数
调  用:SPII();
参  数:无
返回值:无
结  果:外中断反回函数
/**************************************************************************************************/
void SPII_MOTOR(void) {
                unsigned char k,j,dat;
                unsigned int x;
                unsigned char s[4];
                SP= SP_dat;    //重设SP初值
                EA =1;                  //CPU开中断
                TR0 =1;                 //定时器启动
                while(1)
                     {
                     RW=1;MBB=1;IO_data=1;   //初始化选通及脉冲输出线等CPU选通
                     if(RW==0)     //等待主CPU选通!
                       {
                       DELAY(8);   //延迟一段时间
                       if(RW==0)
                         {
                         TR0=0;LED=0;RW=0;      //关闭定时器,开工作指示灯,并应答主CPU
                         if(IO_data)
                           {                    //发送电机坐标
                           x= Mo_data;          //取电机坐标
                           for(j=0;j<16;j++)
                              {
                              while(CLK==1);    //等时钟线变低
                              IO_data=x&0x01;   //将最低位数据送到选通线上
                              while(CLK==0);    //等时钟线变高
                              x>>=1;            //要传送的数据左移一位
                              }
                           IO_data=1;           //置位数据线
                           }
                         else{
                             for(k=0;k<4;k++)
                                {
                                dat=0;          //清接收临时变量清零
                                for(j=8;j>0;j--)
                                   {
                                   while(CLK==1);         //等时钟线变低
                                   IO_data=1;             //初始化数据线
                                   dat>>=1;               //接收数据的最高位左移一位
                                   if(IO_data)dat+=0x80;  //取数据线上的数据
                                   while(CLK==0);         //等时钟线变高
                                   DELAY(1);              //延时1个机器周期
                                   }
                                s[k]= dat; //保存数据
                                }
                             IO_data=1;   //置位数据线
                             k=s[0];      //取功能控制参数
                             Mot=k&0x80;  //取电机方向
                             MIIM=k&0x40; //取电机脉冲输出标志
                             k&=0x0f;     //取控制指令
                             CMM =s[1];   //取电机工作速度
                             switch(k)    //取控制参数变量
                                   {
                                   case 1: MOTOR();break;//调用电机走一步子程序
                                   case 2: {
                                           x= s[2]*256+s[3];//取电机工作步数
                                           MOTORDEL(x);//将收到的电机工作步数送电机加速工作程序
                                           };break;//电机按步数工作
                                   case 3: Motorh();break;//电机复位
                                   case 4: { //关闭电机工作电流
                                           MTdata =s[2]; //取同花参数变量
                                           Mii = s[3];  //取电机标志
                                           Moc=0;//置正常通信标志
                                           M_data=M_data|0xf0;//关闭电机输出
                                           }break;
                                   }
                             }
                         TR0=1; //开定时器
                         }
                       }
                     }
                }
/***************************************************************************************************
函数名:主函数
调  用:main
参  数:无
返回值:无
结  果:外中断反回函数
备  注:主函数工作后,将工作函数的入口地址保存于变量 RDDH中
/**************************************************************************************************/
void main(void) {                            //主程序
                RDDH=(void*)SPII_MOTOR;  //取SPII_MOTOR工作函数的地址作为复位反回地址
                TMOD =0x11;
                TH0  =0x00;
                TL0  =0x01;
                IE   =0x83;   //定义中断控制
                IP   =0x08;   //定义优先中断权为定时器T1
                TCON =0x01;   //定义外中断INT0为负缘触发方试
                SP_dat=SP;    //SP值存副本
                SPII_MOTOR();
                }
/***************************************************************************************************
函数名:外部中断INT0中断处理程序
调  用:[外部引脚INT0中断处理]
参  数:无
返回值:无
结  果:用户处理外部中断信号
备  注:
/**************************************************************************************************/
void INT_0 (void) interrupt 0  using 0 { //切换寄存器组到0 注在特殊情况下,必需设为0组寄存器.
            EA =0;  //关中断
            if(RETI==0)//判断是否有复位脉冲
              {
              DELAY(800);
              DPH=RDDH/256; //将复位地址装入DPTR中
              DPL=RDDH%256;
              MOTOR_RETI(); //调用复位汇编程序
              }
            else{EA=1;}//开外中断使能
            }
/***************************************************************************************************
函数名:记数器中断处理函数
调  用:无
参  数:无
返回值:无
结  果:改变电机输出电流,
/**************************************************************************************************/
void name (void) interrupt 1 using 1
                 {
                 TH0 = 0x00;
                 TL0 = 0x05;//定时器付初值
                 if(MOIC==0)
                   {
                   if(CBB!=0)CBB--;  //判断半流时间计数器是否为0!
                   else MOIC=1;//置电机半流工作方试
                   }
                 if(Moc==0)LED=!LED; //判断当前是否与主CPU通信过//指示灯输出取反
                 else LED=0; //关闭指示灯
                 }
/***************************************************************************************************
函数名:定时中断1中断处理程序
调  用:
参  数:无
返回值:无
结  果:步进电机工作延时
备  注:
/**************************************************************************************************
void name1(void) interrupt 3
                 {
                 TR1 =0;//关闭计数器T1
                 MOTT =0;//置中断标志
                 }
/**************************************************************************************************
坤学自动化工作室
2011-06-25
likunxue@126.com
**************************************************************************************************/
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-10 00:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表