首页 用PWM_细分步进电机_包含原理和程序

用PWM_细分步进电机_包含原理和程序

举报
开通vip

用PWM_细分步进电机_包含原理和程序 用 PWM 细分步进电机,包含原理和程序 农民讲习所 这是俺一个关于打印机项目中步进马达中的内容,使用的原理为电流矢量图(a),为减少矢量表的误差,改进为(g).(误 差大的时候,Ia和Ib的绝对值变大,角度不变,即比例不变) 磁场合成决定步进马达当前的位置。 我们常用的是图(b),用电压驱动时和线圈个数有关系,直接驱动它们,合成的最小角度都是固定的。 细分最常见的是电流细分,电流引起的磁场的合成就决定马达的角度。所以我们一般用电流合成图来代替磁场合成图。 用电流合成电路复杂一点(用...

用PWM_细分步进电机_包含原理和程序
用 PWM 细分步进电机,包含原理和程序 农民讲习所 这是俺一个关于打印机项目中步进马达中的内容,使用的原理为电流矢量图(a),为减少矢量表的误差,改进为(g).(误 差大的时候,Ia和Ib的绝对值变大,角度不变,即比例不变) 磁场合成决定步进马达当前的位置。 我们常用的是图(b),用电压驱动时和线圈个数有关系,直接驱动它们,合成的最小角度都是固定的。 细分最常见的是电流细分,电流引起的磁场的合成就决定马达的角度。所以我们一般用电流合成图来代替磁场合成图。 用电流合成电路复杂一点(用MCU+DA+L298实现也不难)。 这里俺用PWM方式,用控制电压的方式代替电流。原因:在电压稳定后,线圈的电流和电压成正比。稳定是PWM细分的 要点,也决定马达速度不能太高。 在细分的情况下,电机分两相和四相是没意义的。可以把四相电机当两相使用。 下面是俺的程序,使用MEGA16,因为有PWM。 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //2相步进马达驱动 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #define Step_OutMode() DDRB|=BIT(6)|BIT(7) #define Step_InMode() DDRB&=~(BIT(6)|BIT(7)) #define Step_ReadIO() (PORTB&( ~(BIT(6)|BIT(7)) )) #define Step_WriteIO(x) PORTB=x struct Motor2P_Table{ //细分表结构 unsigned char mQuadrant; //象限0-3 unsigned char mX_Pwm; //x输出的PWM unsigned char mY_Pwm; //y输出的PWM }; struct Motor2P{ unsigned char mTableId; //细分表ID unsigned char mTask; //马达驱动的任务转移号 unsigned char mSaveTimer; //马达驱动节电模式使用的计数器 unsigned char mReg; //马达驱动使用的寄存器 unsigned char mTimer; //对2MS的计数器,时间扩展 unsigned int mSteps; //马达要走的步数 unsigned char mDirect; //马达走动方向 unsigned char mStepRunTimer; //步进时输出有效的时间寄存器 unsigned char mStepIdleTimer; //步进时输出节电的时间寄存器 unsigned char mStepCount; //细分表走动步长。1-2-4-8-16 }; //------------------------------------------------------------ #ifdef dMotor2P_Main #define Motor2P_Head #else #define Motor2P_Head extern #endif Motor2P_Head struct Motor2P sMotor2P; //定义变量 Motor2P_Head void Motor_Steps(unsigned char fDirect,unsigned int mSteps);//马达走动.fDirect=1,0->3,顺时 针.步数.要先检查Motor_State()==1才调用 Motor2P_Head void Motor_Init(void); //马达构造函数 Motor2P_Head void Motor_Destory(void); //马达析构函数 //返回马达状态。>0:空闲 #define Motor_State() (sMotor2P.mSteps==0) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //2相步进马达驱动 //采用PWM细分。 //原理:正弦波矢量扩展到正方形矢量 //细分数为2的整数 //节电时电流为平常的N/8。 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #include #include #include #include "Const.h" #include "System.h" #define dMotor2P_Main #include "Motor2P.h" //主程序中定义,直接定义变量 #define dStepRunTime 1 //N*2ms,输出有效的时间 #define dStepIdleTime 1 //输出节电的时间.1->无.改变速度在此改变。 #define dSaveCurrentLimit 10 // dSaveCurrentLimit/16处为节电的比例点。 #define dIdleTimeMax 100 //进入IDLE需要的空闲时间.基于2ms. enum Motor_State{ eMotor_Idle_Process, //下电过程 eMotor_Stop_State, //未启动 eMotor_PowerOn_Process, //上电 eMotor_PowerOnDelay_Process, //上电到正常工作的延时 eMotor_Normal_State, //正常工作中 eMotor_StepDelay_Process, //进入步进处理延时过程 eMotor_IdleDelay_Process, //进入节电处理延时过程 }; #define Step_Quadrant0 BIT(6)|BIT(7) #define Step_Quadrant1 BIT(7) #define Step_Quadrant2 0 #define Step_Quadrant3 BIT(6) //0-90度的细分的PWM数据(0-255).n是细分=16.x=cos(a)*255,y=a/tg(a)(正弦转多边,减少误差).逆时针表,半周期。 const struct Motor2P_Table cMotor2P_Table[]= { //第一象限 +x,+y Step_Quadrant0,255,0 , Step_Quadrant0,254,25 , Step_Quadrant0,251,50 , Step_Quadrant0,244,74 , Step_Quadrant0,237,98 , Step_Quadrant0,226,121 , Step_Quadrant0,211,141 , Step_Quadrant0,195,160 , Step_Quadrant0,180,180 , Step_Quadrant0,160,195 , Step_Quadrant0,141,211 , Step_Quadrant0,121,226 , Step_Quadrant0,98 ,237 , Step_Quadrant0,74 ,244 , Step_Quadrant0,50 ,251 , Step_Quadrant0,25 ,254 , //第二象限 -x,+y Step_Quadrant1,0 ,255 , Step_Quadrant1,25 ,254 , Step_Quadrant1,50 ,251 , Step_Quadrant1,74 ,244 , Step_Quadrant1,98 ,237 , Step_Quadrant1,121,226 , Step_Quadrant1,141,211 , Step_Quadrant1,160,195 , Step_Quadrant1,180,180 , Step_Quadrant1,195,160 , Step_Quadrant1,211,141 , Step_Quadrant1,226,121 , Step_Quadrant1,237,98 , Step_Quadrant1,244,74 , Step_Quadrant1,251,50 , Step_Quadrant1,254,25 , //第三象限 -x,-y Step_Quadrant2,255,0 , Step_Quadrant2,254,25 , Step_Quadrant2,251,50 , Step_Quadrant2,244,74 , Step_Quadrant2,237,98 , Step_Quadrant2,226,121 , Step_Quadrant2,211,141 , Step_Quadrant2,195,160 , Step_Quadrant2,180,180 , Step_Quadrant2,160,195 , Step_Quadrant2,141,211 , Step_Quadrant2,121,226 , Step_Quadrant2,98 ,237 , Step_Quadrant2,74 ,244 , Step_Quadrant2,50 ,251 , Step_Quadrant2,25 ,254 , //第四象限 +x,-y Step_Quadrant3,0 ,255 , Step_Quadrant3,25 ,254 , Step_Quadrant3,50 ,251 , Step_Quadrant3,74 ,244 , Step_Quadrant3,98 ,237 , Step_Quadrant3,121,226 , Step_Quadrant3,141,211 , Step_Quadrant3,160,195 , Step_Quadrant3,180,180 , Step_Quadrant3,195,160 , Step_Quadrant3,211,141 , Step_Quadrant3,226,121 , Step_Quadrant3,237,98 , Step_Quadrant3,244,74 , Step_Quadrant3,251,50 , Step_Quadrant3,254,25 , }; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //马达走动 //入口:方向.fDirect=1,0->3,顺时针. // 步数 //要先检查Motor_State()==1才调用 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Motor_Steps(unsigned char fDirect,unsigned int mSteps) { sMotor2P.mDirect=fDirect; sMotor2P.mSteps =mSteps; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //输出马达能量(电压->电流) //入口:mId=细分驱动表 // mNum=节电比例,16倍缩小,mNum倍放大 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static void InMotor_Energy(unsigned char mId,unsigned char mNum) { const struct Motor2P_Table *pcMotor2P_Table; unsigned char i; unsigned char x; unsigned char y; pcMotor2P_Table=&cMotor2P_Table[mId]; x=(unsigned int)( pcMotor2P_Table->mX_Pwm *mNum) >>4; y=(unsigned int)( pcMotor2P_Table->mY_Pwm *mNum) >>4; PushInterrupt(); CLI(); i=Step_ReadIO()|pcMotor2P_Table->mQuadrant; //方向,因为PWM变化慢,所以方向后改变 OCR1A=x; OCR1B=y; Step_WriteIO(i); PopInterrupt(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //马达走动一步 //入口:方向.fDirect=1,0->3,顺时针 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static void InMotor_DirecctStep(unsigned char fDirect) { if(fDirect){ if(sMotor2P.mTableId==0)sMotor2P.mTableId=sizeof(cMotor2P_Table)/sizeof(struct Motor2P_Table)-sMotor2P.mStepCount; else sMotor2P.mTableId-=sMotor2P.mStepCount; } else { sMotor2P.mTableId+=sMotor2P.mStepCount; if(sMotor2P.mTableId==sizeof(cMotor2P_Table)/sizeof(struct Motor2P_Table) )sMotor2P.mTableId=0; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //马达构造函数 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Motor_Init(void) { //变量初始化 memset( (unsigned char *)(&sMotor2P),0,sizeof(struct Motor2P) ); sMotor2P.mTimer=sMotor2P.mStepRunTimer=dStepRunTime; //输出有效的时间,设置步进时间 sMotor2P.mStepIdleTimer=dStepIdleTime; //输出节电的时间 sMotor2P.mSaveTimer = dIdleTimeMax; //可以判断忙否。>0不忙. sMotor2P.mStepCount=1; //最大16无插值.1-2-4-8-16. //T2初始化。马达驱动 // OCR2=106; //马达定时时间,决定马达的最大速度 OCR2=150; //马达定时时间,决定马达的最大速度 TCCR2=BIT(WGM21)|BIT(CS21); TIMSK|=BIT(OCIE2); //PWM初始化,使用T1的PWM,8bit OCR1A=OCR1B=0; TCCR1B=BIT(CS10); //1分频 TCCR1A=BIT(COM1A1) | BIT(COM1B1) |BIT(WGM10); //8位PWM,OC1A,OC1B DDRB|=BIT(1)|BIT(2); //控制口初始化 Step_OutMode(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //马达析构函数 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void Motor_Destory(void) { TCCR2=0; TIMSK&=~BIT(OCIE2); TCCR1B=TCCR1A=0; DDRB&=~(BIT(1)|BIT(2)); Step_InMode(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //中级线程 //马达驱动使用 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #pragma interrupt_handler timer2_comp_isr:iv_TIMER2_COMP void timer2_comp_isr(void) { switch(sMotor2P.mTask){ case eMotor_Idle_Process: //下电过程.==0 if(--sMotor2P.mReg){ //sMotor2P.mReg此时为衰减比例 if( --sMotor2P.mTimer ==0){ //延时 sMotor2P.mTimer= sMotor2P.mStepRunTimer + sMotor2P.mStepIdleTimer ; InMotor_Energy( sMotor2P.mTableId, sMotor2P.mReg ); } break; } else sMotor2P.mTask = eMotor_Stop_State; //进入STOP状态 case eMotor_Stop_State: //马达未启动 //判断起始条件sMotor2P.mSteps>0; if( sMotor2P.mSteps == 0)break; sMotor2P.mTask = eMotor_PowerOn_Process; case eMotor_PowerOn_Process: //上电启动 if( sMotor2P.mReg < dSaveCurrentLimit ){ if( --sMotor2P.mTimer ==0){ //延时 sMotor2P.mTimer= sMotor2P.mStepRunTimer + sMotor2P.mStepIdleTimer ; InMotor_Energy( sMotor2P.mTableId, ++sMotor2P.mReg ); //衰减比例递增加大电流 } break; } sMotor2P.mTask = eMotor_PowerOnDelay_Process; //进入正常工作模式前的延时 break; case eMotor_PowerOnDelay_Process: //进入步进处理延时过程 if( --sMotor2P.mTimer ==0){ sMotor2P.mTimer= sMotor2P.mStepRunTimer; //开始延时 sMotor2P.mTask = eMotor_Normal_State; //进入正常工作模式 } else break; lMotor_Normal_State: case eMotor_Normal_State: //正常工作中 if( sMotor2P.mSteps == 0){ //节电模式计时器增加 if( ++sMotor2P.mSaveTimer == dIdleTimeMax ){ sMotor2P.mReg = dSaveCurrentLimit; //衰减比例 sMotor2P.mTask = eMotor_Idle_Process; //下电过程 } } else { sMotor2P.mSaveTimer=0; //开始步进 InMotor_DirecctStep( sMotor2P.mDirect ); //走动细分表 InMotor_Energy( sMotor2P.mTableId, 16 ); //输出电流 sMotor2P.mTask = eMotor_StepDelay_Process; //进入步进处理过程 } break; case eMotor_StepDelay_Process: //进入步进处理延时过程 if( --sMotor2P.mTimer ==0){ //节电处理 InMotor_Energy( sMotor2P.mTableId, dSaveCurrentLimit ); sMotor2P.mTask = eMotor_IdleDelay_Process; //进入节电处理延时过程 sMotor2P.mTimer= sMotor2P.mStepIdleTimer; //开始延时 } else break; case eMotor_IdleDelay_Process: //进入节电处理延时过程 if( --sMotor2P.mTimer ==0){ sMotor2P.mTimer= sMotor2P.mStepRunTimer; //延时时间 sMotor2P.mTask=eMotor_Normal_State; //转入正常工作状态,等待下一步。 sMotor2P.mSteps -- ; if(sMotor2P.mSteps == 0)Message_TailPushOnlyMess( nMotor2P_Stop); //发送马达走完消 息。 goto lMotor_Normal_State; } break; } } 驱动分驱动电压和维持电压,可以大幅度降低电流。长时间不用,STOP。(能STOP的原因,是只要再上电按STOP前的 矢量图输出就可以保证位置不动。) 从矢量合成表很容易就推出我们常用的四相的驱动图。 如果把矢量合成表的个数只保留4个,就是最普通的两相驱动方式: Ia=Max,Ib=0;->Ia=0,Ib=Max;->Ia=-Max,Ib=0;->Ia=0,Ib=-Max;-> PWM方式只适合不太高的速率场合 在这个条件下不存在抖动。所有的细分模式都会引起电流的增大,反过来说,电流的增大提高了扭矩力。 引入节电模式,多长时间电机都不会发烫。 四相和两相比较,本质就是想提高步进精度,仅此而已。从矢量图的角度来说,他们没有区别。这也是细分后,四相没 有意义的道理。 很多场合都可以看到‘细分后,四相没有意义’这句话,俺把它从原理阐述出来而已。 效果比较: 细分前,电流为1A,细分后为1.2A左右,加入节电模式,电流只有120mA左右,效果惊人。 力矩变大是细分的必然效果。 步进角度变小。 运行非常稳定,没有失步,没有振动。(细分就是解决此类问题才提出来的,步进角度变小只是它的副作用) 按俺的程序,不需要缓启动和缓停止概念。这里是用缓电流的方式解决的。
本文档为【用PWM_细分步进电机_包含原理和程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_665807
暂无简介~
格式:pdf
大小:157KB
软件:PDF阅读器
页数:10
分类:建筑/施工
上传时间:2013-11-16
浏览量:60