搜索
bottom↓
回复: 26

S曲线公式到步进加速过程推导

  [复制链接]

出0入0汤圆

发表于 2019-2-24 16:17:32 | 显示全部楼层 |阅读模式
最近在搞步进电机控制,加减速度控制是必须的。
我的要求是,给出起始速度,最大速度,加速时间,加速阶段脉冲数4个参数后能自动计算出每个脉冲点的速度
S曲线因为加速度不突变而普遍采用,我选用的S曲线公式为Y = K/(1+EXP(A-BX)),加速度连续的公式应该都可以。

把K定义为最大速度Vm,X定义为时间t,Y即为计算出的速度。
t=0, 起始速度V0 = Vm/(1+EXP(A))  计算出 A = ln((Vm-V0)/VO)   (1)

加速时间定义为Ta,加速时间的一半定义为Th,定义t= Th时,Y = Vm/2 则有
Vm/2 = Vm/(1+EXP(A-Bt))  计算出 B = A/t  (2)

根据公式(1),(2)就可以计算实际速度了。

具体计算每个脉冲点的速度时,就把公式离散化就行了。
比如 加速阶段的时间为100ms, 分100个脉冲完成。那就每隔1ms带入计算就行了。
每点的速度知道了,具体到计算定时器重装周期就根据自己的情况去算吧。

出0入0汤圆

 楼主| 发表于 2019-2-24 16:25:07 | 显示全部楼层
我定义的是加速过程一半时的速度为最大速度的一半来计算参数B的,这样加加速和减加速是对称的,也可以在定义在其它点来计算

出100入101汤圆

发表于 2019-2-24 17:31:46 | 显示全部楼层
坐等大神继续讲课

出0入0汤圆

发表于 2019-2-24 20:37:05 | 显示全部楼层
坐等大神继续讲课+

出0入0汤圆

发表于 2019-2-24 22:18:03 | 显示全部楼层
我也分享一个之前做的S加减速曲线计算方法


  1. /*
  2. 主计算函数
  3. 本来想做成一个通用的函数,但是目前手上的项目需求很明确,时间也不多,所以临时做了个版本
  4. 该函数并不具有通用性,几个参数考虑的重要程度不一样,会有不同的取舍,我是按下面这几条思想做的,供大家参考,有发现不合理的地方请大家指正
  5. 计算中优先考虑的是运动距离必须跟用户设定的保持一致
  6. 另外四个变加速过程的捷度被认为是受动力源和机械结构限制,所以也保持跟用户设定一致,不能修改
  7. 其他参数在计算过程中发现逻辑冲突的,会优先考虑修改最大加减速
  8. 加减速参数满足条件但用户设定行程比较短,会考虑使用一个比用户设定速度更小的参数计算,直到满足要求
  9. */
  10. void MainWindow::Update(bool isV, bool isSave, bool PorV)
  11. {
  12.     /*计算结果缓存,笨办法开两个比较大的数组*/
  13.     QVector<double> x(1024*1024),v(1024*1024),s(1024*1024);

  14.     ui->txLog->clear();

  15.     /*读取用户设定参数*/
  16.     TimeStep = ui->nTimeStep->text().toDouble() * 0.000001; //s
  17.     Smax = ui->nS->text().toDouble();
  18.     Vmax = ui->nVmax->text().toDouble();
  19.     ACCmax = ui->nACCmax->text().toDouble();
  20.     DCCmax = ui->nDCCmax->text().toDouble();
  21.     J1 = ui->nJ1->text().toDouble();
  22.     J2 = ui->nJ2->text().toDouble();
  23.     J3 = ui->nJ3->text().toDouble();
  24.     J4 = ui->nJ4->text().toDouble();

  25.     int xcount = 0;

  26.     ui->txLog->append("Calculate begin.");
  27.     ui->txLog->append("----");
  28.    
  29.     double S1,S2,S3,S4,S5,S6,S7;
  30.     double V1,V2,V3,V4;
  31.     int PlotPointer = 0;
  32.     bool fFirst = true;
  33.     bool fS4Neg = false;
  34.     do
  35.     {
  36.         /*判断用户设定的捷度加减速度和最大速度能不能使各段曲线衔接上*/
  37.         V1 = (ACCmax*ACCmax)/(2*J1);
  38.         V2 = Vmax - (ACCmax*ACCmax)/(2*J2);
  39.         V3 = Vmax - (DCCmax*DCCmax)/(2*J3);
  40.         V4 = (DCCmax*DCCmax)/(2*J4);
  41.         if(fFirst)
  42.         {
  43.             ui->txLog->append("Velocity at end of S1 (V1): "+QString::number(V1, 10, 8));
  44.             ui->txLog->append("Velocity at begin of S3 (V2): "+QString::number(V2, 10, 8));
  45.             ui->txLog->append("Velocity at end of S5 (V3): :"+QString::number(V3, 10, 8));
  46.             ui->txLog->append("Velocity at begin of S7 (V4): "+QString::number(V4, 10, 8));
  47.         }
  48.         if(V2<V1)//加速度出现曲线冲突,修改最大加速度
  49.         {
  50.             ACCmax = sqrt((2*J1*J2*Vmax)/(J1+J2));
  51.             ui->nACCmax->setText(QString::number(ACCmax, 10, 8));
  52.             V1 = (ACCmax*ACCmax)/(2*J1);
  53.             V2 = Vmax - (ACCmax*ACCmax)/(2*J2);
  54.             if(fFirst)
  55.             {
  56.                 ui->txLog->append("----");
  57.                 ui->txLog->append("[-ERROR-]: V2 < V1, try to set a smaller ACCmax.");
  58.                 ui->txLog->append("First try V2 = V1, ACCmax = sqrt((2*J1*J2*Vmax)/(J1+J2)) = "+QString::number(ACCmax, 10, 8)+".");
  59.                 ui->txLog->append("Velocity at end of S1 (V1): "+QString::number(V1, 10, 8));
  60.                 ui->txLog->append("Velocity at begin of S3 (V2): "+QString::number(V2, 10, 8));
  61.             }
  62.         }
  63.         if(V3<V4)//减速段出现曲线冲突,修改最大减速度
  64.         {
  65.             DCCmax = sqrt((2*J3*J4*Vmax)/(J3+J4));
  66.             ui->nDCCmax->setText(QString::number(DCCmax, 10, 8));
  67.             V3 = Vmax - (DCCmax*DCCmax)/(2*J3);
  68.             V4 = (DCCmax*DCCmax)/(2*J4);
  69.             if(fFirst)
  70.             {
  71.                 ui->txLog->append("----");
  72.                 ui->txLog->append("[-ERROR-]: V3 < V4, try to set a smaller DCCmax.");
  73.                 ui->txLog->append("First try V3 = V4, DCCmax = sqrt((2*J3*J4*Vmax)/(J3+J4)) = "+QString::number(DCCmax, 10, 8)+".");
  74.                 ui->txLog->append("Velocity at end of S5 (V3): "+QString::number(V3, 10, 8));
  75.                 ui->txLog->append("Velocity at begin of S7 (V4): "+QString::number(V4, 10, 8));
  76.             }
  77.         }

  78.         /*计算七段运动距离,判断是否符合用户设定的运动距离*/
  79.         S1 = (ACCmax*ACCmax*ACCmax)/(6*J1*J1);
  80.         S2 = (V2*V2 - V1*V1)/(2*ACCmax);
  81.         S3 = Vmax*ACCmax/J2 - (ACCmax*ACCmax*ACCmax)/(6*J2*J2);

  82.         S5 = Vmax*DCCmax/J3 - (DCCmax*DCCmax*DCCmax)/(6*J3*J3);
  83.         S6 = (V3*V3 - V4*V4)/(2*DCCmax);
  84.         S7 = (DCCmax*DCCmax*DCCmax)/(6*J4*J4);

  85.         S4 = Smax - (S1+S2+S3+S5+S6+S7);
  86.         /*第四段位移为负,说明加减速段位移太长,考虑减少最大速度使加减速段时间缩短,行程缩短*/
  87.         if(S4 < 0)
  88.         {
  89.             fS4Neg = true;
  90.             Vmax -=0.001;
  91.         }
  92.         fFirst = false;
  93.     }while(S4 < 0);

  94.     /*输出最终参与计算的运动参数*/
  95.     ui->nVmax->setText(QString::number(Vmax, 10, 8));
  96.     if(fS4Neg)
  97.     {
  98.         ui->txLog->append("----");
  99.         ui->txLog->append("[-ERROR-]: Smax too small, try smaller Vmax = "+QString::number(Vmax, 10, 8));
  100.         ui->txLog->append("Recalc with new Smax.");

  101.         ui->txLog->append("ACCmax  = "+QString::number(ACCmax, 10, 8)+".");
  102.         ui->txLog->append("Velocity at end of S1 (V1): "+QString::number(V1, 10, 8));
  103.         ui->txLog->append("Velocity at begin of S3 (V2): "+QString::number(V2, 10, 8));
  104.         ui->txLog->append("DCCmax  = "+QString::number(DCCmax, 10, 8)+".");
  105.         ui->txLog->append("Velocity at end of S5 (V3): "+QString::number(V3, 10, 8));
  106.         ui->txLog->append("Velocity at begin of S7 (V4): "+QString::number(V4, 10, 8));
  107.     }
  108.     ui->txLog->append("----");
  109.     ui->txLog->append("Fianl S1~S7 : "+QString::number(S1, 10, 8)+", "+QString::number(S2, 10, 8)
  110.               +", "+QString::number(S3, 10, 8)+", "+QString::number(S4, 10, 8)
  111.               +", "+QString::number(S5, 10, 8)+", "+QString::number(S6, 10, 8)+", "+QString::number(S7, 10, 8));

  112.     /*计算各段时间*/
  113.     double T1,T2,T3,T4,T5,T6,T7;
  114.     T1 = ACCmax/J1;
  115.     T2 = (V2-V1)/ACCmax;
  116.     T3 = ACCmax/J2;
  117.     T4 = S4/Vmax;
  118.     T5 = DCCmax/J3;
  119.     T6 = (V3-V4)/DCCmax;
  120.     T7 = DCCmax/J4;
  121.     ui->txLog->append("Fianl T1~T7 : "+QString::number(T1, 10, 8)+", "+QString::number(T2, 10, 8)
  122.               +", "+QString::number(T3, 10, 8)+", "+QString::number(T4, 10, 8)
  123.               +", "+QString::number(T5, 10, 8)+", "+QString::number(T6, 10, 8)+", "+QString::number(T7, 10, 8));


  124.     double AllCount = T1+T2+T3+T4+T5+T6+T7;
  125.     if((AllCount/TimeStep)>1024*1024)
  126.     {
  127.         ui->txLog->append("----");
  128.         ui->txLog->append("Data count exceed max buffer limit, please set a bigger TimeStep.");
  129.         return;
  130.     }

  131.     int TempCount = 0;
  132.     double TempTime = 0.0;

  133.     double Astart = 0.0;
  134.     double Vstart = 0.0;
  135.     double Sstart = 0.0;

  136.     /*分七段生成位移曲线和速度曲线*/
  137.     while(Sstart < Smax)
  138.     {
  139.         //加加速 S=(J*T^3)/6  V=(J*T^2)/2
  140.         if(TempTime <= T1)
  141.         {
  142.             Sstart = J1*TempTime*TempTime*TempTime/6.0;
  143.             Vstart = 0.5*J1*TempTime*TempTime;
  144.         }
  145.         //匀加速   S=V0*T+(A*T^2)/2  V=V0+A*T
  146.         else if(TempTime <= T1+T2)
  147.         {
  148.             Sstart = S1 + V1*(TempTime-T1) + 0.5*ACCmax*(TempTime-T1)*(TempTime-T1);
  149.             Vstart = V1 + ACCmax*(TempTime-T1);
  150.         }
  151.         //减加速 曲线公式参考加加速段,需要做一点变换
  152.         else if(TempTime <= T1+T2+T3)
  153.         {
  154.             Sstart = S1 + S2 + Vmax*(TempTime-T1-T2) - ((J2*T3*T3*T3/6)-(J2*(T1+T2+T3-TempTime)*(T1+T2+T3-TempTime)*(T1+T2+T3-TempTime)/6));
  155.             Vstart = Vmax - (0.5*J2*(T1+T2+T3-TempTime)*(T1+T2+T3-TempTime));
  156.         }
  157.         //匀速
  158.         else if(TempTime <= T1+T2+T3+T4)
  159.         {
  160.             Sstart = S1 + S2 + S3 + Vmax*(TempTime-T1-T2-T3);
  161.             Vstart = Vmax;
  162.         }
  163.         //加减速 曲线公式参考加加速段,需要做一点变换
  164.         else if(TempTime <= T1+T2+T3+T4+T5)
  165.         {
  166.             Sstart = S1 + S2 + S3 + S4 + Vmax*(TempTime-T1-T2-T3-T4) - J3*(TempTime-T1-T2-T3-T4)*(TempTime-T1-T2-T3-T4)*(TempTime-T1-T2-T3-T4)/6.0;
  167.             Vstart = Vmax - 0.5*J3*(TempTime-T1-T2-T3-T4)*(TempTime-T1-T2-T3-T4);
  168.         }
  169.         //匀减速
  170.         else if(TempTime <= T1+T2+T3+T4+T5+T6)
  171.         {
  172.             Sstart = S1 + S2 + S3 + S4 + S5 + V3*(TempTime-T1-T2-T3-T4-T5)-0.5*DCCmax*(TempTime-T1-T2-T3-T4-T5)*(TempTime-T1-T2-T3-T4-T5);
  173.             Vstart = V3 - DCCmax*(TempTime-T1-T2-T3-T4-T5);
  174.         }
  175.         //减减速 曲线公式参考加加速段,需要做一点变换
  176.         else
  177.         {
  178.             Sstart = Smax - J4*(T1+T2+T3+T4+T5+T6+T7-TempTime)*(T1+T2+T3+T4+T5+T6+T7-TempTime)*(T1+T2+T3+T4+T5+T6+T7-TempTime)/6.0;
  179.             Vstart = 0.5*J4*(T1+T2+T3+T4+T5+T6+T7-TempTime)*(T1+T2+T3+T4+T5+T6+T7-TempTime);
  180.         }

  181.         x[TempCount] = TempCount;
  182.         s[TempCount] = Sstart;
  183.         v[TempCount] = Vstart;
  184.         xcount = TempCount;
  185.         TempTime += TimeStep;
  186.         TempCount ++;
  187.     }

  188.     ui->txLog->append("----");
  189.     ui->txLog->append("All data count : "+QString::number(xcount, 10, 0)+" data in "+QString::number(AllCount, 10, 8)+"s.");
  190.    

  191.     /*判断绘图区域绘制速度曲线还是位移曲线*/
  192.     if(isV)
  193.     {
  194.         ui->customPlot->xAxis->setRange(0,xcount);
  195.         ui->customPlot->yAxis->setRange(0,Vmax);
  196.         ui->customPlot->graph(0)->setData(x,v);
  197.     }
  198.     else
  199.     {
  200.         ui->customPlot->xAxis->setRange(0,xcount);
  201.         ui->customPlot->yAxis->setRange(0,Smax);
  202.         ui->customPlot->graph(0)->setData(x,s);
  203.     }

  204.     ui->customPlot->replot();
  205. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2019-2-24 23:42:08 来自手机 | 显示全部楼层
顶起来,听课

出0入0汤圆

发表于 2019-2-25 00:40:22 来自手机 | 显示全部楼层
自带小板凳了

出0入0汤圆

发表于 2019-2-25 01:15:53 | 显示全部楼层
请教大神,假如1ms计算一次速度,当前的速度和下一个速度的脉冲时间间隔如何衔接?

出0入0汤圆

发表于 2019-2-25 06:46:34 来自手机 | 显示全部楼层
谢谢分享。

出0入0汤圆

发表于 2019-2-25 07:53:14 | 显示全部楼层
假如1ms计算一次速度,

出0入0汤圆

发表于 2019-2-25 08:48:59 | 显示全部楼层
坐等大神讲课,顺带问一句:S曲线加速过程的位移怎么计算呢?

出0入0汤圆

发表于 2019-2-25 08:54:30 | 显示全部楼层
感谢分享。

出1310入193汤圆

发表于 2019-2-25 08:55:25 | 显示全部楼层
坐等老师讲课

出10入12汤圆

发表于 2019-2-25 08:59:12 | 显示全部楼层
看着挺有用!!!!!!

出0入0汤圆

 楼主| 发表于 2019-2-25 11:19:22 | 显示全部楼层
cgbabc 发表于 2019-2-25 01:15
请教大神,假如1ms计算一次速度,当前的速度和下一个速度的脉冲时间间隔如何衔接? ...

这里是举例说加速时间是100ms,分100个脉冲完成,计算周期表的时候就是按每增加1ms算一次速度值,并不是1ms去计算一次。 公式里的单位量纲 速度时 mm/s, 时间是s,  所以实际计算时量纲不要搞错

出0入0汤圆

发表于 2019-2-25 11:58:25 | 显示全部楼层
S曲线,这个得持续关注

出0入0汤圆

发表于 2019-2-25 12:44:31 | 显示全部楼层
围观,学习

出0入0汤圆

发表于 2019-2-25 13:32:48 | 显示全部楼层
samo110 发表于 2019-2-24 22:18
我也分享一个之前做的S加减速曲线计算方法

图用qcustomplot绘制的?

出0入0汤圆

发表于 2019-2-25 14:54:55 | 显示全部楼层
meerlin 发表于 2019-2-25 13:32
图用qcustomplot绘制的?

恩,常用绘图任务简单方便,就是大量高速绘图时比较卡

出0入0汤圆

发表于 2019-2-25 14:56:26 | 显示全部楼层
samo110 发表于 2019-2-25 14:54
恩,常用绘图任务简单方便,就是大量高速绘图时比较卡


楼主现在不做结构了么

出0入0汤圆

发表于 2019-2-25 19:10:56 | 显示全部楼层
meerlin 发表于 2019-2-25 14:56
楼主现在不做结构了么

你这接着我这一层回复,有口口声声喊着楼主,我很尴尬呀
我反正是机械专业出来,干了结构干硬件,干完硬件转软件,啥都打一耙,啥都挖不深

出0入0汤圆

 楼主| 发表于 2019-2-25 19:33:06 | 显示全部楼层
samo110 发表于 2019-2-25 19:10
你这接着我这一层回复,有口口声声喊着楼主,我很尴尬呀
我反正是机械专业出来,干了结构干硬件,干完硬 ...

我也尴尬啊

出0入0汤圆

发表于 2019-9-20 10:29:28 来自手机 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2022-2-24 11:25:51 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2022-2-24 12:41:44 | 显示全部楼层
感谢楼主分享

出50入135汤圆

发表于 2023-9-17 09:25:49 | 显示全部楼层
haishangfeiyin 发表于 2019-2-25 08:48
坐等大神讲课,顺带问一句:S曲线加速过程的位移怎么计算呢?
(引用自11楼)

给速度曲线进行积分就好了.可以看下我发的一个贴子.

出50入135汤圆

发表于 2023-9-17 09:29:54 | 显示全部楼层
我开始也是想通过位置曲线来求取相临速度采样点之间应该发多少脉冲,仔细一想,把事情搞复杂了,把速度采样率提高就是对应的脉冲了.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-10 15:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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