[经验] 步进电机S曲线加减速算法设计

[复制链接]

技术员

发表于 2017-12-4 23:31:40   314 查看 2 回复 显示全部楼层 倒序浏览
分享
最近在做步进电机的控制,在步进电机的控制中,步进电机的加减速控制时比较难的一方面。搜索了一些关于步进电机的加减速控制的论文,其中都有提到S曲线的加减速控制时最理想的控制方案,但是在控制的过程比较复杂,如何确定S曲线的加减速公式,到目前为止仍然不是特别明确,最后只得按照一篇文章中的介绍,依葫芦画瓢,高兴的是,画的瓢还挺像那么回事。首先感谢作者的无私奉献。
在此文章的末尾评论区中,有人问到如果用51[color=rgb(68, 68, 68) !important]单片机控制,应该做什么样的修改,而我正是用的51单片机,所以就按照他的例程改为了51单片的样子,同样使用定时产生脉冲信号,从而控制步进电机做相应的运动。以下是我修改之后的程序,如有不妥之处还请大神指正。
//FreCurrent=FreStart+(FreStop-FreStart)/(1+exp((-Flrxible)*(i-Length)/Length))--//加速曲线公式
void CalculateSModelLine(float Length,float FreStop,float FreStart,float Flexible)
{
uint  Period=0;                                            
float deno;
float melo;                                                               
float delt;                                                      
float FreCurrent=0;
             delt = FreStop-FreStart;
             melo = Flexible*(j-Length/2)/(Length/2);
             deno = 1.0/(1+exp(-melo));
                            FreCurrent = delt * deno + FreStart;
                            Period=(unsigned int)(12000000.0 / FreCurrent);
                                      
                                      TH0=(65535-Period)/256;
                                      TL0=(65535-Period)%256;
         一开始我跟原文中一样,一开始直接定义了unsigned int Period[1000],float  FreCurrent[1000],两个数组,编译结果提示如下错误error C249: 'DATA': SEGMENT TOO LARGE;经过查阅,发现需要修改Target选项下的Memory Model下的值为Large:variables in XDATA,再次编译果然通过,紧接着,开始直接用Keil[color=rgb(68, 68, 68) !important]仿真调试,运行查看数组中的值一切OK,下载至51单片机系统中,运行系统,却发现怎么弄都不正常,通过串口打印这两个数组的值,结果也跟仿真调试结果大相径庭。我想很多初学者肯定跟我一样懵逼,这是什么原因造成的呢,于是回头去看[color=rgb(68, 68, 68) !important]芯片数据手册(STC12C5A60S2)发现XDATA区总共就1280B很明显,定义的数组已经超过了范围,又因为这两个数组的值是需要根据实际情况随时改变的,所有肯定无法用CODE定到程序存储区。当然还有办法就是扩展RAM区,但是这无形就增加了硬件成本。所以采用了上述方法,用的时候再计算,计算完之后再使用,这样就不需要单独开辟一个大的数据存储区。通过此案例,也理解了data,Idata,bdata,xdata,code 这些关键字在C51系统中的区别。
此处只是一个加速曲线的实现,减速曲线与之对称就可以了,后面的文章中再考虑如何实现整体的一段移动距离的实现过程。
===========================此处是分割线==========================
=======下面的内容是我参考的文章,再次感谢作者的无私奉献===========
一年前做过的S型曲线加减速算法,再次做的时候竟然犯错,在此总结记录一下,方便以后查阅,同时希望帮助初学者提供简单的参考资料(注:本项目采用的带细分的驱动器,MCU的OC比较输出模块产生50%的PWM方波)。
S型曲线的的方程,在[-5,5]的图形如下图所示:
如要将此曲线应用在步进电机的加、减速过程中,需要将方程在XY坐标系进行平移,同时对曲线进行拉升变化:
其中的A分量在y方向进行平移,B分量在y方向进行拉伸,ax+b分量在x方向进行平移和拉伸。
项目中加速过程:从5600Hz加速到64000Hz,采用4细分。输出比较模块所用的定时器驱动频率为10M,采用1000个点进行加速处理。最终根据项目的需要,在加速过程中采用的曲线方程为:
其中的Fcurrent为length(1000)个点中的单个频率值。Fmin起始频率为5600; Fmax为最大频率64000;  -flexible*(i - num)/num是对S型曲线进行拉伸变化,其中flexible代表S曲线区间(越大代表压缩的最厉害,中间(x坐标0点周围)加速度越大;越小越接近匀加速。理想的S曲线的取值为4-6),i是在循环计算过程中的索引,从0开始,num为 length/2 大小(这样可以使得S曲线对称)。在项目中i的区间[0,1000), num=1000/2=500。这些参数均可以修改。提供的计算接口如下。
对应的计算接口code:
/*  calculate the Period and Freq array value, fill the Period value into the Period register during the [color=rgb(68, 68, 68) !important]timer interrupt.
*calculate the acceleration procedure , a totally 1000 elements array.
* parameter    fre[]: point to the array that keeps the freq value.
*   period[]: point to the array that keeps the timer period value.
*   len: the procedure of acceleration length.it is best thing to set the float number, some compile software maybe transfer error if set it as a int
*   fre_max: maximum speed, frequency vale.
*   fre_min: start minimum speed, frequency vale.  mind : 10000000/65535 = 152, so fre_min can't less than 152.
*   flexible:  flexible value. adjust the S curves
*/
void CalculateSModelLine(float fre[],  unsigned short period[],   float  len,  float fre_max,  float fre_min, float flexible)
{
    int i=0;
    float deno ;
    float melo ;
    float delt = fre_max-fre_min;
    for(; i<len; i++)
    {
        melo = flexible * (i-len/2) / (len/2);
        deno = 1.0 / (1 + expf(-melo));   //expf is a library function of exponential(e)
        fre = delt * deno + fre_min;
        period = (unsigned short)(10000000.0 / fre);    // 10000000 is the timer driver frequency
    }


    return ;
}
// start move motor
void StartPWM()
{
    DriverMotorFlag = TRUE;
    Index = 0;
   
    MOTOR_EN_DISABLE = ENABLE;
    OpenOC4(OC_ON | OC_TIMER_MODE16 | OC_TIMER3_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);

    // map rc13 to oc4 output
    RPC13R = 11;


    // 50 percent duty
    OC4RS = OC_PERIOD_MIN / 2;
    OpenTimer3(T3_ON | T3_PS_1_8, OC_PERIOD_MIN);


    INTSetVectorPriority(INT_TIMER_3_VECTOR, INT_PRIORITY_LEVEL_6);
    INTSetVectorSubPriority(INT_TIMER_3_VECTOR, INT_SUB_PRIORITY_LEVEL_1);
    EnableIntT3;
}
//stop motor, hereis no deceleration
void StopPWM()
{
    DriverMotorFlag = FALSE;
    Index = 0;
   
    MOTOR_EN_DISABLE = DISENABLE;
    OpenOC4(OC_OFF | OC_TIMER_MODE16 | OC_TIMER3_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);
    // map rc13 to oc4 output
    RPC13R = 0;
    PORTCbits.RC13 = 0;
   
    CloseTimer3();
    DisableIntT3;
}
//change the timer Period value in the correspond timer rather than the other place, Or the motor will be stalled occasionally.
// 刚开始我在另外的一个定时器中断中每隔1ms改变 应用在OC模块的timer3 的Period值,结构偶发的造成电机在加速过程中堵转。其实应该是在timer3的中断中修改。
static unsigned short CountForAcc = 0;
void __ISR(_TIMER_3_VECTOR, ipl6) Timer3OutHandler(void)
{
    // clear the interrupt flag, or the interrupt will not occur again.
    mT3ClearIntFlag();

    if(CountForAcc++ > 2)    // here can adjust the totally time of acceleration
    {
        CountForAcc = 0;
        //if(DriverMotorFlag == TRUE && PR3 > OC_PERIOD_MAX + SPEED_STEP)
        if(DriverMotorFlag == TRUE && Index < ACC_TIMES)
        {
            PR3 = Period[Index++];
            OC4RS = PR3 / 2;
        }
    }
}
通过CalculateSModelLine接口得到如下不同的几条加速曲线:
黄色:CalculateSModelLine(Freq, Period, 1000, 56000, 16000, 4);
橙色:CalculateSModelLine(Freq, Period, 1000, 64000, 500, 8);
蓝色:CalculateSModelLine(Freq, Period, 1000, 64000, 500, 15);
灰色:CalculateSModelLine(Freq, Period, 1000, 40000, 500, 5);
最后可以估算加速过程的时间和角位移,以橙色曲线为例:CalculateSModelLine(Freq, Period, 1000, 64000, 500, 8)为例(假设在中断中没有  if(CountForAcc++ > 2)  条件限制):
时间:Period第一个点的值为10000000/500 = 20000,最后也点的值 10000000/64000=156,平均值为10000左右,timer中断的平均时间Tn=10000/10000000=1ms, 1000个点,总时间为1s,当然,起始频率大加速时间就越短,比如Fmin=16000Hz,Fmax=64000,则40ms左右即可完成加速过程。
角位移:1.8(单步) * 1000(步数) / 4(细分)= 450°
上述为加速过程,减速同样的道理,只要将方程改为:
可以得到减速曲线如下所示:
以上为实际的项目数据,欢迎各位指正。

标签:步进电机 单片机 S曲线加速 XDATA DATA

高级工程师

发表于 2017-12-5 11:44:18  
不错,外瑞顾得!!1!!!!!!!
回复

点赞 举报

总工程师

发表于 2017-12-5 19:40:45  

PCB在线计价下单

板子大小:

cm
X
cm

层数:

2

板子数量:

10

厚度:

1.6
学习一下,毕竟用的不多
回复

点赞 举报

高级模式
您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐 上一条 /9 下一条

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

推荐专区

技术干货集中营

专家问答

用户帮助┃咨询与建议┃版主议事

工程师杂谈

工程师创意

工程师职场

论坛电子赛事

社区活动专版

发烧友活动

-

嵌入式论坛

ARM技术论坛

Android论坛

Linux论坛

单片机/MCU论坛

FPGA|CPLD|ASIC论坛

DSP论坛

嵌入式系统论坛

-

电源技术论坛

电源技术论坛

无线充电技术

-

硬件设计论坛

PCB设计论坛

电路设计论坛

电子元器件论坛

控制|传感

总线技术|接口技术

-

测试测量论坛

LabVIEW论坛

Matlab论坛

测试测量技术专区

仪器仪表技术专区

-

EDA设计论坛

multisim论坛

PADS技术论坛

Protel|AD|DXP论坛

Allegro论坛

proteus论坛|仿真论坛

EasyEDA-中国人自已的EDA工具

Orcad论坛

-

综合技术与应用

电机控制

智能电网

光电及显示

参考设计中心

汽车电子技术论坛

医疗电子论坛

-

开源硬件

-

无线通信论坛

无线通信技术专区

天线|RF射频|微波|雷达技术

-

IC设计论坛

芯片测试与失效分析

Mixed Signal/SOC[数模混合芯片设计]

Analog/RF IC设计

设计与制造封装测试

-

厂商专区

TI论坛

TI Deyisupport社区

-

检测技术与质量

电磁兼容(EMC)设计与整改

安规知识论坛

检测与认证

-

消费电子论坛

手机技术论坛

平板电脑/mid论坛

音视/视频/机顶盒论坛

-

电子论坛综合区

聚丰众筹官方社区

新人报道区

聚丰供应链

-

论坛服务区

-

供求信息发布

供需广告

招聘┃求职发布区

电子展览展会专区