数字积分法DDA(实时步进电机梯形+S形加减速)实现方法

在一般的单片机,或者STM32 ,如何才能实现实时的步进电机加减速脉冲输出呢?通过在网络上各种搜索学习,真正有实用价值的资料并不多,大多只是原理,然后是无限的公式公式公式。。。对于只有小学文化程度的我看得头都大了,看到了DDA插补的方式,只用到整数,通过加法积分,溢出就可以多轴直线插补,圆弧插补了,哪么DDA积分法能否实现加减速呢?在万能的网络上根本没有答案

然后翻出了女儿高中的物理书本学习研究速度相关的知识,得到的结论是

答案是肯定的

通过速度物理相关的知识,写了一个循环模拟定时器,循环执行了多次积分累加,验证确实是可以实现出来,要先通过移动速度,加速度,计算出速度因子,加速度积分因子,在每次循环累加只要溢出就输出一个脉冲,通过累加次数的不同而溢出产生的脉冲,等同于产生了不同频率,比如最大频率为100KHZ,哪么最大速度时每周期就是10微秒了,此时速度为100HZ的话,对应的周期时间为0.01秒,如果在一个定时器频率为100KH的中断里,要产生100HZ的频率,也就是0.01/0.00001=1000次累加,输出一个脉冲,不同的频率在这个100KHZ定时器中断时,以不同的累加次数产生即可

先拿几项参数来说明一下如何实现,速度30mm/s,加速度100mm/s,都以秒为单位,这里不提及角速度这样的单位,因为转换过来后是完全哪么一回事!反正怎么简单怎么来,也好理解,因为全后面全都转换为(步)作为单位,时间为(秒),每移动1mm对应的步数为640步,

step_mm = 640;

v_step =30*640;

a_step=100*640;

所以单位转换为步

v_step =19200;

a_step=64000;

首先计算出加速度所要的时间A_T=v_step/a_step=19200/64000=0.3秒

求出加速度所要的步数,通过面积公式s=v*t,由于加速度是一个斜坡,等同于一个三角形面积,即正方形面积的一半,所以公式为s=v*t*0.5 or s=v*v/a*0.5

A_S=v_step*A_T*0.5=19200*0.3*0.5=2880步

Timer_freq=100000; 定时器频率100KHZ,对的是固定频率,当然单片机性能高的还可以设定更高的频率

求出加速移动2880步所要的定时器次数,A_HZ=A_T*Timer_freq=0.3*100000=30000

积分因子使用32位整数

求出最大速度因子

Vmax_factor=0xFFFFFFFF*v_step/Timer_freq;

加速度因子

A_factor=Vmax_factor/A_HZ;

以上为计算这些参数的方法,然后接着看如何实现加速

整个加速过程所以要时间为0.3秒,对应定时器的频率100KHZ,要在定时器中断里中断30000次,每中断一次,累加器都与积分因子累加一次,累加器每溢出一次,输出一个脉冲,要使用到两个累加器,一个为速度累加器,一个为加速累加器

如下为一个循环执行的代码,循环30000次,模拟100KHZ定时器中断,即每循环一次理解为10微秒,实际要实现的代码是放定时器中断函数里执行的,现在只是意思意思,好理解和明白,实际上这方法超级简单,就是线性增量速度,把最大速度微分成30000份,再累积起来,这实际上与v=0.3*a是相关联的,因为累加次数等同于时间,即速度与时间和加速度的三者的关系

注:代码哪些数值都是按照前面所说的计算所得,要完整实用还是得要全补上计算的,由于只作验证测试用,所以代码里数值都直接写上了的,不要问这些数值怎么来了

void ACC()

{

    int v_step =19200;

    int a_step=64000;

    int A_S=2880;

    int Timer_freq=100000;

    int A_HZ=30000;

    UINT32 Vmax_factor=(UINT32)(0xFFFFFFFF*(double)(v_step/Timer_freq));

    UINT32 A_factor=Vmax_factor/A_HZ;


    UINT32 v_accumulator=0;
    UINT32 tmp=0;
    UINT32 v_factor_accumulator=A_factor;
    int move=0;

    for(int i=0;i<int A_HZ;i++)
    {
        tmp = v_accumulator;
        v_accumulator += v_factor_accumulator; //积分
        if(v_accumulator < tmp) //如果溢出
            {
                move++; //输出脉冲
            }
        if(v_factor_accumulator<Vmax_factor) //加速
            v_factor_accumulator += A_factor;  //加速积分

        if(v_factor_accumulator>=Vmax_factor) //判断是否进入恒速度
            v_factor_accumulator = Vmax_factor; 
    }
}

以上代码只是演示了0.3秒的加速过程,即30000次定时器中断,此时v_factor_accumulator的值刚好等于Vmax_factor的值 ,即达到最大速度,验证时可以跟踪代码,在输出脉冲位置加断点,每中断一次,观察(i)的次数,是不是会慢慢的比上一次的减少了,这就是速度的变化了,另外刚好30000次完成时,move的值就是2880步,这样验证了0.3秒加速移动了2880步的距离,整个加速度过程是与加速度速度和时间的公式完全符合的,如果超过30000次后还要继续执行下去就是恒速段了,减速这里没有实现,实际 要根据移动距离的总步数,加速度所要的步数,减速所要的步数来判断什么时候加速完成进入恒速,什么时候从恒速进入减速,移动距离的步数是否能达到最大速度,达不到最大速度就要减速,另外多轴联动插补输出等等。。。。

多轴联动插补,其实就是按空间矢量的路径速度,求出各轴的速度和加速度,(对于空间矢量和各轴实际的速度和加速度,我另一文章里有详细讲解),把各轴的几个因子计算出来,写成这样的对应各轴的代码就行了

如果放到定时器中断里:

void TIM3_IRQHandler(void)//100KHZ
{
    if(A_S>0){
        tmp = v_accumulator;
        v_accumulator += v_factor_accumulator; //积分
        if(v_accumulator < tmp) //如果溢出
            {
                move++; //输出脉冲
                A_S--;
            }
        if(v_factor_accumulator<Vmax_factor) //加速
            v_factor_accumulator += A_factor;  

        if(v_factor_accumulator>=Vmax_factor) //判断是否进入恒速度
            v_factor_accumulator = Vmax_factor; 
    }
}

从恒速度减速下来,其实就是v_factor_accumulator-=A_factor;具体实现还要相应的速度段判断

现在v_factor_accumulator的是以线性增量的,如果是以S形增量变化,哪就是S形的加速度斜坡了,原理实际上就变化的加速度值,但由于个人能力问题,尝试了许多种以DDA的方式,也无法以S形的方式准确的在相就的时间内移动相应的步数,即不准确,但加速度的S形是可以弄出来了,原因应该是加加速度时和减加速度时没弄准确,然后实际在相关的时间内移动步数和速度上都不能准确对应上,无法几者都与速度物理公式符合,反正现在是想不出来能准确实现的,要有能实现出S形DDA方式变化增量的通知一下哦!

另外最好使用32位数作为累加值,即以0xFFFFFFFF作为最大的溢出值,因为数值越大,等于把浮点数放大,会更精确

此方法没有复杂的计算过程,在中断里也就加加减减,也没有浮点运算,对于MCU的开销非常的小,通过几个参数就可以实时的加减速的脉冲输出了,其实某些FPGA的运动控制卡,也是DDA实现的,脉冲频率可以高达4M,对于FPGA也只是看过了一下介绍,本人也不懂

实际应用,还要有初速度因子,结束速度因子,因为G64连续模式里,有前瞻处理,会有进初速度,恒速度,结束速度(即下一路径的进入速度)

把输出脉冲按4毫秒采样写到一数组里,用电子表格显示加速度斜坡,以验证结果吧!

void ACC()

{

    int v_step =19200;

    int a_step=64000;

    int A_S=2880;

    int Timer_freq=100000;

    int A_HZ=30000;

    UINT32 Vmax_factor=(UINT32)(0xFFFFFFFF*(double)(v_step/Timer_freq));

    UINT32 A_factor=Vmax_factor/A_HZ;


    UINT32 v_accumulator=0;
    UINT32 tmp=0;
    UINT32 v_factor_accumulator=A_factor;
    //int move=0;
    int out[75]={0};
    for(int n=0;n<75;n++)
    {
        for(int i=0;i<400;i++)
        {
            tmp = v_accumulator;
            v_accumulator += v_factor_accumulator; //积分
            if(v_accumulator < tmp) //如果溢出
            {
                out[n] +=1; //输出脉冲
            }
            if(v_factor_accumulator<Vmax_factor) //加速
                v_factor_accumulator += A_factor;  //加速积分

            if(v_factor_accumulator>=Vmax_factor) //判断是否进入恒速度
                v_factor_accumulator = Vmax_factor; 
        }

    }
}

然后把out的数据导入到Excel中以图形显示

上图就是0.3秒,按4毫秒采样为75组的加速度斜坡的图形化显示结果了,每组4毫秒的步数除0.004得到频率值来显示的 

然后还是把研究出来的DDA不太准确的S形曲线也分享出来吧,因为把变化加速度弄进去后,由于细分值太小了,所以无法准确,现在只能使用了浮点数才能准确移动2880步,但在1/2时间的速度还是不准确的,S分了两段处理,一段加加速度变化,一段为减加速度变化

判断分段 if(move==(A_HZ*0.5))acc_dt = -acc_dt; 把加加因子变为负值,即为减加因子

加加速度因子是实际上按最大速度因子的两倍速度微分成30000份后,再微分15000份,原理是按照加速度的斜率所求得的,具体公式可以参照

13. 步进电机S形加减速实现 — [野火]电机应用开发实战指南—基于STM32 文档 (embedfire.com)

代码如下:

void ACC()

{

    int v_step =19200;

    int a_step=64000;

    int A_S=2880;

    int Timer_freq=100000;

    int A_HZ=30000;

    UINT32 Vmax_factor=(UINT32)(0xFFFFFFFF*(double)(v_step/Timer_freq));

    //这方法,这两个因子因为数值微分得太小了,只能使用浮点型数据,要不偏差太大
    double acc_dt=2.0*(double)Vmax_factor/A_HZ/(A_HZ*0.5); //《加加速度积分因子》
    double A_factor=acc_dt;


    UINT32 v_accumulator=0;
    UINT32 tmp=0;
    UINT32 v_factor_accumulator=A_factor;
    int move=0;
    int out[75]={0};
    for(int n=0;n<75;n++)
    {
        for(int i=0;i<400;i++)
        {
            ++move;//移动所花时间的计数
            tmp = v_accumulator;
            v_accumulator += v_factor_accumulator; //积分
            if(v_accumulator < tmp) //如果溢出
            {
                out[n] +=1; //输出脉冲
                
            }
            
            A_factor+=acc_dt; //《加加速度》增量
            

            if(v_factor_accumulator<Vmax_factor) //加速
                v_factor_accumulator += A_factor;  //加速积分

            if(v_factor_accumulator>=Vmax_factor) //判断是否进入恒速度
                v_factor_accumulator = Vmax_factor; 

            if(move==(A_HZ*0.5))acc_dt = -acc_dt; //加速到0.15秒时切换为《减加速度》
        }

    }
}

然后把out的数据导入到Excel中以图形显示,S形加速度斜坡

现在输出的总步数也是刚好2880步的,但实际上还是不准确,速度累加器本身是整数型的,它的数足够大,所以还是能保证了总移动的步数为2880步,但在每个速度的变化实际上还是存在偏差的,比如执行15000次位置下断点,输出的步数 461步,按公式计算此时应该是输出480步才是正确的,要怎么解决,就得处理加加速度的微分值,不能太小,不能使用浮点类型数,但现在这办法也只能这么小,反正暂时想不到更好的解决办法

本人的水平真的太有限了,说真的我真的只有小学文化,当初也就读到初二没再上学了,这些东西能研究出来,也是因为喜欢,也因为有万能的网络可以搜索各种知识学习,有能力的大神们,如果能把S形弄得非常的准确,而且也是整数型积分的方法,记得回来留言通知一下啊

通过调试,把每输出一步的累加次数计算出每步的频率后发现这S形加速是错误的,它还是以线性加速,这应该是错误的马速度增量想成是加速度增量,而且按时间分段采样后变成了像是S形变化的曲线,所以暂时不研究它了,线性斜坡这种方法也是存在问题,就是增量值由于微分的分数过多,小数部分就构成了误差,速度累加起来后,在实际的时间对应的速度却产生了偏差,后续看有没有办法改良,留着下了文章再说了。。。。。。。。。。。。。

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA梯形减速是一种通过FPGA实现步进电机控制方法。在这种方法中,通过调整脉冲频率来实现步进电机的加减速控制。根据引用\[1\]中的描述,FPGA的运动控制卡可以使用DDA(Digital Differential Analyzer)算法实现脉冲输出。这种方法的优点是计算过程简单,没有浮点运算,对于MCU的开销非常小。 然而,引用\[2\]中提到的S形加速是错误的,实际上是线性加速。这可能是因为将速度增量误认为是加速度增量,并且在时间分段采样后产生了类似S形变化的曲线。另外,线性斜坡方法也存在问题,增量值的微分分数过多会导致小数部分误差,从而在实际时间对应的速度上产生偏差。 对于步进电机的控制,引用\[3\]中提到了空载启动频率和有负载情况下的启动频率。空载启动频率是指步进电机在空载情况下能够正常启动的脉冲频率。如果脉冲频率高于该值,电机可能会发生丢步或堵转。在有负载的情况下,启动频率应更低。如果要使电机达到高速转动,脉冲频率应该有加速过程,即启动频率较低,然后按一定加速度升到所希望的高频。 综上所述,FPGA梯形减速是一种通过调整脉冲频率来实现步进电机减速控制的方法。然而,需要注意的是在实际应用中可能存在一些问题,如S形加速误差和线性斜坡方法的误差累积。同时,根据步进电机的负载情况和所需转速,需要选择适当的启动频率和加速过程。 #### 引用[.reference_title] - *1* *2* [数字积分法DDA实时步进电机梯形+S形加减速实现方法](https://blog.csdn.net/dbxzjq/article/details/130022758)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [FPGA学习笔记(5)——步进电机梯形减速算法](https://blog.csdn.net/step__forward/article/details/124715218)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值