Stepper too slow on low speed

Hi there,

I made a project, where I want to pull a thread with two Lego-Wheels. The hardware all works as it should, but I got a problem using the stepper, which I could not solve by myself and google didn’t help either:

If the speed of the stepper is set too low, it decreases the speed even more.
In this program I calculated the speed and steps with the distance to pull and the time-span, in which the thread should be pulled this distance:

#include <Stepper.h> 
int SPU = 2048; 
Stepper Motor(SPU, 3,5,4,6); 
double roundsPerMinute = 0;
double rounds = 0;

double distance = 20; //in cm
double timeSpan = 1; //in min
double wheelDiameter = 23.3; //in mm

void setup() 
{
  Serial.begin(9600);

  double distancePerRound = (wheelDiameter/10)*PI;
  rounds = distance/distancePerRound;
  roundsPerMinute = rounds/timeSpan;

  //calculate Speed and needed rotations
}

void loop() {
    Serial.println("Rounds per minute: " + String(roundsPerMinute));
    Serial.println("Rounds: " + String(rounds));
    
    Motor.setSpeed(roundsPerMinute);
    
    long steps = rounds*2048; //calculate speed from rounds
    Serial.println("Steps: " + String(steps));
    
    long start = millis(); //start measuring time
    
    
    for(int i = 0; i < int(steps/10000); i++){ //I tested out that the .step function only can recieve values up to 32767, so I call this function multiple times
      Motor.step(10000);
    }
    Motor.step(steps%10000); 
    
    
    long neededTime = millis() - start; //stop measuring time
    
    Serial.println("Needed Time: " + String(neededTime/1000.0));
    Serial.println();
}

This works all fine if the roundsPerMinute are higher than ca.5, but when they are lower, the problem I explained appears.

To name an example:
distance = 147 cm
timeSpan = 6 min
→ real distance: correct
→ real time: 6 min 41 sec

I hope you can understand what I mean.

Stepper: 28BYJ-48
Driver: ULN2003

What do I do wrong?

Thank you in advance!

The stepper library takes speed as an integer (whole number) in RPM, you should set your move distance in steps and speed in milliSeconds (or microSeconds) between steps.
2.33cm * PI = 7.32 cm per turn / 2048 steps per turn = 0.003574cm per step = 279.785 steps per cm.
20 cm / min = 5596 steps or a step every 10722 microSeconds.

JCA34F:
The stepper library takes speed as an integer (whole number) in RPM, you should set your move distance in steps and speed in milliSeconds (or microSeconds) between steps.

Those two highlighted parts seem to contradict each other. And the first part is correct.

...R

Example (untested):

#include <Stepper.h>
int SPU = 2048;
Stepper Motor(SPU, 3,5,4,6);
double roundsPerMinute = 0;
double rounds = 0;

double distance = 20; //in cm
double timeSpan = 1; //in min
double wheelDiameter = 23.3; //in mm
unsigned long stepsToGo; //NEW <<<<<<<<<<<<
unsigned long stepTime;  //NEW <<<<<<<<<<<<
unsigned long microsPerStep; //NEW <<<<<<<<<<<<

void setup()
{
  Serial.begin(9600);

  double distancePerRound = (wheelDiameter/10)*PI;
  rounds = distance/distancePerRound;
  roundsPerMinute = rounds/timeSpan;
  stepsToGo = rounds * SPU; //NEW <<<<<<<<<<<<
  microsPerStep = 1000000UL * 60 * timeSpan / (rounds * SPU); //NEW <<<<<<<<<<<<
  //calculate Speed and needed rotations
  Serial.println(stepsToGo); //NEW <<<<<<<<<<<<
  Serial.println(microsPerStep); //NEW <<<<<<<<<<<<
  delay(10000); //NEW <<<<<<<<<<<< 10 seconds to read calculations
  stepTime = micros();
}

void loop() {
  if(stepsToGo > 0)
  {
    if(micros() - stepTime > microsPerStep)
    {
      Motor.step(1); // -1 for reverse
      stepsToGo--;
      stepTime += microsPerStep;
      Serial.println(stepsToGo); 
    }
  }  
       
 /* Serial.println("Rounds per minute: " + String(roundsPerMinute));
    Serial.println("Rounds: " + String(rounds));
   
    //Motor.setSpeed(roundsPerMinute);
   
    long steps = rounds*2048; //calculate speed from rounds
    Serial.println("Steps: " + String(steps));
   
    long start = millis(); //start measuring time
   
   
    for(int i = 0; i < int(steps/10000); i++){ //I tested out that the .step function only can recieve values up to 32767, so I call this function multiple times
      Motor.step(10000);
    }
    Motor.step(steps%10000);
   
   
    long neededTime = millis() - start; //stop measuring time
   
    Serial.println("Needed Time: " + String(neededTime/1000.0));
    Serial.println();*/
}

JCA34F:
Example (untested):

You seem to be moving one step at a time and substituting your own timing mechanism in place of the stepper.setSpeed() function.

That might be a solution but it would have been useful if you had explained that for the benefit of the OP.

The OP might wish to consider the AccelStepper library which is far better than the standard Stepper library.

…R

Thank you all for your answers!

JCA34F:
The stepper library takes speed as an integer (whole number) in RPM,

This was my major fault. I did not know that

I will try out your suggestions in a few days.

Thank you a lot!