Firmware/Constant Acceleration
The official FiveD firmware changes speed by a fixed amount each step, however this also alters the step time. acceleration = dv/dt, so with a fixed dv but a changing dt, acceleration changes during a move. This makes high speeds quite unattainable as the acceleration quickly outstrips the motor's ability to keep up.
Teacup Firmware contains a constant acceleration implementation based on [this article]
I don't remember how I calculated and integrated the acceleration term into the below, feel free to work it out from the article and update this description.
- sf and ef are start and end feedrates in mm/min
- dx, dy and dz are move distances along each axis
- distance is the movement distance, equivalent to sqrt(dx^2 + dy^2 + dz^2)
- ts is total steps, equivalent to max(dx, dy, dz).
- c and end_c are start and end step timer values
- CF shall refer to conversion factors necessary for unit translations but mostly irrelevant to describing this process.
so, here we go
c (tick/step) = um/step * min/mm * CF[min->tick] um/step = distance / ts sf = mm/min c = tick/step = min/step * CF[min->tick] = distance / ts / sf * CF[min->tick]
and conversely,
end_c = distance / ts / ef * CF[min->tick]
from [the article]
n = ts * sf^2 * 4 / (sf^2 - ef^2) [Equation 16]
and in each step we calculate
c = c - (2c / (4n + 1)) [Equation 13] n += 1
however I have integrated 4n+1 into the initial setup of n, which simplified this to:
n = (ts * sf^2 / ((sf^2 - ef^2) / 4)) + 1
then after each step
c = c - (2c / n) n += 4
c must be checked against end_c - because this is an integer approximation of a recursive function, mere loss of precision causes significant cumulative error. I had to implement c and end_c as 24.8 fixed point in order to maintain usable resemblance to the ideal values.
As a result of its calculation, n is positive when accelerating and negative when decelerating so we don't need to differentiate between them.
Since sf^2, ef^2 and ((sf^2 - ef^2) / 4) are used fairly often, I precalculate them into ssq, esq and dsq respectively in my implementation.
Also, since ssq, esq and dsq are only ever used in ratio with one another, I can scale sf and ef by any factor I like in order to keep the precision within 32 bits.