Simple Stepper Program

I wrote a very simple program to demonstrate stepper control using a Polulu A4988 stepper driver. It should also work with any stepper driver that just needs step and direction signals from an Arduino.

I have included it in response to several queries and it seemed it would be easier to create this Thread and then just add a link to it.

Edit 10 Dec 2014 - readers may also be interested in this note about Stepper Motor Basics

If all you want to do is demonstrate that a motor can work this code is ideal.
Edit 23 Jul 2016 - increased millisBetweenSteps to 250 for slower running

// testing a stepper motor with a Pololu A4988 driver board or equivalent
// on an Uno the onboard led will flash with each step
// this version uses delay() to manage timing

byte directionPin = 9;
byte stepPin = 8;
int numberOfSteps = 100;
byte ledPin = 13;
int pulseWidthMicros = 20;  // microseconds
int millisbetweenSteps = 250; // milliseconds - or try 1000 for slower steps


void setup() { 

  Serial.begin(9600);
  Serial.println("Starting StepperTest");
  digitalWrite(ledPin, LOW);
  
  delay(2000);

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  
 
  digitalWrite(directionPin, HIGH);
  for(int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
    digitalWrite(stepPin, LOW);
    
    delay(millisbetweenSteps);
    
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
  
  delay(3000);
  

  digitalWrite(directionPin, LOW);
  for(int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    // delayMicroseconds(pulseWidthMicros); // probably not needed
    digitalWrite(stepPin, LOW);
    
    delay(millisbetweenSteps);
    
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
}

void loop() { 
}

More recently there has been a request for a more complete example using buttons to control a stepper motor and I have now created a new version which also uses millis() rather than delay() for timing. Following is the code for this version

EDIT (13 Nov 2014) to correct serious error. Humble apologies. Instead of 2 separate programs I had accidentally repeated the first program. The correct second program is now here

// testing a stepper motor with a Pololu A4988 driver board or equivalent

// this version uses millis() to manage timing rather than delay()
// and the movement is determined by a pair of momentary push switches
// press one and it turns CW, press the other and it turns CCW

byte directionPin = 9;
byte stepPin = 8;

byte buttonCWpin = 10;
byte buttonCCWpin = 11;

boolean buttonCWpressed = false;
boolean buttonCCWpressed = false;

byte ledPin = 13;

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds

void setup() { 

     Serial.begin(9600);
     Serial.println("Starting Stepper Demo with millis()");

     pinMode(directionPin, OUTPUT);
     pinMode(stepPin, OUTPUT);
     pinMode(ledPin, OUTPUT);
     
     pinMode(buttonCWpin, INPUT_PULLUP);
     pinMode(buttonCCWpin, INPUT_PULLUP);
     
}

void loop() { 
    
    curMillis = millis();
    readButtons();
    actOnButtons();
    
}

void readButtons() {
    
    buttonCCWpressed = false;
    buttonCWpressed = false;
    
    if (digitalRead(buttonCWpin) == LOW) {
        buttonCWpressed = true;
    }
    if (digitalRead(buttonCCWpin) == LOW) {
        buttonCCWpressed = true;
    }
}

void actOnButtons() {
    if (buttonCWpressed == true) {
        digitalWrite(directionPin, LOW);
        singleStep();
    }
    if (buttonCCWpressed == true) {
        digitalWrite(directionPin, HIGH);
        singleStep();
    }
}

void singleStep() {
    if (curMillis - prevStepMillis >= millisBetweenSteps) {
            // next 2 lines changed 28 Nov 2018
        //prevStepMillis += millisBetweenSteps;
        prevStepMillis = curMillis;
        digitalWrite(stepPin, HIGH);
        digitalWrite(stepPin, LOW);
    }
}

...R
EDIT 28 Nov 2018. I changed to using prevStepMillis = curMIllis; because with the other method the time could get out of sync if there was a long interval with no button pressed.

5 Likes

Hi Robin2,
But why is the whole program in the SETUP loop?? I did some work with steppers years ago using the old Philips SAA1027 (I think), way before Arduinos and the like. But I have just ordered a couple of cheap Chinese A4899 modules (about £3 the pair) so will be playing with them again soon (3 weeks from China), and will give your code a try, I have a few old steppers from printers, etc.

I would like a robot that goes where you tell it, and not just somewhere near!

Regards

Mel.

Cactusface:
But why is the whole program in the SETUP loop??

It is just a very basic test program to prove that the motor works. Move it one way. Move it the other way. Stop.

The second program is more typical of normal use.

...R

very nice and simple will be very good for testing all the stepper I have laying around

Thanks for posting! I'm waiting for components but excited to try this!

I do have another question. Robin - how did you come up with the 20 microsecond second pulse duration and 25 milliseconds between pulses? Can it be done any faster? One of my steppers has 100 steps, so it would be good if I could step it more quickly.

dptdpt:
I do have another question. Robin - how did you come up with the 20 microsecond second pulse duration and 25 milliseconds between pulses? Can it be done any faster? One of my steppers has 100 steps, so it would be good if I could step it more quickly.

This a THIRD thread where you have asked questions about your project. Why not keep all your own info and questions in one place?

The 20 microseconds is not really needed - most stepper drivers just need a pulse of a few microseconds and there is enough delay within the digitalWrite() function for that. Initially I tried it at 20 usecs just being cautious.

The 25 millisecs is just trial and error. Experiment with any values you like - but only AFTER you have it working with 25 msecs. Stepper motors will generally work at higher speeds if they are supplied with higher voltages.

...R

Sorry Robin! I thought about putting my question in my other thread, but thought it might be of interest to anyone who used your program. I'd be happy to delete it if you disagree. On most forums, people prefer for you to break up questions into different topics/threads based on relevance. It makes the forum more useful as a knowledgebase if threads stick to a single topic as much as possible. It would make it a lot easier for me, though, if I just put everything in a single "me" thread!

Leave things where they are now, but for the future I suggest you keep things in your main Thread.

I appreciate your consideration of other Forum users, but it does make it difficult to help you because somebody trying to answer a question in one Thread may not be aware that relevant background info is already in another Thread. You can easily include links in your Thread if you want to cross-reference other Threads.

...R

Hi Robin,
I am a student and I am doing a part of the final project of master thesis. I have Arduino UNO, stepper motor Skidproof Nema17, and stepper motor driver A4988. I tried to run my motor and it is ok. Now I want to change and vary the speed. I know that the speed is linked with the frequency of the pulse signal. Can you give some advice on how to do? Need I others components in addition to the ones I have?
Thank you so much for your availabilty

Marco

marco1990:
Now I want to change and vary the speed.

Just change the value of millisBetweenSteps in my demo programs

You may also be interested in stepper motor basics

...R

@Robin2

Thank you for this useful thread.
Let me know, Can we use the code with driver CWD556 and stepper motor 57HS22 ?

Could you explain to me please why we use always pulse HIGH then delay and then LOW
and what if we use just HIGH
and what is the difference between the first delay and the second delay?

digitalWrite(stepPin, HIGH);

delayMicroseconds(pulseWidthMicros);

digitalWrite(stepPin, LOW);
    
delay(millisbetweenSteps);

Hi daxasd,
Pluse HIGH on it's own will do nothing, it's the LOW to HIGH transition that steps the motor. The time between this, controls how fast the motor moves.

Regards

Mel.

Cactusface:
it's the LOW to HIGH transition that steps the motor. The time between this, controls how fast the motor moves.

This may be a little confusing.

It is the time between successive pulses that controls the speed.

In the example code in Reply #12 the short delayMicroseconds(pulseWidthMicros); determines the width of the HIGH pulse. With many stepper drivers this line can be omitted because the digitalWrite() is slow enough to produce a satisfactory pulse.

The delay(millisBetweenSteps); determines the speed of the motor by setting the number of milliseconds between successinge step pulses.

I'm nearly sure I answered a similar question involving a "driver CWD556 and stepper motor 57HS22" yesterday or the day before.

...R

thanks guys for reply

then what is the difference between using this high and low pulses and using the
Stepper.h library

for example

#include <Stepper.h>
Stepper myStepper(StepsPerRevolution, 8,9,10,11);
Stepper myStepper(StepsPerRevolution, 9,10);
setSpeed(rpms);
step(steps);

also I have seen AccelStepper.h library is it useful?

thanks

They are just 3 different ways of doing much the same thing. Ultimately the libraries have to do what my code does. They just wrap it up in fancy clothes.

The libraries do have a value if you are using a h-bridge to drive a stepper because they take care of the complex series of pulses. But it is much more sensible IMHO to leave that task to a specialized stepper driver and take the load off the Arduino.

As its name implies the AccelStepper library is intended to apply acceleration and deceleration to the motor. If you don't need acceleration and if you have a specilized stepper driver it does not really offer much value IMHO.

...R

1 Like

@Robin2

Thank a lot

then in the case of the stepper.h library is it convenient to use these functions when we use a specialized stepper driver that adjust the pulses and the microsteps manually
or using direct pulses without any library is better in this case.

daxasd:
then in the case of the stepper.h library is it convenient to use these functions when we use a specialized stepper driver that adjust the pulses and the microsteps manually
or using direct pulses without any library is better in this case.

Your question is a bit confusing - especially the bit I have highlighed

And what do you mean by "these functions" ?

I have never used the Stepper library and I am not sure whether it is suitable for controlling a specialized stepper driver. I think the options are DIY or the AccelStepper library.

...R

Be carefull to set the amps on the A4988 as we burned up 3 of them befor we caught on