< Return to JoshWhitman.com Home Page

Arduino Code to Speed-Test a Stepper Motor

Revised version of the program I wrote for Arduino in my Stepper Speed Test video on YouTube.

int stepPin = 3; //Set to whatever pin will trigger steps.
int dirPin = 2; //Set to the pin that tells the stepper driver if it's forward or backward.
int enablePin = 4; //
unsigned long rpm = 300; //Target max RPM of the stepper for this test.
unsigned long stepsPerRevolution = 200; //Enter the number of steps for your motor to make a full revolution.
bool forward = true; //Toggle to switch motor direction.
unsigned long accelTime = 2; //Second to accelerate the motor up to the max RPM (use 0 to just start the motor at full speed)

unsigned long firstStamp; //When the warmup began.
unsigned long lastStamp; //Stamp from the previous toggle.
unsigned long curStamp; //Stamp from the current iteration.
unsigned long rampTime = accelTime * 1000000; //How long to accelerate in microseconds.
bool warmup = true; //Track if we've made it through the initial acceleration stage or not.
bool pinOn = false;
unsigned long toggleTime;

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enablePin, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(stepPin, pinOn); //Set the step pin low.
  digitalWrite(dirPin, forward); //Set the direction.
  digitalWrite(enablePin, LOW); //Pull the enable pin low to turn on the stepper driver.  
  firstStamp = lastStamp = micros(); //Note the start time.

  //Determine the number of microseconds per toggle of the step pin at the target RPM.
  toggleTime = 60000000; //Number of micros in one minute
  toggleTime /= rpm; //divid by number of times per minute to revolve
  toggleTime /= stepsPerRevolution; //divide by number of steps to complete a full revolution.  Now we have the number of micros per step.
  toggleTime /= 2; //Cut in half so half the time it's on, half off.
}

void loop() {
  curStamp = micros(); //Get the timestamp for this loop.

  unsigned long toggleTarget = toggleTime;
  
  if (warmup){ //Still accelerating at the outset, we'll increase the toggle time proportionally.
    if (curStamp - firstStamp > rampTime) warmup = false; //We've amde it to the end of the speed ramp.
    else {
      //Increase the toggle time proportional to how far along the acceleration ramp we are, longer at the start, no increase at the end.
      unsigned long tempToggle = (rampTime - (curStamp - firstStamp)) * toggleTime / rampTime; //less and less added time to the toggle.
      toggleTarget += tempToggle; //Add this extra toggle delay to the motor start.
    }
  }

  unsigned long elapsed = curStamp - lastStamp;
  if (elapsed >= toggleTarget) {
    //Toggle the step pin.
    pinOn = !pinOn;
    digitalWrite(stepPin, pinOn);
    digitalWrite(LED_BUILTIN, pinOn);

    //Update the tracking variables.
    lastStamp += toggleTarget; //Advance the stamp by the amount of time that was meant to have occurred between pins.
  }
}