laurb9 / StepperDriver

Arduino library for A4988, DRV8825, DRV8834, DRV8880 and generic two-pin (DIR/STEP) stepper motor drivers
MIT License
556 stars 228 forks source link

Support non-blocking nextAction() #122

Open ddowling opened 11 months ago

ddowling commented 11 months ago

Is there any interest in a non-blocking version of the nextAction() method? I have been testing the following replacement that can be called with nextAction(false) from the main loop or an interrupt handler to drive all of the step pulses without blocking the caller. I also modified how the last_action_end value was calculated to base this off the calculated times as this significantly reduces the accumulation of jitter on the step pulses which was affecting the maximum speeds I could achieve.

long BasicStepperDriver::nextAction(bool block)
{
    if (steps_remaining > 0)
    {
        if (block)
            delayMicros(next_action_interval, last_action_end);
        else
        {
            unsigned long now = micros();

            long delay =  (last_action_end + next_action_interval) - now;

            if (delay > 0)
                return delay;
        }

        // DIR pin is sampled on rising STEP edge, so it is set first
        digitalWrite(dir_pin, dir_state);
        digitalWrite(step_pin, HIGH);

        // save value because calcStepPulse() will overwrite it
        unsigned long pulse = step_pulse;
        calcStepPulse();

        // Rely on the the calStepPulse function to produce a small delay
        // for the step high pulse
        digitalWrite(step_pin, LOW);

        // Base last_action_end on the expected time the event should
        // happen to smooth out jitter caused by timing clicks arriving late
        if (last_action_end == 0)
            last_action_end = micros();
        else
            last_action_end += next_action_interval;

        next_action_interval = pulse;
    }
    else
    {
        // end of move
        last_action_end = 0;
        next_action_interval = 0;
    }
    return next_action_interval;
}

I can work this into a pull request if there is some interest.