Maximum speed using Accelstepper

Finally managed to get the stepper running as expected. (It overran by 30% earlier. Change of power supply unit solved the matter.)
The goal is to run a rotating table having a worm gear ratio of 90:1.
Controller is a clone UNO, power supply 12V, 20 Amp. TB6600 driver set to 2.8 Amp.
Right now cranking up acceleration as well as maximum speed to find the no load maximum figures. Increasing acceleration, no problem. Increasing max speed, no problem but.... I'm missing something.

Look at max speed an acceleration in the code. The stepper is happily running...

#include<arduino.h>

//I2C for LCD
#include <AccelStepper.h>
#include <Wire.h>
//#include <hd44780.h>
//#include <hd44780ioClass/hd44780_I2Cexp.h>

//hd44780_I2Cexp mylcd; // declare lcd object: auto locate & config exapander chip

AccelStepper myStepper (1, 6, 7);

// LCD geometry
#define LCD_COLS 16
#define LCD_ROWS 2

enum mode {Sides, Angle };
int faces = 4;
//unsigned long nrOfStepsPerRev = 90L * 200L * 32L; // microstep 32 & rotating table
unsigned long nrOfStepsPerRev = 200 * 32 * 4; // microstep 32 & testing stepper 1 rev
unsigned long currentStep;

enum cmd {increase, decrease, Go, Chg, GoStep, nobutton};
unsigned long anglePos;

void setup() {
  Serial.begin(115200);
  Serial.println("Rotation ");
  /*  //1Hz 90% dutycycle
    pinMode(9, OUTPUT);                               // Set digital pin 9 (D9) to an output
    TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11);  // Enable the PWM output OC1A on digital pins 9 and invert output
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12);     // Set fast PWM and prescaler of 256 on timer 1
    ICR1 = 62499;                                     // Set the PWM frequency to 1Hz: 16MHz/(256 * 1Hz) - 1 = 62499
    OCR1A = 6249;                                     // Set the duty-cycle to 10%: 62499 / 10 = 6249

    pinMode(10, OUTPUT);                               // 1 Hz pulse output on digital pin 9 (D9)
  */  pinMode(13, OUTPUT); digitalWrite(13, LOW);// Make board LED go off
  delay(10);//allow pwm timers to start

  //  myStepper.begin();
  myStepper.setMaxSpeed(100000L);
  myStepper.setAcceleration(30000L);

#define digitalIncreaseButton 2
  pinMode (digitalIncreaseButton, OUTPUT);
#define digitalDecreaseButton 3
  pinMode (digitalDecreaseButton, OUTPUT);
#define digitalChgButton 4
  pinMode(digitalChgButton, OUTPUT);
#define digitalGoButton 5
  pinMode(digitalChgButton, OUTPUT);
#define guard1 6
#define guard2 7

#define cuttingSpeed 100 // when cutting during rotation
#define movingSpeed 500 //when moving without cutting

  /*
       int status;
    status = mylcd.begin(LCD_COLS, LCD_ROWS);
    if (status) // non zero status means it was unsuccesful
    {
      status = -status; // convert negative status value to positive number

      // begin() failed so blink error code using the onboard LED if possible
      hd44780::fatalError(status); // does not return
    }
    mylcd.clear();
  */
  // Print start message to the LCD
  /*  mylcd.print("221118a Rotating");
    delay(5000);
    mylcd.print("Running");
    delay(1000);
  */
}

enum cmd readButtons(void)
{
  char cmd = 'q';
  /*
    if ((digitalIncreaseButton) == 0)  return (increase);
    if ((digitalDecreaseButton) == 0)  return (decrease);
    if ((digitalGoButton) == 0)        return (Go);
    if ((digitalChgButton) == 0)       return (Chg);
  */
  if (Serial.available() > 0)
  {
    cmd = Serial.read();
    //    Serial.print("Recieved cmd "); Serial.println(cmd);
  }

  if (cmd == 's' )
    return (GoStep);
  if (cmd == 'S' )
    return (GoStep);

  return (nobutton);
}

boolean guardCheck(void)
{
  /* commented out until hardware is designed
    if (!digitalRead(guard1) && !digitalRead(guard2))
    return (true);//Unlocked, clear to go
    else
    return false;//Locked, don't go
  */
  return (true);
}

void loop()
{
  unsigned long lastMillis;
  enum cmd lcmd;
  enum mode lmode = Sides;
  float tmpfloat;

  lcmd = readButtons();// Read button inputs if any    + - Go Chg mode

  if ( millis() - lastMillis > 200 )
  {
    lastMillis = millis();
    if ( lmode == Sides )  //number of surfaces
    {
      switch (lcmd)
      {
        case increase:
          {
            faces++;
            break;
          }
        case decrease:
          {
            faces--;
            if (faces < 2)
            {
              faces = 1; //1 rotate one turn
//              myStepper.setMaxSpeed(cuttingSpeed);
            }
            else
//              myStepper.setMaxSpeed(movingSpeed);
            break;
          }
        case Chg:
          {
            lmode == Angle; //switch to angle mode
//            myStepper.setMaxSpeed(movingSpeed);// used i angle mode
            break;
          }
        case Go:
          {
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON
            anglePos += nrOfStepsPerRev / faces;
            myStepper.runToNewPosition(anglePos);//Blocking until done
            break;
          }
        case GoStep:
          {
            Serial.print("GoStep received. ");
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

            Serial.print("Stepping to step "); Serial.println(currentStep + 1);
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            currentStep %= faces;
            Serial.print("anglePos = "); Serial.println( anglePos);
            tmpfloat = 360 * float(currentStep) / float(faces);
            Serial.print("Angle = "); Serial.println( tmpfloat);

            myStepper.runToNewPosition(anglePos);//Blocking until done
            while (Serial.available() )//Pretyping commands not allowed
              Serial.read();// Empty buffer to awoid runaway.

            Serial.println("Returned from runToNewPosition.");
            //            myStepper.runToPosition(anglePos);//Blocking until done

            if (currentStep == 0)// Back on zero position, update AccelStepper position!!!
              myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            break;
          }
        default:
          break;
      }//end of switch
    }//end of "if (lmode == Sides)"
    else if ( lmode == Angle )  // Angle per step
    {
      switch (lcmd)
      {
        case increase:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            break;
          }
        case decrease:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            if (faces < 1) faces = 1; //1 rotate one turn
            break;
          }
        case Chg:
          {
            lmode == Sides; //switch to sides mode
            //          goFlag = false;//
            break;
          }
        case Go:
          {
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

//            myStepper.setMaxSpeed(movingSpeed);
            //            myStepper.runToNewPosition(anglePos);//Blocking until done
            myStepper.moveTo(anglePos);//Blocking until done
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            break;
          }
        default:
          break;
      }
    }
  }
  //  if (guardCheck())
  //  {
  //    Serial.print("!");
  //myStepper.run();
  //  }
}// End of loop
/*
  moveTo KEYWORD2
  move  KEYWORD2
  run KEYWORD2
  runSpeed  KEYWORD2
  setMaxSpeed KEYWORD2
  setAcceleration KEYWORD2
  setSpeed  KEYWORD2
  speed KEYWORD2
  distanceToGo  KEYWORD2
  targetPosition  KEYWORD2
  currentPosition KEYWORD2
  setCurrentPosition  KEYWORD2
  runToPosition KEYWORD2
  runSpeedToPosition  KEYWORD2
  runToNewPosition  KEYWORD2
  stop  KEYWORD2
  disableOutputs  KEYWORD2
  enableOutputs KEYWORD2
  setMinPulseWidth  KEYWORD2
  setEnablePin  KEYWORD2
  setPinsInverted KEYWORD2
  maxSpeed  KEYWORD2

  enum flag {const1, const2, ..., constN};
  By default, const1 is 0, const2 is 1 and so on. You can change default values of enum elements during declaration (if necessary).

  // Changing default values of enum constants
  enum suit {
  club = 0,
  diamonds = 10,
  hearts = 20,
  spades = 3,
  };
*/
  myStepper.setMaxSpeed(100000L);

That is quite a bit faster than the library is capable of.

From the AccelStepper library documentation:

Performance
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.

Thanks gF.
Haha, I thought something was wrong when increasing the numbers but not experiencing any increasing speed.
I was plowing through various documentation of Accelstepper not long ago but didn't find the page I liked. I'll check Your link and se what it says about acceleration. Microstep 32 is used and every increase of acceleration is accepted, performing well... But somewhere there must be a limit...

The max number of steps that can be sent is ~4k but the actual max for any patricular project is also dependent on other factors such as the load and your code.

Determining the max speed and acceleration for your project will require testing.
Start real slow and set it up so you can determine if any steps have been lost.
Slowly increase speed and/or acceleration repeating the test as necessary until it starts dropping steps then back it down 15-20% .
The first time I did so I found it was much slower than I had hoped. :frowning_face:

I did quite some testing and it looks like there's no upper limit for speed, nor for acceleration. This without load. As the rotating table will be mounted on a mini mill it's natural that during cutting the speed has to be limited in order not to crash mill bits.

How are you measuring speed?

Have you tried the MobaTools stepper library. I find it easier to use than AccelStepper and perhaps you can get more speed from your motors using MobaTools. It is available via the IDE library manager and has pretty good documentation.

Saving millis before accelstepper goes to work and then printing millis() - prevMillis. The movement is all the time 1 revolution.
Code below. Look for the GoStep in the switch/case.

#include<arduino.h>

//I2C for LCD
#include <AccelStepper.h>
#include <Wire.h>
//#include <hd44780.h>
//#include <hd44780ioClass/hd44780_I2Cexp.h>

//hd44780_I2Cexp mylcd; // declare lcd object: auto locate & config exapander chip

AccelStepper myStepper (1, 6, 7);

// LCD geometry
#define LCD_COLS 16
#define LCD_ROWS 2

enum mode {Sides, Angle };
int faces = 4;
//unsigned long nrOfStepsPerRev = 90L * 200L * 32L; // microstep 32 & rotating table
unsigned long nrOfStepsPerRev = 200 * 32 * 4; // microstep 32 & testing stepper 1 rev 4 sides
unsigned long currentStep;

enum cmd {increase, decrease, Go, Chg, GoStep, nobutton};
unsigned long anglePos;

void setup() {
  Serial.begin(115200);
  Serial.println("Rotation ");
  /*  //1Hz 90% dutycycle
    pinMode(9, OUTPUT);                               // Set digital pin 9 (D9) to an output
    TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11);  // Enable the PWM output OC1A on digital pins 9 and invert output
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12);     // Set fast PWM and prescaler of 256 on timer 1
    ICR1 = 62499;                                     // Set the PWM frequency to 1Hz: 16MHz/(256 * 1Hz) - 1 = 62499
    OCR1A = 6249;                                     // Set the duty-cycle to 10%: 62499 / 10 = 6249

    pinMode(10, OUTPUT);                               // 1 Hz pulse output on digital pin 9 (D9)
  */  pinMode(13, OUTPUT); digitalWrite(13, LOW);// Make board LED go off
  delay(10);//allow pwm timers to start

  //  myStepper.begin();
  myStepper.setMaxSpeed(4000);
  myStepper.setAcceleration(30000);

#define digitalIncreaseButton 2
  pinMode (digitalIncreaseButton, OUTPUT);
#define digitalDecreaseButton 3
  pinMode (digitalDecreaseButton, OUTPUT);
#define digitalChgButton 4
  pinMode(digitalChgButton, OUTPUT);
#define digitalGoButton 5
  pinMode(digitalChgButton, OUTPUT);
#define guard1 6
#define guard2 7

#define cuttingSpeed 100 // when cutting during rotation
#define movingSpeed 500 //when moving without cutting

  /*
       int status;
    status = mylcd.begin(LCD_COLS, LCD_ROWS);
    if (status) // non zero status means it was unsuccesful
    {
      status = -status; // convert negative status value to positive number

      // begin() failed so blink error code using the onboard LED if possible
      hd44780::fatalError(status); // does not return
    }
    mylcd.clear();
  */
  // Print start message to the LCD
  /*  mylcd.print("221118a Rotating");
    delay(5000);
    mylcd.print("Running");
    delay(1000);
  */
}

enum cmd readButtons(void)
{
  char cmd = 'q';
  /*
    if ((digitalIncreaseButton) == 0)  return (increase);
    if ((digitalDecreaseButton) == 0)  return (decrease);
    if ((digitalGoButton) == 0)        return (Go);
    if ((digitalChgButton) == 0)       return (Chg);
  */
  if (Serial.available() > 0)
  {
    cmd = Serial.read();
    //    Serial.print("Recieved cmd "); Serial.println(cmd);
  }

  if (cmd == 's' )
    return (GoStep);
  if (cmd == 'S' )
    return (GoStep);

  return (nobutton);
}

boolean guardCheck(void)
{
  /* commented out until hardware is designed
    if (!digitalRead(guard1) && !digitalRead(guard2))
    return (true);//Unlocked, clear to go
    else
    return false;//Locked, don't go
  */
  return (true);
}

void loop()
{
  unsigned long lastMillis;
  enum cmd lcmd;
  enum mode lmode = Sides;
  float tmpfloat;

  lcmd = readButtons();// Read button inputs if any    + - Go Chg mode

  if ( millis() - lastMillis > 200 )
  {
    lastMillis = millis();
    if ( lmode == Sides )  //number of surfaces
    {
      switch (lcmd)
      {
        case increase:
          {
            faces++;
            break;
          }
        case decrease:
          {
            faces--;
            if (faces < 2)
            {
              faces = 1; //1 rotate one turn
              //              myStepper.setMaxSpeed(cuttingSpeed);
            }
            else
              //              myStepper.setMaxSpeed(movingSpeed);
              break;
          }
        case Chg:
          {
            lmode == Angle; //switch to angle mode
            //            myStepper.setMaxSpeed(movingSpeed);// used i angle mode
            break;
          }
        case Go:
          {
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON
            anglePos += nrOfStepsPerRev / faces;
            myStepper.runToNewPosition(anglePos);//Blocking until done
            break;
          }
        case GoStep:
          {
            Serial.print("GoStep received. ");
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

            Serial.print("Stepping to step "); Serial.println(currentStep + 1);
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            currentStep %= faces;
            Serial.print("anglePos = "); Serial.println( anglePos);
            tmpfloat = 360 * float(currentStep) / float(faces);
            Serial.print("Angle = "); Serial.println( tmpfloat);

            lastMillis = millis();
            myStepper.runToNewPosition(anglePos);//Blocking until done
            Serial.print("Runtime "); Serial.println( millis() - lastMillis);
            while (Serial.available() )//Pretyping commands not allowed
              Serial.read();// Empty buffer to awoid runaway.

            Serial.println("Returned from runToNewPosition.");
            //            myStepper.runToPosition(anglePos);//Blocking until done

            if (currentStep == 0)// Back on zero position, update AccelStepper position!!!
              myStepper.setCurrentPosition(0);//Accelstepper ready for a second turn around
            break;
          }
        default:
          break;
      }//end of switch
    }//end of "if (lmode == Sides)"
    else if ( lmode == Angle )  // Angle per step
    {
      switch (lcmd)
      {
        case increase:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            break;
          }
        case decrease:
          {
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            if (faces < 1) faces = 1; //1 rotate one turn
            break;
          }
        case Chg:
          {
            lmode == Sides; //switch to sides mode
            //          goFlag = false;//
            break;
          }
        case Go:
          {
            while (!guardCheck());;//DON*T GO IF LOCKS ARE ON

            //            myStepper.setMaxSpeed(movingSpeed);
            //            myStepper.runToNewPosition(anglePos);//Blocking until done
            myStepper.moveTo(anglePos);//Blocking until done
            anglePos = nrOfStepsPerRev * ++currentStep / faces;
            break;
          }
        default:
          break;
      }
    }
  }
  //  if (guardCheck())
  //  {
  //    Serial.print("!");
  //myStepper.run();
  //  }
}// End of loop
/*
  moveTo KEYWORD2
  move  KEYWORD2
  run KEYWORD2
  runSpeed  KEYWORD2
  setMaxSpeed KEYWORD2
  setAcceleration KEYWORD2
  setSpeed  KEYWORD2
  speed KEYWORD2
  distanceToGo  KEYWORD2
  targetPosition  KEYWORD2z
  currentPosition KEYWORD2
  setCurrentPosition  KEYWORD2
  runToPosition KEYWORD2
  runSpeedToPosition  KEYWORD2
  runToNewPosition  KEYWORD2
  stop  KEYWORD2
  disableOutputs  KEYWORD2
  enableOutputs KEYWORD2
  setMinPulseWidth  KEYWORD2
  setEnablePin  KEYWORD2
  setPinsInverted KEYWORD2
  maxSpeed  KEYWORD2

  enum flag {const1, const2, ..., constN};
  By default, const1 is 0, const2 is 1 and so on. You can change default values of enum elements during declaration (if necessary).

  // Changing default values of enum constants
  enum suit {
  club = 0,
  diamonds = 10,
  hearts = 20,
  spades = 3,
  };
*/

No, but I've seen the name mentioned in forum topics. Thanks for recommending it!
Getting the stepping working some mechanical mount of the stepper to the mill needs to be designed. Then I will be in real business evaluating, and likely adjusting things.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.