You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
}
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);
}
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:
#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();
}
#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);
}
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;
}
#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;
}
}
The text was updated successfully, but these errors were encountered: