nth motor step delay calc help

dynex

New member
Joined
Jul 10, 2021
Messages
9
Hi forum,


I've been trying to calculate "inner-step delays" of a stepper motor with a equation, but I'm a bit stuck.

Background:
The objective is to step a motor nth times for a specified time. To further complicate things, I’ve been trying to factor in ramp time to achieve the desired target time.

Using an exponential equation to calculate the nth delay time, seemed to work pretty well. Changing the delay time linearly seemed to ramp the motor exponential? which was awful....

what I have is far is as follows.

iv = initial Velocity (given)
fv = final Velocity (?)
dt = total distance (given)
t = total time (given)
p = percentage IE 10%
t1 = s
t = 2*t1 + t2
t2 = d2/fv
d3 = d1 =dt * p
d2 = dt - 2*d1
dt = d1+d2+d3
n = nth step

y=ab^x ( {0, 1/5000} {d1, 1/fv} )
a = 1/iv
b = (iv / fv)^(1/n)
y = (1/iv)*(iv/fv)^(1/n)
so that's my exponential equation for calculating ramp delay time based on the nth step.
This actually gives y = 1/f. My microsecond delay is y/2.

To calculate the ramp time I’ve used a summation equation.
s = a*((1-b^n) / 1-b)
this gives the total time ramping will take at nth steps

The problem is I need compute the final velocity to account for the added ramp delay so I can finish steeping at the specified time. (I need to move a given distance in a given time)

I'm unable to solve to "fv", I feel like I'm missing something really obvious, and its really bothering me. I thought I would ask the forum to see if anyone had any ideas.
--------------------
a = 1/iv
b = (iv/fv)^(1/n)
s = a*((1-b^n)/(1-b))
t = d2/fv + 2*s
-----------------------

This is the sample datasets I’ve been working with.
dt = 9744
d1 = 974
d2 = 8770
iv = 5000hz
fv = ? (should be more than 9800hz)
n = 974
t = 1sec

Let me know if I need to provide more information, or explain things in more detail.
I'm looking forward to a reply, thanks.
 
I don't know if I can edit my post... attached is a pdf with the equations and a graph.
I can attach a plot of my sample data set if required.
 

Attachments

  • math_step.pdf
    318.8 KB · Views: 8
Well, I was hoping for better reception, to drum up interest, I'm attaching some code and graphs. This is not homework by the way.

I can brute force a value for fv, but I would really like a way to calculate it. Hopefully someone can give me some advice, thanks in advance.

screen_shot.png
 

Attachments

  • log6.txt
    226.7 KB · Views: 4
  • mtest.cpp.txt
    1.6 KB · Views: 2
I'm sure your equation for T (2nd line of the pdf in post#2) can't be rearranged to a form Fv=<something>

I can suggest two options:-
  • simplify the equation for T
  • or, in your code, implement a "binary search" to find Fv much more quickly than the linear search you implemented under the comment "brute force final velocity".
 
I'm sure your equation for T (2nd line of the pdf in post#2) can't be rearranged to a form Fv=<something>

I can suggest two options:-
  • simplify the equation for T
  • or, in your code, implement a "binary search" to find Fv much more quickly than the linear search you implemented under the comment "brute force final velocity".
Thanks for the reply, I've tried to rearrange the equ to solve for fv, but "I" can't. I even tried wolframalpha....

How would I go about simplifying the T equation?
And again, I do appreciate the reply. I was apprehensive about posting on the forum. I'm glad to see chivalry among strangers.

I'm also open to solving the problem with a different solution.

EDIT: you said "can't be rearranged to a form Fv=<something>" my mistake, that's actually the answer I was hoping for.
I'll explore another avenue.
 
Last edited:
Changing the delay time linearly seemed to ramp the motor exponential? which was awful....
Why not try a linear ramp of the frequency, giving a constant acceleration? And (step frequency) = 1/(step time)
 
I'll give it a shot.

IV = 5000
FV = 9744
a = 593
delay = 1/f
-------------------------------------------------------
for (double i = 5000.0; i <= 9744.0; i += 593)
{
time_inc += 1.0 / i;
printf("%d:%f\n",f++, 1.0 / i);
}
printf("t:%f\n", time_inc);
--------------------------------------
0:0.000200
1:0.000179
2:0.000162
3:0.000148
4:0.000136
5:0.000126
6:0.000117
7:0.000109
8:0.000103


t:0.001278
-----------------------------------

the total time was 1.278 ms, in 9 steps.
9 = (1/2) (5000 + 9744) * t, t = 1.221ms

57 microseconds are missing, between actual and calculated.
I assume the error would double when ramping down.

I'm honestly not sure if this is a program error or a mathematical error, but that's a lot of play, I was hoping for more accuracy.
 
Why not try a linear ramp of the frequency, giving a constant acceleration? And (step frequency) = 1/(step time)
1626042615286.png
I went ahead and used my ti89T, just encase vars were being overflowed.
I hope this is what you were talking about, if not, I may have egg on my face.
 
The summation in your code is equivalent to...

[MATH]t=\sum_{x=0}^8\frac{1}{5000 + 593x}[/MATH]
t is equal to the shaded area in the following graph...

gr.png

In your alternative calculation you effectively take the average period, and multiply it by the number of periods. That's the same as the area under the blue line in the graph. There is more shaded red area above the blue line than below. This is because the red bars drop more steeply at the start of the graph. This is where the inaccuracy comes from.

You can obtain a better result by calculating the area under the green line. This is a midpoint Riemann sum (click). It's still an approximate value, but it will be closer to the true value.

[MATH]t ≈ \int_0^9\frac{1}{5000 + 593(x-0.5)}dx= \int_{-0.5}^{8.5}\frac{1}{5000 + 593u}du[/MATH]
[MATH] =\left[\frac{\ln\left( 5000 + 593u \right)}{593}\right]_{u=-0.5}^{8.5} [/MATH]
= 1.278ms
 
Last edited:
There is more shaded red area above the blue line than below. This is because the red bars drop more steeply at the start of the graph.

...I didn't explain the above very well :whistle: What I mean is that in the region 0<x<4 there's an area of red rectangles above the blue line, let this be area "A". While in the region 5<x<9 there's an area of white space between the blue line and the top of the red rectangles, let this be area "B". In order for the blue line estimate to be good, then A should be close to the same value as B. (Then the area of the red shaded rectangles would equal the area under the blue line). But, because the red bars drop more steeply in area A, then A>B. Hope this is more clear!
 
...I didn't explain the above very well :whistle: What I mean is that in the region 0<x<4 there's an area of red rectangles above the blue line, let this be area "A". While in the region 5<x<9 there's an area of white space between the blue line and the top of the red rectangles, let this be area "B". In order for the blue line estimate to be good, then A should be close to the same value as B. (Then the area of the red shaded rectangles would equal the area under the blue line). But, because the red bars drop more steeply in area A, then A>B. Hope this is more clear!
Sorry, I was out and about, I appreciate you taking the time to reply back. Don't worry to much about clarity, there is no good way to explain this stuff.
 
Last edited:
Having explained why your calculations were giving different results, I recommend that you abandon that method and change your approach. :eek::)

A simpler method, IMO, is to use Newton's laws of motion (constant acceleration). Each step of the motor will move the shaft a set "distance". So, if the motor must accelerate for a period, then break this journey down into lots of destinations along the way - each destination corresponding to an individual step of the motor. This way you can calculate the actual time that each step should occur. EVERY calculation can be performed from the same starting position/velocity (so that you avoid any possible rounding errors associated with adding up lots of individual slices). In this scenario it's good to let the continuous math drive the discrete math, rather than the other way around.
 
Having explained why your calculations were giving different results, I recommend that you abandon that method and change your approach. :eek::)

A simpler method, IMO, is to use Newton's laws of motion (constant acceleration). Each step of the motor will move the shaft a set "distance". So, if the motor must accelerate for a period, then break this journey down into lots of destinations along the way - each destination corresponding to an individual step of the motor. This way you can calculate the actual time that each step should occur. EVERY calculation can be performed from the same starting position/velocity (so that you avoid any possible rounding errors associated with adding up lots of individual slices). In this scenario it's good to let the continuous math drive the discrete math, rather than the other way around.
This was exactly what I needed!!, I feel like a fool for not realizing it sooner. I implemented it today at work, and she works likes a champ.

I'll post some reduced code and sample graphs for completeness. (encase anyone finds this thread helpful)

I can't thank you enough for helping me come to this realization. Physics be a cruel mistress. o_O

(good thing I'm not a rocket scientist, we would all be dead lol)
 
1626134103391.png
 

Attachments

  • 1626134071562.png
    1626134071562.png
    59.6 KB · Views: 1
  • log.txt
    226.7 KB · Views: 1
  • RC.cpp.txt
    1.5 KB · Views: 2
Top