打印

关于步进电机控制程序问题

[复制链接]
8089|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mugenwon|  楼主 | 2011-5-12 18:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
首先说明:是用于舞台灯光控制马达。2相4线电机,1.8度。最高速必须能达到3.5~4圈每秒。慢速也要极慢,不能丢步。而且因为驱动电流很大(很大力,惯性很大),必须用加减速。用AVRmega168,12M晶体。

我有这样的分析,假如速度要4圈每秒,最大角度12圈,就是12*200=2400步。为了平滑,采用64细分,就是2400*64=153600细分步。
速度方面,4圈每秒,每细分步时间是1/4/200/64=19.5微妙,当他20微妙每步。

问题就在这里,CPU同时处理2个马达,无法完全用细分步来跑(已经用此芯片的快速pwm功能,查表修改定时值)。为了能让他从任意速度变化成任意速度和角度又不丢步,必须有很好的加减速控制。

我曾经试过几个方法都不成功。第一是永远用8细分来跑,结果是勉强合格,但是跑的慢会很卡,不行。第二是永远用64细分控制,速度不够快。
然后是把细分步数,执行次数,定时器时间等分成很多个级别,分级跑,结果是目标位置和速度配合不起来。

在这里想请教高手有什么高见?如何控制加减速,而且步数不能错。

相关帖子

沙发
mugenwon|  楼主 | 2011-5-12 18:42 | 只看该作者
顺便贴一下目前代码。修改了很多次,现时还不行
        //=====================================
        //以下为X马达控制转动
     //=====================================
        //控制跳微步和转区
        if(nowstep_X!=jmubiao_X)                        //要转
        {
                if(mm_X)                                                //不过界模式
            {        if(jmubiao_X>nowstep_X)                        //目标大
                    {
                    if(mad_X)                                         //加减速处理
                    {
                            if(mspeedp_X==0)                //0正向加速
                                            {       
                               
                                ++mstp2_X;                                                        //次数
                                if(mstp2_X>=speedm[mstp_X][0])                //次数超,换行
                            {        ++mstp_X;
                                    mstp2_X=0;
                            }
                            mspeedp_X+=speedm[mstp_X][1];                //速度等级
                                                forword_X();
                                        }
                                        else if(mspeedp_X>0)        //速度为+
                                        {        if(jmubiao_X-nowstep_X>mspeedp_X)        //距离远
                                                {        if(mspeedp_X<MSPEED_MAX)                //正向加速,限速
                                    {       
                                        ++mstp2_X;
                                                if(mstp2_X>=speedm[mstp_X][0])
                                            {        ++mstp_X;
                                                    mstp2_X=0;
                                            }
                                    mspeedp_X+=speedm[mstp_X][1];         
                                }
                                                }
                                            else                                                                //距离近,正向减速
                                            {   mspeedp_X-=speedm[mstp_X][1];               
                                    if(mstp2_X>0)
                                            --mstp2_X;
                                else
                                {        if(mstp_X>0)
                                                --mstp_X;
                                        mstp2_X=speedm[mstp_X][0]-1;
                                }
                                
                                    }
                                            forword_X();
                                                }
                                        else                        //速度为-
                                        {        mspeedp_X+=speedm[mstp_X][1];                //反向减速
                            if(mstp2_X>0)
                                    --mstp2_X;
                            else
                            {        if(mstp_X>0)
                                        --mstp_X;
                                mstp2_X=speedm[mstp_X][0]-1;
                            }  
                                                
                                                backword_X();
                                        }
                    }
                    else
                            forword_X();                                //不加减速直接转      
                }
                else                                                //目标小               
                {       
                    if(mad_X)                                         //加减速处理
                    {       
                    
                            if(mspeedp_X==0                                                        )//反向加速
                                            {       
                                ++mstp2_X;                                                       
                                if(mstp2_X>=speedm[mstp_X][0])               
                            {        ++mstp_X;
                                    mstp2_X=0;
                            }
                            mspeedp_X-=speedm[mstp_X][1];
                                                backword_X();
                                        }
                                        else if(mspeedp_X>0)                                        //正向减速
                                        {        mspeedp_X-=speedm[mstp_X][1];       
                            if(mstp2_X>0)
                                    --mstp2_X;
                            else
                            {        if(mstp_X>0)
                                        --mstp_X;
                                mstp2_X=speedm[mstp_X][0]-1;
                            }
                                   
                                                forword_X();
                                        }
                                        else//速度负
                                        {        if(jmubiao_X-nowstep_X>=mspeedp_X)//距离近,反向减速
                                                {        mspeedp_X+=speedm[mstp_X][1];                       
                                    if(mstp2_X>0)
                                            --mstp2_X;
                                    else
                                    {        if(mstp_X>0)
                                                --mstp_X;
                                        mstp2_X=speedm[mstp_X][0]-1;
                                    }
                                
                                    }
                                            else
                                            {        if(mspeedp_X>-MSPEED_MAX)                                //反向加速,加限速
                                    {   
                                        ++mstp2_X;                                                       
                                                if(mstp2_X>=speedm[mstp_X][0])               
                                            {        ++mstp_X;
                                                    mstp2_X=0;
                                            }
                                    mspeedp_X-=speedm[mstp_X][1];               
                                }
                                            }
                                            backword_X();
                                        }
                    }
                    else
                            backword_X();   
                }
            }
            /*else                                                        //过界模式(这里不处理加减速,不能用在XY马达)
            {        if(jmubiao_X>nowstep_X)               
                    {        if((jmubiao_X-nowstep_X)<(MX_MSTEP/2))        //正转
                        {        forword_X();                             
                    }
                    else                                                                //反转
                    {        backword_X();  
                    }
                }
                else
                {        if((nowstep_X-jmubiao_X)<(MX_MSTEP/2))        //反转
                        {        backword_X();   
                    }
                    else                                                                //正转
                    {        forword_X();
                    }
                }//以上为正反转控制
            }//以上不过界模式
                        */
        }//以上是要转,计算步
        else                //在加减速模式这里还有步控制
        {        if(mm_X)                                                //不过界模式
                {        if(mad_X)                                                         //加减速处理
                {                                            
                    if(mspeedp_X>1)                                                //速度正向减速
                                {        mspeedp_X-=speedm[mstp_X][1];       
                        if(mstp2_X>0)
                            --mstp2_X;
                        else
                        {        if(mstp_X>0)
                                --mstp_X;
                            mstp2_X=speedm[mstp_X][0]-1;
                        }
                               
                                        forword_X();
                                }
                                else if(mspeedp_X<-1)                                //反向减速
                                {        mspeedp_X+=speedm[mstp_X][1];                       
                        if(mstp2_X>0)
                            --mstp2_X;
                        else
                        {        if(mstp_X>0)
                                    --mstp_X;
                            mstp2_X=speedm[mstp_X][0]-1;
                        }
                        
                                        backword_X();
                                }
                                else
                                {        mspeedp_X=0;
                            mstp2_X=0;
                                mstp2_X=0;
                        }
                }
            }

        }

使用特权

评论回复
板凳
受不了了| | 2011-5-12 19:17 | 只看该作者
他们说最好的是5次曲线加加速啥的,我一般都用梯形加减速

使用特权

评论回复
地板
mugenwon|  楼主 | 2011-5-12 19:24 | 只看该作者
不要说什么曲线。按实际情况,不同速度和目标,这条曲线都不同,(不过公式可能相同),但是这样的单片机不可能给你计算复杂的公式。只能查表解决,或者用简单的一次线性方程。

使用特权

评论回复
5
受不了了| | 2011-5-12 19:28 | 只看该作者
那你就用查表发来做个梯形加减速好了,最方便和简单,多做几个表,根据不同负载决定选哪一条曲线。刚搜了,那个它们叫S曲线,什么5阶多项式,我的数学不大好

使用特权

评论回复
6
ajian8172| | 2011-5-12 21:20 | 只看该作者
好难呀  看来还得努力学习

使用特权

评论回复
7
mugenwon|  楼主 | 2011-5-13 10:14 | 只看该作者
本帖最后由 mugenwon 于 2011-5-13 10:34 编辑

貌似今天早上被我解决掉了。:lol在这里也谢谢楼上所有人。也写写总结可能对有需要的人有些帮助。
1,因为cpu是硬件有pwm方式的输出,所以用这个功能,能减轻cpu负担。(刚开始我是用定时器产生pwm波形,cpu速度跟不上,马达力度不够,噪音也大)
2,按道理,应该控制马达的力,例如跑动中力可以小点,加减速力可以加大。但这样做就必须控制pwm波形。这样对程序和cpu要求会太高了。所以用控制速度的办法变相控制力。
3,因为马达当前速度,,当前位置,和目标位置都是随机的,所以加减速曲线是没有统一的线(不过有统一规律,就是公式,但很复杂没想出来)。
4,控制马达速度,就是通过控制每一步的执行时间来定。一步执行时间越长,马达越慢。马达起动和停止就让时间加长,跑动中就减少每步时间。
5,因为舞台灯是一个转动很灵活很顺滑的设备,灯头很笨重,马达速度要够快,又要够稳,这对马达控制提出非常高的要求(曾经做过一台类似打点机的设备控制,根本不需要加减速,直接转动没事,因为负载轻)
6,程序控制马达每步时间,可以通过查表方法。不同速度,对应不同的每步时间。调试时根据实际情况调整表格即可。表格数据越多,马达越顺滑。
7,程序必须能知道当前的位置,目标位置,还有当前速度(速度有正负之分)。在不同时机改变加速度方向。这个逻辑有点复杂
8,必须用细分来驱动否则无比卡。理论上越细分马达越顺滑。但是细分太夸张要保持高速度cpu会不堪重负。所以加减速要用很小的细分,跑动后可以细分粗一点甚至不用细分。这样的处理如果用公式也比较麻烦,所以可以把细分步数合成到表格中查表解决。
9,表格中的数据学问非常大。因为表格是死的,他只能代表一条曲线。之前说过,曲线没有统一的。所以这个表格曲线斜率(时间变化快慢)必须很小才能保证任何时候都不丢不不卡。而且时间必须修改定时器时间,不能用一个定死的定时器时间再累加的方法(这个我试过,不行)。比如说每步增减1%,定时时间太短的话,这1%增减量无法用累加的办法(累加一次就增减50%),所以必须修改定时器时间。
最后程序因为太复杂又长,所以就不贴了;P
另外我觉得查表还不是一个很好的办法,我觉得应该结合物理公式建立一条很简单的公式来处理才是无敌的!搞完这个我再研究看看用什么公式,到时候继续贴上结论。

使用特权

评论回复
8
受不了了| | 2011-5-13 10:47 | 只看该作者
公式,那楼主就去钻研一下5阶多项式,然后拿出来分享一下:lol
脉冲越滑溜,声音越好听,力量也越大

使用特权

评论回复
9
linzf9| | 2011-8-30 16:40 | 只看该作者
1# mugenwon


楼主我现在也在搞步进电机的细分!能否发细分程序函数给我参考参考!万分感激!邮箱:linzf9@163.com

使用特权

评论回复
10
dengm| | 2011-8-30 22:32 | 只看该作者
这类应用应用汇编完成, 速度才能上的了。用硬件DA, 不用pwm

使用特权

评论回复
11
weibestww| | 2011-9-2 20:23 | 只看该作者
步进电机的学问好大,得仔细研究研究,我们刚搞了一个A3987驱动的步进电机,用的就是PWM,效果还可以。

使用特权

评论回复
12
lqfy| | 2013-6-19 15:51 | 只看该作者
楼主能不能发一下关于升降速的程序的部分呢,让我参考参考,是不是c语言写的呢?最近在研究步进电机,谢谢楼主。1178708109@qq.com这是我的邮箱,

使用特权

评论回复
13
yangbing2013| | 2013-9-28 19:19 | 只看该作者
强烈关注

使用特权

评论回复
14
eydj2008| | 2014-9-22 18:41 | 只看该作者
https://bbs.21ic.com/icview-652948-1-1.html
步进电机 控制程序 这里有呀

使用特权

评论回复
15
腾腾| | 2014-9-22 22:11 | 只看该作者
分享下好东东。
里面有STM32步进电机程序的详细分析。

stm32f10x_an2820_fw.chm

675.52 KB

使用特权

评论回复
16
赤那| | 2015-6-17 15:36 | 只看该作者
可不可以将步进电机相关的代码,发我邮箱1120310049@zust.edu.cn,学生党,我想结合代码,在学习一下理论的东西。玩一下步进电机

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

96

主题

430

帖子

3

粉丝