AccelStepper setSpeed question

Hello and thank you, in advance for any support, with my question.
I have fumbled my way through a sketch, which controls the speed and directions of a single stepper motor with a pot. The pot is centre off and the centre position is also indicated by a bicolour LED.
My frustration, is that the motor never achieves it’s maximum speed, as determined by: setMaxSpeed, despite the setSpeed integer reaching that value (5000 in this case)
It seems the motor does not exceed 1000 steps/sec with this code.

If alternatively, I run the same motor using the accelStepper example code: Quickstop.
The example code allows the motor to spin all the way to the MaxSpeed value, as a function of moveTo.

Can anyone explain why the motor will not run at 5000 steps/sec with?:

    stepper.setSpeed(5000);
        stepper.run();

My Sketch:

/* 
 Stepper Motor Control - Speed and Direction control - Centre Off
 
 */
 
#include < >



const int BiLedPin1 = 6; // LED Pin 1
const int BiLedPin2 = 7; // LED Pin 2

const int SwitchPin = 8;        // pin 8: Enable Switch


AccelStepper stepper(AccelStepper::DRIVER, 10, 11); 

int Switch = 0;         // variable for reading the switch status

void setup() {

  Serial.begin(9600);  

    stepper.setMaxSpeed(5000);

   
  pinMode(BiLedPin1, OUTPUT);
  pinMode(BiLedPin2, OUTPUT);
  pinMode (SwitchPin, INPUT_PULLUP);
}

void loop() {
 
  int PotValue = analogRead(A0);  // read the pot value:

  int Pot = map(PotValue, 0, 1023, -100, 100);   // map it to a range from -100 to 100:
  
  int motorSpeed = (Pot * 50);   //multiply the Pot value:
   
  Switch = digitalRead(SwitchPin);
  
 Serial.println(motorSpeed);   // Display the scaled MotorSpeed value:

 Serial.println(Pot);   // Display the scaled pot value:

   if ((-5 < Pot ) && (5> Pot))
{ 

   digitalWrite(BiLedPin2, HIGH); // BiColour GREEN
 digitalWrite(BiLedPin1, LOW);   // BiColour GREEN
      
  } 
  
  else if ((5 < Pot ) || (-5 > Pot ))
{ 

   digitalWrite(BiLedPin2, LOW);
 digitalWrite(BiLedPin1, HIGH);
      
  } 
  if ((Switch == LOW) && (Pot > 10))
{
 
    stepper.setSpeed(motorSpeed);
        stepper.run();
  
  }
   
   else if ((Switch == LOW) && (Pot < -10))
{ 

    motorSpeed = (motorSpeed / -1);//Invert the negative motorSpeed value
    stepper.setSpeed(-motorSpeed); 
        stepper.run();
     
  }
  

    }
   if ((-5 < Pot ) && (5> Pot))

How many times did you have to try to get that statement right? Do you THINK that way? How much easier is it to see that the value is in the range by typing:

   if(Pot > -5 && Pot < 5)
  else if ((5 < Pot ) || (-5 > Pot ))

Why are you not dealing with Pot = 5? With Pot = -5?

    motorSpeed = (motorSpeed / -1);//Invert the negative motorSpeed value

The usual way to do this is to multiply by -1? Why do you want to be weird?

Two questions. Why are you not giving the motor time to get up to speed before you call setSpeed() again?

How are you powering the steppers? The maximum speed that a stepper can obtain is far more a function of the amount of current it gets that it is how often you tell it to step.

Stepper.run() should be called as often as possible, make it the first statement in loop().

void loop()
{
  stepper.run();
  ...
  ...
  ...

Have you written a short program without any attempt at direction control just to find out what the motor is capable of?

I'm not sure if the AccelStepper library is capable of doing 5000 steps per second. It uses floating point maths which is very slow on an Arduino.

AFAIK people have adapted my Simple Stepper Code to get high step rates for testing.

...R
Stepper Motor Basics

Hello all and thank you all for your replies.

I am driving the motor with a DRV8825 carrier.
I managed to convince myself that the hardware is capable of achieving the higher speed, in combination with accelStepper, as the example code 'Quickstop' seems to work well with a higher maxSpeed.
That said though Robin2, you are right, 5000 is too high.
I have the driver set to half step, and run it at about 3400 sps Max.
I have written some simple programs, with varying success.
My reason for implementing accellStepper, is in hoping to use the acceleration and deceleration functions.
If the floating point issue slows things down too much, I will go back and use a modified version of your simple stepper code.
Thank you for sharing it.
Yes, PaulS, I am weird.. Thank you for the observation (and the guidance).

izulustudios:
My reason for implementing accellStepper, is in hoping to use the acceleration and deceleration functions.

That is not the only way to do acceleration.

I have been experimenting with using Timer2 to generate the step pulses and changing the speed (acceleration and deceleration) by varying the number of counts before the Timer cause an interrupt. It seems to work quite adequately.

...R

Hello everyone.
So, experimenting further, I have determined that it is the analogRead (ADC) and mapping which slows the whole process (loop?) down.
If I remove:

 int PotValue = analogRead(A0);

  int Pot = map(PotValue, 0, 1023, -100, 100); ]

The motor runs up to maxSpeed.
With the analogRead in the sketch, I only get up to about 80% of my maxSpeed..

Can anyone suggest a way around this, (for example using an Arduino Due, as opposed to a Leonardo)
or will reading the pot inevitably always slow everything down by this margin?

Thank you again for any support.

izulustudios:
With the analogRead in the sketch, I only get up to about 80% of my maxSpeed..

That suggests that you are calling analogRead() for every step - I doubt if that is necessary.

...R

will reading the pot inevitably always slow everything down by this margin?

It ought to be obvious that analog readings take time.

Thanks PaulS, thats really constructive advice..

Can anyone please tell me whether analogRead will run faster on a Due, than it is currently running on a Leonardo?
I cannot get accelStepper to run my motor fast enough, in combination with an analogRead function.
Any further suggestions hugely appreciated.

Any further suggestions hugely appreciated.

Why do you need to read the analog pin on EVERY pass through loop()?

Obviously, the Due will complete the necessary instructions to read the analog pin faster. However, the time it takes for the analog to digital converter to charge up and return a reading is not based on the processor clock speed. It is based on physics.

It is also possible to get an ADC reading in two stages so that it does not block the Arduino - but this is a little more complex than using analogRead(). You need to study the Atmega 328 datasheet - assuming you are using an Uno.

...R

Thank you both, again for your helpful replies.
I am currently running the project on a Leonardo.
I like the sound of not running the analogRead on every pass, but right now, don't know how to achieve this.
I'll do some digging.
Thank you again.

I like the sound of not running the analogRead on every pass, but right now, don't know how to achieve this.

How often DO you need to read the pin?

The blink without delay example will provide some clues.

izulustudios:
I like the sound of not running the analogRead on every pass, but right now, don't know how to achieve this.

Have a look at the demo Several Things at a Time and at Planning and Implementing a Program

...R

Apologies, repeated post..

Thanks PaulS.
That feels like it’s pointing me in the right direction.
I think every 200mS, would absolutely fine for this application (even every half second would work).
I have been muddling with an extract from ‘blink without delay’, but unfortunately it still isn’t working.
(motor isn’t running at all…)
Code below:
I will keep muddling!
Thanks again.

/* 
 Stepper Motor Control - Speed and Direction control - Centre Off
 
 */
 
#include <AccelStepper.h>


unsigned long previousMillis = 0; 
const int interval = 200;  // interval at which to read the pot (milliseconds)

const int BiLedPin1 = 6; // LED Pin 1
const int BiLedPin2 = 7; // LED Pin 2

const int SwitchPin = 8;        // pin 8: Switch

AccelStepper stepper(AccelStepper::DRIVER, 10, 11); 

int Switch = 0;         // variable for reading the pushbutton status
int Pot;
int motorSpeed;

void setup() {

  Serial.begin(9600);   // initialize the serial port:
    stepper.setMaxSpeed(4000);
   stepper.setAcceleration(200);

   
  pinMode(BiLedPin1, OUTPUT);
  pinMode(BiLedPin2, OUTPUT);
  pinMode (SwitchPin, INPUT_PULLUP);

}

void loop() {
 
      stepper.run();
      
  Switch = digitalRead(SwitchPin);
  
if (motorSpeed > -100 && motorSpeed < 100)
   
{ 

   digitalWrite(BiLedPin2, HIGH); // BiColour GREEN
 digitalWrite(BiLedPin1, LOW);   // BiColour GREEN
      
  } 
  
  else if  ((100 < motorSpeed ) || (-100 > motorSpeed ))
 
{ 

   digitalWrite(BiLedPin2, LOW); // BiColour RED
 digitalWrite(BiLedPin1, HIGH);  // BiColour RED
      
  } 
  
  if ((Switch == LOW) && (motorSpeed > 100))
{

  motorSpeed = (motorSpeed/-1); //Invert the negative motorSpeed value
    stepper.setSpeed(-motorSpeed);
  
  }
   
   else if ((Switch == LOW) && (motorSpeed < -100))
{ 

    stepper.setSpeed(motorSpeed);
     
  }
    
      unsigned long currentMillis = millis();
 
  if (currentMillis - previousMillis >= interval)
  
  {  
 
    
    int PotValue = analogRead(A0);  // read the pot value:

  int motorSpeed = map(PotValue, 0, 1024, -4000, 4000);   // map it to a range from -4000 to 4000:
 
   Serial.println(motorSpeed);   // Display the scaled pot value:
 Serial.println(currentMillis);    // Display the cumulated millis:
  Serial.println(Switch);    // Display the switch staus:
 
    previousMillis = currentMillis;
 
  }

    }