赞
踩
在一般的单片机,或者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形变化的曲线,所以暂时不研究它了,线性斜坡这种方法也是存在问题,就是增量值由于微分的分数过多,小数部分就构成了误差,速度累加起来后,在实际的时间对应的速度却产生了偏差,后续看有没有办法改良,留着下了文章再说了。。。。。。。。。。。。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。