AccelStepper uneven step intervals

Hi all,

I am working on a project with an Arduino Nano Every involving a stepper motor. AccelStepper works well for this, and I am using the acceleration feature so I can run the motor in its slew range.

For the application (a reciprocating mechanism creating pulsatile flow emulating human blood circulation) I need to run the driver up to about 2500 steps per second. In practice, it runs quietly and smoothly up to about 1500 SPS (no load) but above that the motor starts rattling noisily, and above about 2000 SPS the motor misses steps and stalls.

I know this is not a motor or driver hardware issue, because I can run a 3000 to 4000 Hz square wave into the driver and the motor runs smoothly and quietly. So I suspected there was an issue with the signal from the Arduino.

Testing with a very simple program at constant speed using AccelStepper.runSpeed(), at around 1500 SPS, the output waveform starts to look messy, with unevenly spaced pulses. This gets worse and worse at higher speeds. At 3000 SPS it is really bad. This is either the cause of my problem, or is contributing to it significantly. Below are the output waveforms from my step pin at 1000 SPS and 3000 SPS:


Here is a closeup:
image

According to AccelStepper documentation, it should run fine up to 4000 SPS on an Uno @ 16 MHz:

The fastest motor speed that can be reliably supported is about 4000 steps per second at a clock frequency of 16 MHz on Arduino such as Uno etc. Faster processors can support faster stepping speeds.

I am running on hardware at 20 MHz and don't get a reliable even output above 1500 SPS so I'm now a bit stuck as to why.

The code I am using to produce this is very simple and I am not doing anything during loop() that would slow down execution between calls to runSpeed(). Here is the entire loop function I used to produce the above - apart from checking millis(), all I am doing is calling runSpeed() in each loop:

void loop() {

  if (millis() > (starttime + 5000)) {  // read and update speed ONLY ONCE EVERY 5 SECONDS
    starttime = millis();
    int sensorReading = analogRead(potPin);
    int motorSpeed = map(sensorReading, 0, 1023, 5, 5000);
    lcd.print(motorSpeed);
    lcd.print(" Hz     ");
    myStepper.setSpeed(motorSpeed);
  }

  myStepper.runSpeed();
}

The code in loop() in my main project is even slimmer and doesn't even call millis(), it just has a switch statement and calls AccelStepper.run(). As long as AccelStepper.run() returns TRUE (i.e. motor has not reached target) then that's literally all that is executed before returning.

I am trying to work out what is limiting the performance of my system so that it will not give me a clean, constant frequency output. I would consider FastAccelStepper, but this is not compatible with the Nano Every architecture.

Is there anything obvious I have missed that could be impacting performance? Am I asking too much from the hardware - if so, what Arduino board would you recommend where it will not struggle at these sorts of speeds? Or should I be using a different library?

You know that limited acceleration will lead to uneven step intervals?

Increase the allowed acceleration until it works better.

Hi, in the example above I have already completely removed acceleration from the picture.

runSpeed() drives the stepper motor at a constant speed (set by setSpeed()) but the steps are still very uneven.

If the speed is as expected then uneven steps may result from a too low clock frequency.

I am running it on a Nano Every at 20 MHz (had to modify boards.txt to force this speed) - however, it should work fine on an Uno at 16 MHz according to the library docs, so this should exceed requirements.

Is this what you mean? Or is there another frequency I need to be aware of?

That does not say that all steps are of equal duration.

I think that for high speed operation you want to use a hardware timer based library.

MobaTools uses timers and supports the NanoEvery, but because it allows for multiple steppers/servos the highest speed is limited and I don't recall what that that is.

I have used this timer interrupt library on the Nano Every to send a pulse in the isr to a stepper. You will have to manage the accelleration yourself.
https://github.com/khoih-prog/megaAVR_TimerInterrupt

1 Like

You could try the MobaTools library. This library creates the step pulses in timer interrupts, so is not dependant on loop cycle time (the lcd functions need considerable time).
The library is able to create up to 2500 steps / sec on AVR out of the box.

1 Like

Thank you both. I will investigate MobaTools and megaAVR_TimerInterrupt, and let you know how it goes!

I converted my code from AccelStepper to MobaTools, which is much better because the non-blocking methods will run alongside other tasks, like reading sensors, without any disruption.

However, the signal for the stepper driver was exactly the same: steps were still uneven and I still couldn't achieve the speeds I wanted.

Replaced the Nano Every with an Arduino Uno R4 Minima and everything now works beautifully, smooth as silk...