Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evenly spread multisteps #1096

Open
Switchleg1 opened this issue Feb 26, 2024 · 0 comments
Open

Evenly spread multisteps #1096

Switchleg1 opened this issue Feb 26, 2024 · 0 comments

Comments

@Switchleg1
Copy link

Hello,

This is not an issue just curious if you have experimented with evenly spaced multi stepping? Instead of sending two or four steps consecutively in one interrupt its possible to complete one step per timer call and only compute the interval and heavy computations every 1-8 steps allowing you to still achieve 40k steps per second on the mega2560 with much smoother stepper operation.

currently using a STEP_DOUBLER_FREQUENCY of 5000 and allowing 8 steps per calculation

I have simplified some of the code below to show an example:

/////////////// Step //////////////////////////
HAL::forbidInterrupts();

    if (Machine::stepsTillNextCalc) {

#if STEPPER_HIGH_DELAY > 0
if (loop)
HAL::delayMicroseconds(STEPPER_HIGH_DELAY);
#endif
if (cur->isXMove())
if ((cur->error[X_AXIS] -= cur->delta[X_AXIS]) < 0) {
cur->startXStep();
cur->error[X_AXIS] += cur_errupd;
#ifdef DEBUG_STEPCOUNT
cur->totalStepsRemaining--;
#endif
}
if (cur->isYMove())
if ((cur->error[Y_AXIS] -= cur->delta[Y_AXIS]) < 0) {
cur->startYStep();
cur->error[Y_AXIS] += cur_errupd;
#ifdef DEBUG_STEPCOUNT
cur->totalStepsRemaining--;
#endif
}
if (cur->isZMove())
if ((cur->error[Z_AXIS] -= cur->delta[Z_AXIS]) < 0) {
cur->startZStep();
cur->error[Z_AXIS] += cur_errupd;
#ifdef DEBUG_STEPCOUNT
cur->totalStepsRemaining--;
#endif
}
if (cur->isAMove())
if ((cur->error[A_AXIS] -= cur->delta[A_AXIS]) < 0) {
cur->startAStep();
cur->error[A_AXIS] += cur_errupd;
#ifdef DEBUG_STEPCOUNT
cur->totalStepsRemaining--;
#endif
}

#if STEPPER_HIGH_DELAY > 0
HAL::delayMicroseconds(STEPPER_HIGH_DELAY);
#endif
cur->stepsRemaining--;
Machine::stepsTillNextCalc--;
Machine::endXYZASteps();
}

HAL::allowInterrupts(); // Allow interrupts for other types, timer1 is still disabled

if (Machine::stepsTillNextCalc) {
    return Machine::interval;
}

/////////// main calculation interval //////////////

//check endstops
cur->checkEndstops();

#if RAMP_ACCELERATION
//If acceleration is enabled on this move and we are in the acceleration segment, calculate the current interval
if (cur->moveAccelerating()) { // we are accelerating
Machine::vMaxReached = HAL::ComputeV(Machine::timer, cur->fAcceleration) + cur->vStart; // v = v0 + a * t
if(Machine::vMaxReached > cur->vMax) Machine::vMaxReached = cur->vMax;
speed_t v = Machine::updateStepsPerTimerCall(Machine::vMaxReached);
Machine::interval = HAL::CPUDivU2(v);
#if QUICK_STEP
Machine::timer += Machine::interval;
#else
Machine::timer += Machine::interval * Machine::stepsTillNextCalc;
#endif
Machine::stepNumber += Machine::stepsSinceLastCalc; // only used for moveAccelerating
} else if (cur->moveDecelerating()) { // time to slow down
uint16_t v = HAL::ComputeV(Machine::timer, cur->fAcceleration);
if (v > Machine::vMaxReached) { // if deceleration goes too far it can become too large
v = cur->vEnd;
} else {
v = Machine::vMaxReached - v;
if (v < cur->vEnd) v = cur->vEnd; // extra steps at the end of deceleration due to rounding errors
}
v = Machine::updateStepsPerTimerCall(v);
Machine::interval = HAL::CPUDivU2(v);
Machine::timer += Machine::interval * Machine::stepsTillNextCalc;
} else
#endif
{ // full speed reached
Machine::updateStepsPerTimerCall(cur->vMax, cur->fullInterval);
}

if (Machine::stepsTillNextCalc > cur->stepsRemaining) {
    Machine::stepsTillNextCalc = cur->stepsRemaining;
}
Machine::stepsSinceLastCalc = Machine::stepsTillNextCalc;

static INLINE speed_t updateStepsPerTimerCall(speed_t vbase) {
#if MAX_STEPS_PER_CALL >= 8
if (vbase > STEP_DOUBLER_FREQUENCY * 4) {
Machine::stepsTillNextCalc = 8;
#endif
#if MAX_STEPS_PER_CALL >= 4
if(vbase > STEP_DOUBLER_FREQUENCY * 2) {
Machine::stepsTillNextCalc = 4;
} else
#endif
#if MAX_STEPS_PER_CALL >= 2
if (vbase > STEP_DOUBLER_FREQUENCY) {
Machine::stepsTillNextCalc = 2;
} else
#endif
{
Machine::stepsTillNextCalc = 1;
}

    return vbase;
}
static INLINE void updateStepsPerTimerCall(speed_t vbase, ticks_t fullInterval) {

#if MAX_STEPS_PER_CALL >= 8
if (vbase > STEP_DOUBLER_FREQUENCY * 4) {
Machine::stepsTillNextCalc = 8;
interval = fullInterval;
} else
#endif
#if MAX_STEPS_PER_CALL >= 4
if (vbase > STEP_DOUBLER_FREQUENCY * 2) {
Machine::stepsTillNextCalc = 4;
interval = fullInterval;
} else
#endif
#if MAX_STEPS_PER_CALL >= 2
if (vbase > STEP_DOUBLER_FREQUENCY) {
Machine::stepsTillNextCalc = 2;
interval = fullInterval;
} else
#endif
{
stepsTillNextCalc = 1;
interval = fullInterval;
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant