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:
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?