Manually controlling bipolar stepper motor with Arduino and EasyDriver

Manually controlling bipolar stepper motor with Arduino and EasyDriver


Stepper motors are great for accurate positioning because they move in discrete steps – a feature that makes them very appropriate for CNC software control. But every once in a while you have an application where you need to press a button and rotate some kind of a jig at a preset angle or move something a preset distance if it’s a stepper-driven linear stage. So, I decided to modify an earlier Arduino sketch I wrote for testing the world’s smallest stepper motor to make it a bit more useful (and clean any bugs in the process). Keep reading to see what came out …
Shout outs to forum user Yellow who in this thread provided an inspiration for the code modification. I had another project in mind but was dragging my foot for a long time, and seeing that someone else can also use results of your work provides a great motivation, so thanks, Yellow!


Arduino sketch for the manual EasyDriver control of bipolar stepper motors

Also see the code in the post below. The circuit is extremely simple because most of the hard work of commutating the windings of the stepper is done by the Allegro A3967 motor controller chip, mounted on the EasyDriver board. The Arduino can be any incarnation thereof. I used Nano and I had to move the outputs away from the D0 and D1 because it was messing with uploads (I think it’s only a problem with Nano specifically) but any Arduino will do – there are only 8 digital I/Os and one analog.

Circuit diagram for the EasyDriver + Arduino manual stepper control

Circuit diagram for the EasyDriver + Arduino manual stepper control

The parts list for the project is very short:

  1. Arduino. Any type will be adequate.
  2. EasyDriver board, populated. Please check with the author, Brian Schmalz on the best source of them.
  3. Bipolar stepper motor i.e. one with 4 leads. 6- and 8-lead unipolar stepper can also be converted to bipolar by connecting the proper ends of the windings together and floating the center point – not a very difficult task but outside of the scope of this post
  4. 2 x pushbuttons for LEFT/RIGH a.k.a. UP/DOWN a.k.a CW/CCW control
  5. 3 x LED for indicators, preferably different color
  6. 3 x 510 Ohm current limiting resistors for the LEDs
  7. 2 x 10K Ohm pullup resistors for the buttons
  8. 1 x 10K Ohm potentiometer (anything between 1K and 100K is fine)
  9. Couple of lines in the Arduino code you may want to look at and adjust to your needs are highlighted in the code below.
    Note the int stepsPassedMax = 160; line (line 28).Here 160 means 20 full steps in 1/8th microstepping mode. It just happens that the micro stepper I was using earlier (not the one on the video) had 20 SPR (Steps Per Revolution) and this would have been one 360 degree rotation of the motor’s shaft. If you have a better stepper (200SPR is common), it may only be 1/10th of one rotation – check with the datahseet on the motor and adjust the stepsPassedMax accordingly or send, say, 200*8= 1600 steps and see if the motor completes a full 360 degree revolution if you don’t have a datasheet and suspect that this is a 200SPR motor.
    Another adjustment you may make is the desired RPMs or, more appropriately, angular speed since you may not even need a full rotation, hence no R in RPM:
    The smaller the stepDelay variable, the faster the motor turns. See lines 36 and 60 in the code below.

    Below is the complete code:

    /* 
    EasyDriver stepper test sketch
     
    Circuit diagram and description at http://elabz.com/manually-controlling-bipolar-stepper-motor-with-arduino-and-esaydriver/
    
     */
    
    // constants won't change. They're used here to 
    // set pin numbers:
    const byte stepUpPin = 4;     // the number of the step pin
    const byte stepDownPin = 5;     // the number of the step pin
    const byte stepOut = 2;
    const byte directionOut = 3;
    const byte ledPin =  12;      // pin # for direction indicator LED 
    const byte readyPin =  11;      //pin # for LED that comes on when all the steps have been completed
    const byte inMotionPin = 10; // pin # for the LED that light up when the stepper is supposed to be still moving
    const byte ratePin = 0; // A0 - analog 0 pin on Arduino to control the stepping dealy (i.e. RPMs)
    const byte enablePin = 6; // turn EasyDriver off when not turning (saves power but ONLY use when there's no need to hold position)
    
    // Variables will change:
    byte ledState = LOW;         // the current state of the output pin
    byte lastStepUpButtonState = HIGH;   // the previous reading from the step UP pin
    byte lastStepDownButtonState = HIGH;   // the previous reading from the step DOWN pin
    byte directionState=HIGH;             // the current direction
    byte stepUpState=HIGH;             // the current state of UP button 
    byte stepDownState=HIGH;             // the current state of DOWN button
    int stepsPassed = 0; //how many steps?
    int stepsPassedMax = 160; // trying to calculate steps per revolution (remember the microstepping settings 1/8th is default)
    // most small and micro steppers, especially those that came from a CD- or DVD-R/RW drives 
    // have 20 steps per revolution. So 160 mircosteps should make the motor spin 360 degrees once.
    
    long lastStepUpDebounceTime = 0;  // the last time the output pin was toggled
    long lastStepDownDebounceTime = 0;  // the last time the output pin was toggled
    long debounceDelay = 50;    // the debounce time in ms; increase if the output flickers
    
    long stepDelayBase = 1; // 1ms base rate. Multiply by the reading from the RATE potentiometer for actual step delay
    long stepDelay; // 
    long lastStepTime = 0; // last time the step signal was sent
    
    void setup() {
      pinMode(stepUpPin, INPUT);
      pinMode(stepDownPin, INPUT);
      pinMode(ratePin, INPUT); 
      pinMode(stepOut, OUTPUT);  
      pinMode(directionOut, OUTPUT);
      pinMode(ledPin, OUTPUT);
      pinMode(readyPin, OUTPUT);
      pinMode(inMotionPin, OUTPUT);
      pinMode(enablePin, OUTPUT);
      digitalWrite(readyPin, HIGH); // turn OFF all LEDs in the beginning
      digitalWrite(inMotionPin, HIGH);  // turn OFF all LEDs in the beginning
      digitalWrite(ledPin, HIGH); // turn OFF all LEDs in the beginning
    }
    
    void loop() {
    
    // read the state of the switch into a local variable:
    int readingStepUp = digitalRead(stepUpPin);
    int readingStepDown = digitalRead(stepDownPin);
    stepDelay = analogRead(ratePin) * stepDelayBase/50;
    if(stepDelay < 1) stepDelay = 1; // reality check - a pot can read 0 and then it would mean infinite RMP - not possible
    
    if(readingStepUp == LOW || readingStepDown == LOW) { // only read buttons if either one of them is LOW
    
      // If the switch changed, due to noise or pressing:
      if (readingStepUp != lastStepUpButtonState) {
        // reset the debouncing timer
        lastStepUpDebounceTime = millis();
        lastStepUpButtonState = readingStepUp;
      } 
      
      if ((millis() - lastStepUpDebounceTime) > debounceDelay) {
        // whatever the reading is at, it's been there for longer
        // than the debounce delay, so take it as the actual current state:
        lastStepUpButtonState = readingStepUp;
        lastStepUpDebounceTime = millis();
        stepUpState = readingStepUp;
      }
    
    
    
      // If the switch changed, due to noise or pressing:
      if (readingStepDown != lastStepDownButtonState) {
        // reset the debouncing timer
        lastStepDownDebounceTime = millis();
        lastStepDownButtonState = readingStepDown;
      } 
      
      if ((millis() - lastStepDownDebounceTime) > debounceDelay) {
        // whatever the reading is at, it's been there for longer
        // than the debounce delay, so take it as the actual current state:
        lastStepDownButtonState = readingStepDown;
        lastStepDownDebounceTime = millis();    
        stepDownState = readingStepDown;
    
      }
    
      
    }else{
     stepUpState = HIGH;
     stepDownState = HIGH;
     
    } // end of if block that reads button states
      
    if(stepsPassed == 0 ) { // if the previous command has completed, make the direction decision 
        if(stepUpState == LOW || stepDownState == LOW) { 
          if(stepUpState == LOW && stepDownState == LOW) { directionState = LOW; } // why are you holding both UP and DOWN buttons?
          if(stepUpState == LOW && stepDownState == HIGH) { directionState = HIGH;} // go up
          if(stepUpState == HIGH && stepDownState == LOW) { directionState = LOW;} // go down
          stepsPassed = stepsPassedMax+1;
      }
     } 
      
    
    if(stepsPassed > 0 ) // send step signals now
    {
      digitalWrite(enablePin, LOW); // wake up
      digitalWrite(ledPin, directionState); // set proper direction
      digitalWrite(directionOut, directionState); 
      if((millis() - lastStepTime) > stepDelay) // delay expired, send another step
        {
            digitalWrite(stepOut, HIGH);
            stepsPassed--;
            lastStepTime = millis();
        }else
        {
          // time for one step not yet expired, hold the STEP signal low 
          digitalWrite(stepOut, LOW);
        }
    }else{
     digitalWrite(enablePin, HIGH); // go to sleep
    
    }
    
    if(stepsPassed == 0) { 
     digitalWrite(readyPin, LOW);
     digitalWrite(inMotionPin, HIGH); 
    
     }else{
     digitalWrite(readyPin, HIGH);
     digitalWrite(inMotionPin, LOW); 
     }
    
    }
    
    

    As always, I would appreciate your comments here and your questions and requests for help in the forums, Help section. Also, the Motor Control section is great for any discussions about this project since it involves stepper motor control.

23 Responses to “Manually controlling bipolar stepper motor with Arduino and EasyDriver”

  • Akshay:

    Great !
    Exactly what I was searching, very unique on the whole Internet
    I have small query

    Its that can I use arduino UNO instead off Nano ??

  • Akshay:

    Or may be u can help with pin diagram of arduino uno please

    It would be a great help if realte the arduino Uno diagram with ur diagram of arduino, easy drivr ckt and stppr motr.

    http://forum.arduino.cc/index.php/topic,146315.0.html

    Please do reply
    thank you

  • Akshay:

    Could you please please help me out with the new Schematic for UNO board. Can you please
    possibly post it.

    Would be a great help to me

    Thank you

  • Akshay, the schematic IS ALREADY for an UNO. I do use Nano on the video but the schematic is drawn as if you would connect it to an Arduino UNO. Since all the inputs/outputs have standardized names, you can use the exact same schematics with any Arduino. Just follow the actual locations of the pins on the board. They are clearly labeled on UNO, so you should have problem connecting to it.

  • Akshay:

    Thanks a lot !
    Surely will let u knw once I finished application of ur project in my project
    I already credit your Name for it
    Thank You :)

  • Sandeep:

    Which buttons are used ?

    Press to ON and Press to OFF (switch button=tact)
    OR
    Keep button Pressed to ON and release to OFF

  • Bill Parker:

    Hi
    Would it be possible to have an lcd or serial lcd keeping the total of steps for this as I don’t have the knowledge to do it but want to know if possible as i have the ideal project for this if it can keep tally going cw and decreasing going ccw.
    Cheers
    Bill

    • Hi Bill, thank you for stopping by! It is certainly possible and very easy to do. Arduino has enough I/O lines left to control an alphanumeric LCD (does not need to be serial either). I am not sure I can scramble enough time to build a circuit like this right now but you may want to look into the LCD sample code provided with the Arduino IDE. Inside the code of the samples you’ll find the LCD hookup circuit. All you need to do is to output the numeric value of the step count multiplied by distance per step.
      I don’t want to trivialize the task, especially if you don’t have prior experience programming Arduino, but if you were going to build the stepper control circuit in the first place, the LCD is not a huge addition. Once again, look up the sample code provided with Arduino in the LiquidCrystal library. Or here, obviously: http://arduino.cc/en/Tutorial/LiquidCrystal

  • Bill Parker:

    I would like the above circuit so i can tell the amount of pulses over a given x axis length to divide length by pulses to give me pulses required per mm of movement.
    Cheers
    Bill

  • Bill:

    Manually controlling bipolar stepper motor with Arduino and EasyDriver

    Hi I asked if it was possible to add an lcd to the above page and the reply was we dont have time. Please may i ask again as I am so interested in this one thing but can not work it out. I am 55 my first electronics magazine was everyday electronics 1974 i have always played with electronics but 4 years ago i fell 3 mtrs onto my head on a stone wall then 2 mtrs to the floor i have been in and out of hospital as i have seizures everyday and they have damaged my spine so i have had a spinal operation and my memory is so bad i can get lost in our 3 bedroom house and so have carers 2 times a week to give my wife a break as i can not go out alone. I still want to add a lcd so i can use old printer part that i don’t know the ratio of belt and motor so i can move it forwards say 300mm and have a distance and a pulse count total so i can divide it to give me pulses per mm i can then use 2 axis for moving a drill to drill holes exact places.It would be so appreciated if some body could find the time to alter the code fo r me i have lcd’s and i have serial 2×16 lcd’s i don’t call this a sob story but i have given so many years to youth groups and charity work i would love a little help for once. Please do not print my name as i would not feel happy having to beg for help.
    Thanking you
    Cheers
    Bill

    • Hello Bill, sorry to hear about your accident. I hope you make a full recovery soon, although from what you’ve described it will not be quick or easy. I am not a spring chicken myself and understand full well that things get harder with age. I just think that a human body is a wonderful self-healing machine, but you gotta give it time.

      Getting back to your task at hand: since this is a one-time use (once you know parameters of the motor, you don’t need to repeat the tests), building an electronic device with any kind of an interface, such as an LCD, is really an overkill. All of that information may already be available either via the motor’s datasheet obtainable online or oftentimes simply printed right on the motor itself. Look for “SPR” – Steps Per Revolution – and you may get lucky and take the info you need right from the motor’s casing. If you want, post any kind of markings you can find on the motor (hopefully, including the manufacturer’s name) and I’ll help you locate the datasheet and interpret the motor’s parameters. Since this is from a printer, you’re probably looking at a lower end of the SPR spectrum – chances are, this is a 40 to 100 SPR motor. But, again, if you can provide more info, I can narrow it down.

      With all that said, judging by your further description of the task at hand, what you actually need for accurate and repeatable drilling is a CNC router. If you are not familiar with CNC (Computer Numeric Control), look up some info on it online. There is a ton of info available online, and there are some nice ready-made CNC routers as well kits to build yourself one. There are also great many DIY router builds out there, check out Intsructables for DIY designs people post online http://www.instructables.com/tag/type-id/?sort=none&q=CNC+router and what you can do with them (not just drilling). Even I built some miniature ones from remnants of old DVD drives :) , so it does not have to be overly complicated or expensive.

      So, anyway, give a CNC router a thought and in the meantime, let me know more about the motor(s), and I’ll simply help you lookup the info on it. I really don’t see a reason to build a whole device for that purpose.

      Cheers!

  • Bill:

    Thank you admin for your reply and I do understand what you say. I am already working on a cnc I have just got my bearings and linear bearings yesterday so i can now get all my measurements sorted to have my steal work cnc cut and powder coated. I have been an industrial electrician all my working life and never thought cnc electrically and mechanically was as easy as it is but the coding is another matter. I have used chemicals to etch pcb’s over the years but now want to build a cnc pcb router just for the fun of it as i don’t make pcb’s these days as i like to play with arduino and just try to alter a sketch to my needs. I hope one day to be able to contact you again to say I have built my cnc and it is working fine.
    Cheers
    Bill

    • Hi Bill, good luck with your CNC build! I ended up getting myself a kit-built CNC router but building it from scratch like you’re doing it, sounds even more fun. If you are not deterred by cutting your steel and power coating, compared to that, programming the router will be a breeze. G-code programs are simply text files that can by read and parsed (and understood) manually if need be. There’s also a lot of free software out there that handles all stages of CNC work, from creating the part in a CAD, to outputting the G-Code, to controlling the actual hardware, so you may not even need to get all the way down to the actual coding if you don’t like it.

  • Chris:

    Hi!
    First, thanks so much for sharing this online. It has been a huge help for me in a current university project in which I am building a large rig for moving a light to simulate solar patterns. It was just what I needed and saved me countless hours of working through this on my own (I am no expert with arduino by any means and am just starting to get comfortable with it).
    I just have one question regarding your code and controlling the RPM:
    I can’t seem to figure out which number I change in order to speed the motor up. Could you please give me any advice on this? I read through your instructions above, but no matter what I do, the motor seems to be rotating at the same rate.
    Also, I was wondering if you have any tips for possibly allowing each button to dictate a different control? for example, button one is pushed and the motor rotates 5 full turns at a slow RPM, when the second button is pushed, the motor rotates the opposite way, but at a much faster RPM. I am thinking along the lines of moving something slowly with the motor, then having it return to its “home” position much quicker.

    Thanks so much!

    • Hi Chris, thanks for stopping by! Hope you’re holding up well in those polar vortexes :)
      The speed control us on lines 36 and 60. The multiplication coefficient on line 36 is 1 but can go lower than that (it’s a long type variable). You can make it 0.5 for twice the speed. You can also alter line 60

      stepDelay = analogRead(ratePin) * stepDelayBase/50;

      And make it, say

      stepDelay = analogRead(ratePin) * stepDelayBase/100;

      to make it turn twice as fast.

      As far as using different speeds to to a fro movements, you can insert a statement altering the step delay somewhere at line 117

      if ( directionState ) {
          stepDelay = stepDelay/2;
      }
      

      It should make it run twice as fast in one direction than in the opposite. You just have to adjust to real life which direction you want faster. To reverse the selection, do if (!directionState) instead.

      I have disassembled the test rig, cannot check the code right now, but it should work.

      Cheers!

  • Chris:

    Fantastic!
    Thank you so much! I will give it a go today.
    When the project ha developed further I will most definitely share my work on the forums.

    Best,

    Chris

  • Mark N:

    Spot on. exactly what I want. Just a fwd/Rev speed control, stepper motor to drive the X axis on my Milling machine. Been looking for a while now.
    Heartfelt Thanks.
    Mark N.

    • Thank you for stopping by, Mark! If you are using the same hardware, just be sure to not overload the driver IC – this is not the most powerful stepper driver in the world. I think it can do 750mW @ 24V – sufficient for a small milling machine, not enough for anything big.
      Cheers!

Leave a Reply

Or use the Forums ! If your comment is a question, please consider posting it to a matching section of our Electronics Forums. The forums allow for a more natural conversation flow, especially if multiple replies are required. Additionally, you'll be able to style your writing (bold font, italics etc.) and post images which can help with a good answer.

Notify me of followup comments via e-mail. You can also subscribe without commenting.

Tools

Coming soon ...

Recent Comments
  • admin: Thanks! Glad you made it work! This way of driving a bipolar stepper was just to prove a point that it’s...
  • Matt: Hey bud I got this all to work after some trial and error, now how ever I would like to drive 2 steppers for my...
  • admin: How did you measure the 225mA output? Did you connect 4 diodes (regular rectifier diodes, not laser of course)...
  • David: Hello. I have extracted a 5.6mm diode from a 16x DL dvd burner, I already have an AiXiz module and driver...
  • admin: Thank you for stopping by, Mark! If you are using the same hardware, just be sure to not overload the driver...
  • Mark N: Spot on. exactly what I want. Just a fwd/Rev speed control, stepper motor to drive the X axis on my Milling...
  • admin: That’s right – R4 pulls the Enable input of the chip down, and the driver will be off until...
  • Nate: I have a question on the R3/R4 and ttl. So you say that if R4 is installed its normally off. So the laser is...
  • admin: Thanks for stopping by, Tom. I don’t have a ready-made DXF but the Eagle board file attached above in...
  • admin: It does need to be on a ferrous material for a great increase in performance. Although I do believe you can...
Meta