Driving a Bipolar Stepper Motor with Arduino and ULN2803AG

Driving a Bipolar Stepper Motor with Arduino and ULN2803AG


While I’m getting ready to rip open some 10+ broken DVD-RW drives coming to me from an eBay seller, I though it would be great to have a testbed for the bipolar stepper motors I will harvest from those.

I have a bunch of ULN2803AG Eight Darlington Transistor Arrays with Common Emitters left from past projects and these can sink (but unfortunately not source) peak loads of 600mA (500mA continuous) and are well suited for power application like driving small motors. However, there is a problem with 4-wire bipolar stepper motors: they don’t have the common points of windings wired to the outside which would be needed for providing the motors with power. See the ULN2003 datasheet for more information about the IC: ULN2801,2802,2803,2804 and 2805 Darlington Array datasheet

Still, it looked to me that it would still be possible to make a small bipolar stepper work by floating the voltage using some 22 Ohm resistors to the motor supply voltage (motor you see on the video has 18 Ohm windings, so this was the closest resistor value).

Arduino with ULN2803A Driving a small bipolar stepper motor

Arduino with ULN2803A Driving a small bipolar stepper motor


At first I attempted to use for the motor voltage the same +5V supplied by Arduino but because of the floating middle point the max voltage across each winding was only 1.7V and that was not enough to move the rotor. When the motor supply voltage was increased to +9V (the 9V battery on the picture), things started working. There is still only 4V across each winding at any time it’s energized but it looks enough to make the linear slide move with some force which I hope will be enough for carrying the laser diode housing.
Bipolar stepper with Arduino and ULN2803 - Schematics

Bipolar stepper with Arduino and ULN2803 - Schematics


Here is the schematic of the whole setup and below is the Arduino sketch. Please note that the resistors needed to be at least 1/4W rated but I did not have the 22 Ohm needed for the project and used 1/8W ones. They did get noticeably hot, so it’s not the way to do it in real life.

Additionally, a better way to drive a 4-wire bipolar motor would be to use the quad half-H ICs like SN754410 (on which Arduino’s official bipolar instructions are based) but I thought many hobbyists would appreciate a possibility to make things run using a simpler hookup that ULN chips allow. Also, one $0.60 ULN2803AG chip can actually drive two motors, so it’s pretty much the cheapest way to drive your 4-way bipolar stepper. Please note that another common Darlington Array IC, ULN2003A (similarly priced) has 7 arrays instead of 8 and therefore can only be used to drive one stepper motor per IC.

Driving your 4-wire bipolar stepper via a ULN2803AG is not efficient because you’re wasting pretty much the same amount of energy on heating the resistors that float the median voltage point as you’re using for rotating the motor’s rotor but if efficiency is not your immediate concern, you can use this simple hookup with a little bit of programming that takes into consideration the different HIGH/LOW levels needed to drive the motor if hooked up this way.

In the code that follow below the main principal of driving the motor was changing the state of the ULN2803 outputs in this way:

Pins 1 and 2 represent the winding #1
Pins 3 and 4 represent the winding #2

When 1 is HIGH and 2 is LOW, the voltage across winding #1 is considered positive

When 1 is LOW and 2 is HIGH, the voltage across winding #1 is considered negative

When 1 is HIGH and 2 is HIGH, the voltage across winding #1 is considered zero or winding disabled. This is basically done to conserve motor supply power. It works in exact same way as more logical LOW-LOW but LOW-LOW will draw current through the respective resistors – simply wasteful.

The code below is driving the motor in Half Step Sequence

Here is a link to the zip file with the Arduino sketch for the Arduino IDE
BP_Stepper_ULN2803.pde

// Driving a bipolar stepper motor with Arduino and a ULN2803 
// Octal High Voltage High Current Darlington Transistor Array 
// This example code is in the public domain. Based on several 
// Arduino code samples
// http://elabz.com/

// constants won't change. They're used here to 
// set pin numbers:
const int buttonPin = 2;     // the number of the misc. pushbutton pin
const int buttonForwardPin = 6;     // the number of the misc. pushbutton pin
const int buttonBackwardPin = 7;     // the number of the misc. pushbutton pin
const int ledPin =  13;      // the number of the forward LED pin
const int ledForwardPin =  4;      // the number of the forward LED pin
const int ledBackwardPin =  5;      // the number of the backward LED pin
const int motorPin1 =8;
const int motorPin2 =9;
const int motorPin3 =10;
const int motorPin4 =11;
const int motorDelay=10;

// Variables will change:
int ledForwardState = LOW; // the current state of the forward LED output pin
int ledBackwardState = LOW; // the current state of the forward LED output pin
int buttonState;             // the current reading from the misc input pin
int buttonForwardState;             // the current reading from the forward input pin
int buttonBackwardState;             // the current reading from the backward input pin
int lastButtonState = LOW; 
int lastForwardButtonState = LOW;   // the previous reading from the input pin
int lastBackwardButtonState = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastForwardDebounceTime = 0;  // the last time the output pin was toggled
long lastBackwardDebounceTime = 0;  // the last time the output pin was toggled
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(buttonForwardPin, INPUT);
  pinMode(buttonBackwardPin, INPUT);
  pinMode(ledForwardPin, OUTPUT);
  pinMode(ledBackwardPin, OUTPUT);
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);

}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
  }
  
  // set the LED using the state of the button:
  digitalWrite(ledPin, buttonState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
  
  
    int readingForward = digitalRead(buttonForwardPin);
    int readingBackward = digitalRead(buttonBackwardPin);
  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (readingBackward != lastBackwardButtonState) {
    // reset the debouncing timer
    lastBackwardDebounceTime = millis();
  }   
  
  if (readingForward != lastForwardButtonState) {
    // reset the debouncing timer
    lastForwardDebounceTime = millis();
  } 
  
  if ((millis() - lastForwardDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonForwardState = readingForward;
    lastForwardButtonState = readingForward;
    forward();
}else if ((millis() - lastBackwardDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonBackwardState = readingBackward;
    lastBackwardButtonState = readingBackward;
    backward();
  }else{
   
   stopping(); 
   lastBackwardButtonState = LOW;
   lastForwardButtonState = LOW;
  }
  
  // set the LED using the state of the button:
  digitalWrite(ledPin, buttonState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:

  
  
}

void forward()
{
   digitalWrite(ledForwardPin, HIGH);
  
// HALF STEP  
  
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delay(motorDelay);

  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay);  
  
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay);  
  
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay); 
  
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay); 

  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay); 

  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delay(motorDelay); 
  
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delay(motorDelay); 

}
void backward()
{
  
 digitalWrite(ledBackwardPin, HIGH);
 
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delay(motorDelay); 

  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delay(motorDelay);  
  
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay);  
  
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay); 
  
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay); 

  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay); 

  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
  delay(motorDelay); 
  
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delay(motorDelay); 
  
}

void stopping()
{
  digitalWrite(ledForwardPin, LOW);
  digitalWrite(ledBackwardPin, LOW);
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
}

64 Responses to “Driving a Bipolar Stepper Motor with Arduino and ULN2803AG”

  • [...] only unipolar? And it does not have to be only unipolar either. Here is how to drive (small) bipolar stepper with Arduino and ULN2803 (ULN2003) with schematics and the Arduino code. It all depends on your application and how much money you [...]

  • Shane:

    hey…I tried uploading your code onto my arduino and I’m getting errors.

    sketch_apr22a:64: error: stray ‘\’ in program
    sketch_apr22a:94: error: stray ‘\’ in program
    sketch_apr22a:100: error: stray ‘\’ in program
    sketch_apr22a.cpp: In function ‘void loop()':
    sketch_apr22a:64: error: expected `)’ before ‘u2013′
    sketch_apr22a:71: error: expected `)’ before ‘digitalWrite’
    sketch_apr22a:94: error: expected `)’ before ‘u2013′
    sketch_apr22a:100: error: expected `)’ before ‘else’

    any ideas?
    Thanks

    • admin:

      Hi Shane, thanks for stopping by.

      It looks as if copy/paste did not work as it should have, looks like some of the double slashes that denote comments ended up in a wrong place. I’ll try to attach a zip of the Arduino sketch instead of the text inside the post to eliminate any errors related to text formatting.

    • admin:

      Here is the link to the sketch so you can avoid copy/paste errors http://elabz.com/wp-content/uploads/2011/03/BP_Stepper_ULN2803.pde_.zip

      Hope this helps

      • Shane:

        Thanks so much!
        Plugged by board in uploaded it and the motor is spinnin…

        I didn’t have the 22 ohm resisters…so I replaced them with 100 ohm….it’s working but they really get hot.

        any advice on how I might go about adding some tip120’s to the circuit to drive a bigger motor?

        Thanks again..

        • admin:

          Glad to hear that Shane!

          But as far as driving a bigger motor, I would not recommend adding transistors to this IC which in itself is basically a pair of transistors per each channel. The whole idea of this exercise was to see if a small bipolar stepper motor (the kind you find in CD or DVD drives as well as old floppy drives) could be operated using the simplest circuit possible. Also, I did this wondering if the Darlington array ICs (ULN2803 or 2003) of which I have a small stash of, could be used in a less traditional way.

          Anyways, long story short, there are better ways to drive bipolar steppers and I would advise you to take them if you’re looking into a larger motor. You should take a look at Arduino’s official stepper guide here http://arduino.cc/en/Reference/StepperBipolarCircuit for cirquit ideas for larger motors.

          The difference between using an ULN2803 chip and an H-Bringe chip, such as SN754410, is that an H-Bridge does, in fact have both Darlington Array for sink (low output) AND a similar transistor arrangement (saw it referred to as “pseudo-Darlington”) for source (“high output”). Which I think is exactly what you were thinking about in terms of adding TIPs – someone has already done that and packaged into an IC.

          Unfortunately H-Bridge chips are several times more expensive than ULNs and are not as common, so you probably have to order them someplace whereas ULNs could be found on a bottom of anyone’s parts bin. But I would not mess with larger motors – those resistors would get freakishly hot. I’ve replaced mine with 1/2W since I posted this and they still get just as hot – the price (in terms of power) you have to pay for the fact that ULN Darlington Array chips cannot source current, only sink.

          One of those days I want to redo the official Arduino stepper library to include half-stepping instead of full step that’s there now. Could be useful for a “smoother ride” so to speak, less jerky movement of whatever it is that the stepper is supposed to move. But other than that, you should be able to use all standard Arduino stuff (both software and hardware) and run a larger motor. Just get yourself a couple of SN754410NE chips. They have only half of channels found on ULN2803, so you need one SN754410NE per each motor.

          I would love to see what you are building, so if you feel like sharing, I’m all ears :)

          Good luck!

  • Shane:

    Oh and I changed the delay in between the steps to “2” instead of “10” to get faster movement.

    • admin:

      Good stuff, Shane! Thanks for the video!

      But yes, out of your three motors this particular setup was actually devised to be used with your smallest one :) Additionally, the small ones have only 20 steps per revolution whereas the larger motor you used most likely has 200, so you were absolutely correct with the delay change – it would have been 10 times slower than intended if you didn’t change it.

      For a battery-powered device like Segway you definitely need all efficiency you can get and this is NOT an efficient way to drive a motor, evidenced by the heat dissipated by the resistors. So, that’s out. Also, steppers are not efficient motors themselves. They do have great advantages like ease of control and positioning without closed loop control but they waste A LOT of energy.

      You most definitely need to look at DC motors for your Segway-like project. Given that you’ll probably want to ride it a considerable distance (in other words, use it longer that you’d use a cordless drill), you’ll need to start looking at driving brushless DC motors. A simpler to control brushed DC motor will be a toast by the end of your first ride.

      So, the actual motor you’re probably going to use in the Segway project is a brushless DC and I think it would have to be of a considerable size. Definitely 200W+. I think the actual Segway has two 500W motors. And they are definitely brushless and high-efficiency.

      I’ve ridden the actual Segway once on a tour of Washington, DC. It was a great fun and it did make me look into self-balancing robots. If I were approaching this task (and I am, just not directly :) ), I would have started with working out the kinks on a robot before putting myself on it.

      So, this was a great starting project, congratulations! Now you’ll need to gradually move to larger DC motors and eventually control currents of 10A+ and be able to implement a closed control loop with a three-axis accelerometer in it. Segway is an incredible machine and making one from scratch would be a combination of many interesting mini (and not so mini) projects, but that’s what makes it so exciting, right?!

      I’ll be watching your progress with great interest and when I have something to share myself, I’ll definitely post here.

      Cheers!

      • Shane:

        Thanks, I’ll definitely make sure to post any progress i may make…

        I quick thought though, can you recommend any specific, cost effective (cheapest, that will definitely do the job) brush-less motor that are available online?
        There are a bunch on Google Shopping.

        Thanks for all the info.

        • admin:

          I think I should stop sounding like an expert in Segways, which I’m not. I’m greatly interested in the subject, just like you are, and I keep collecting relevant info and skills but I’m not yet at the implementation stage and so I would not know which motor works best. So, anything I say is just an opinion and can be proved wrong in practice.

          Among those DIY designs I’ve seen the ones with gearboxes and chain drives to the wheels look the most cumbersome to make but may actually have an advantage of #1 lower center of gravity #2 easier to control (control errors are smaller at the wheel due to gearbox reduction) and #3 the motors are easier to find because they are not specialized.

          On the other hand, I’ve seen some done using specialized brushless DC hub motors – basically the motor becomes a part of the wheel and that makes the design mechanically simpler and easier to implement (to an electronics guy like myself). These also appear to have better efficiency (no friction in gearbox/chain/sprocket) but they are #1 more expensive unless you peruse eBay and wait for the shipment from China #2 harder to control (motor directly coupled to the wheel, every small error matters) #3 raise the center of gravity.

          eBay is brimming with DC hub motor offers, all from China, at something like $250+ per wheel, shipped to the US. You most likely don’t need kits (at $400+ per) because the controller may or may not work for your application: I’m not sure you can or even should be able to reverse a bike’s motor and you definitely need reverse for a Segway.

          Non-hub mounted brushless DC motors for bikes (for more mechanically gifted unlike myself) are in $100 range each. You need two, obviously.

          So, anyways, I know it’s not much of a help but I would actually start by buying a small brushless DC motor (servo or not) for something like $15-$20 and played with it first to get familiar with the ways brushless motors are controlled. Then, when I’m more comfortable with the control principal, I would juice my circuit up to handling the larger ones.

          Alternatively, you can look into a broken DVD drive (a source of parts that never fails me), take the spindle motor from it and learn your brushless control on it, for free. That’s what I’m doing right now for one of my projects. The DVD spindle motor has almost no torque but it’s controlled the same way as your “normal” brushless DC motor. I’m hoping to finalize the circuit and the project in a week or so and post it here. Oh, and once again, you’ll definitely need a SN754410NE for this one.

          Cheers!

  • Shane:

    Sounds good…thanks, definitely some good info there. I already ordered a couple SN754410NE chips and they’re on their way. I can’t wait to see the project you’re working on. Be sure to post the diagram and Sketch as it would be a great learning resource for myself.

    I have plenty of DVD drives lying around as well, I’ll start tearing into em, and I also found one odd ball motor. It’s a Dynapar Servo, I think.

    Have you ever seen one like it?

    http://i900.photobucket.com/albums/ac208/shane122108/IMG_1681.jpg

    http://i900.photobucket.com/albums/ac208/shane122108/IMG_1680.jpg

    Dynapar Servo Encoder

    And would they be of any use?

    Thanks

    • admin:

      This guy is not a motor, it’s an encoder. For RPM / position control of your servo motor. It gets coupled onto the motor’s shaft and then your controller reads the data from it to see where the motor’s at. Also a useful part, often more expensive than the motor itself.

      I like the LED treasure hunt background on your pictures, nice touch! :) I also have a bunch of those older, low output colored ones (more recent high output ones are usually all transparent regardless of emitting color). Maybe I should start arranging them like this for photos, creates a nostalgic look … :)

  • Shane:

    Ha, sorry about that. See I’m learning new things everyday…I got a whole bunch of old parts from where I used to work. I also have a smart motor and was wondering how those are used. Model SM2315D. Is the driver circuit housed inside the motor on these particular motors?

    Sorry for all the questions, I just find the information you give me to be much more simplified than any explanation I may find on the web.

    • admin:

      Hi Shane,
      No worries about questions: one of the reasons I put this site up was to chat with like-minded people like yourself. Also, I actually enjoy looking into these things.

      I looked up a SM2315DT brochure and it looks like a wonder of a motor: “Using a patented design, SmartMotors incorporate a Servo Motor, Amplifier, and Motion Controller into the same integral frame.” From what I can tell you can control it not only with a TTL input (as in directly from Arduino, for example) but also via RS-232 (Com port on a PC). Like I said, a wonder of a motor…
      Anyways, with a device like this an actual user manual would be essential. Give http://www.animatics.com (the manufacturer) a try, see if they have downloadable user manual someplace. Or call them 408-748-8721

  • Shane:

    Hey there…just checking in to see if you have made any progress on the project you were working on?

    Do you have a sketch complete?

    • admin:

      Thanks for coming back, Shane! Yes, the project is complete and I will be posting some better description later on, hopefully in just a couple of days, when I get the schematics drawn and some diagrams I need to explain it better. But as a sneak peek preview, here is what I was working on:

  • b1ackmai1er:

    Hi thanks for your article and code.

    I am able to get my motor going in one direction only.
    I thought my button was wired up wrong but even changing the forward code to the reverse code it still goes one way only.

    Any suggestions?

    • Hi and thanks for stopping by!

      Do you mean if you change the code to only call forward() subroutine and then change it again to only call backward() subroutine, it rotates in the same direction in both cases? Is the rotation very jerky, by the way?

      The only thing I can think of is that one of the motor’s windings is not connected properly: either no connection at all or reversed polarity.

      I am assuming you’re connecting a 4-wire bipolar motor. The code will have to be re-done for unipolar.

      I should be able to play with the circuit today, will post more if I am able to reproduce the issue. If you get yours fixed, please post here what the issue was.

      Thanks!

  • [...] For more complicated and real world examples of Arduino code marked up with this plugin, please see my earlier posts: Arduino Nano and HP5082-7433 vintage 7-segment LED display or Driving a Bipolar Stepper Motor with Arduino and ULN2803AG [...]

  • Thomas:

    Nice work(s). I just started experimenting with stepper motors and it’s real fun. I just have a question about your schematics: the resistors R1-4 seem to be superfluous. I’m operating my stepper without any of those resistors and don’t have a problem. Is there any reason you included them?

    • Hi Thomas, thank you for stopping by!

      The reason those resistors are there is to complete the circuit to the positive supply for the ends of the winding that are supposed to be high in a particular step. ULN Darlington arrays only sink current (clamp to ground so to speak), they are not even connected to positive supply in any way.

      It did not occur to me to try and remove the resistors. I may be able to find time and try it tonight. But the only thing I can think of is that if the motor continues to operate, it must be that enough current leaks through the ULN (and Arduino) at the time that its output is supposed to be open?

      Are you using a bipolar motor, by the way?

      Anyhow, I would love to take a closer look at what’s going on. Do you mind maybe post a picture or a diagram and more info about your circuit (such as the motor type) in the forum thread about Arduino, ULN and Bipolar Stepper I started for the purpose?

      Thanks again for stopping by!

      • Thomas:

        I used this page as a start: http://graigroup.wordpress.com/2008/04/27/stepper-motor-driver-using-uln2803/ except that I just use the single transistors instead of pairs.

        As you can see they also don’t use a pull-up resistor. I’m using a unipolar stepper but will try with a bipolar now (if I understood correctly I can use the unipolar also as bipolar by just ignoring the centre connection).

        Sorry for not posting to the forum but that requires registration and I’m a bit reluctant with registrations.

        • Thank you for the confirmation, Thomas!

          Yes, I see now. Unipolar steppers are much different in a way that you can create current using a sinking driver like the ULN by connecting the common input of the motor to the positive supply.

          In a bipolar stepper though you need all four ends of the winding to go HIGH or LOW based on the stepping sequence but the ULN2803 can only create LOW (i.e. sink current) but not HIGH (source current). So, basically, the R1-R4 resistors are sourcing that current where ULN can’t. When the output of the ULN goes open, the pull up resistors create a HIGH. When the output of ULN channel is LOW, it is LOW and the current runs both through the motor as well as through the corresponding resistor – the inherent inefficiency of this particular circuit. You’re absolutely correct, you’ll see the difference if you try your motor in bipolar configuration.

          That forum belongs to this site and I’m the (only) moderator, so no need to worry. You’d be in good hands :) Blog post comments become quite unruly after a while – hard to tell who replies to what, that’s why the forum might have been a better venue for a conversation. Additionally, it allows for picture attachments, text styling (bold, italics etc.) and, most importantly, to preview before posting. I make a bunch of typos and always like to see if I let any rubbish slip into my text. :)

          Thanks again for visiting. Good luck with your circuit!

  • Thomas:

    Thanks for the quick reply. I see what you mean. I guess the better would be to use H-bridges? (I saw a quite simple schematic with 6 single transistors). I’m just at a start so I might drop in (also to the forum) later. Unfortunately I don’t have so much time for this hobby.

    • Since you got a unipolar motor, ULN2803 (or other Darlington Array) should do just fine. They are cheaper than the Full-H or Half-H drivers like the SN754410 and also ULNs are much more common because they are also used in driving LEDs (they are especially useful for matrices). Since LEDs are also very popular among hobbyists, it is almost a guarantee that someone interested in the hobby would have at least one or two ULNs laying around.

      I know what you mean about time :)

  • [...] Playing with a DVD drive stepper and an Arduino today. I mostly used the information from here [...]

  • Kiran:

    I am newbie to electronics. I appreciate your works. I am a follower of your youtube videos.I like the dancing lady. :)

    I am currently trying to make a bi-polar stepper motor work. I read your circuit explanation. Can you help me understand what you meant by floating voltage and how is it helping the circuit?

    • Thanks for stopping by, Kiran. What I meant by floating is that we need to create positive voltage on some ends of the stepper motor winding while bringing other ones to zero in order to create a current through the winding and so make the motor rotate.

      The ULN2803 or other Darlington array ICs can only sink current, i.e. bring its output to zero, they can’t source it i.e. bring it to the positive supply voltage. So, we need to bring the output to the positive supply voltage by adding those 22 Ohm resistors between the windings and the positive supply. When the ULN2803 output is not active, this end of the winding is at positive supply voltage minus the voltage drop on the 22 Ohm resistor. When the ULN2803 output is active, it becomes a zero. That’s how we are able to alternate between the zero and the positive supply without using a specialised H-bridge driver IC, such as SN754410.

      The alternative would be to use the SN754410 which is able to produce both positive voltage and zero on its outputs. It also has the benefit of not wasting energy on passing current through the 22 Ohm resistors, which does nothing useful in terms of moving the motor. That’s why if this is a battery-powered or just energy efficient application, you’d need to look into using an H driver IC instead of the Darlington array IC.

      The reason I did bipolar stepper on Darlington is, first and foremost, I heard someone say it’s impossible and I just wanted to prove them wrong :) . Also, the ULN2803 is the absolute cheapest way to drive two stepper motors (SN754410 are more expensive ICs and have half the amount of outputs) and I wanted to use them because the rest of the circuit is also built on parts that were half their way to trash already, so everything had to be absolutely the lowest price solution :) Hope this makes sense.

      Cheers!

  • Kiran:

    Yes absolutely. It was great explanation. Your response time is amazing. I am new to online discussions on this subject and you are a great encouragement and motivation. :)

    I said motivation because your reply came in the best of times. Below is my story of failure and I was just about to give up and then I got your response. :)

    I tried to wire a similar circuit with a cd drive bipolar stepper motor and a ULN2803 but failed to get it working. I am not using an Arduino as it is expensive for me :) . Instead I am using a small 8 pin PICAXE 08M2 IC and a development circuit I wired on a breadboard. I am assuming that I am using the wrong resistance value. The resistance across the motor winding is 6 ohms approx. What value of resistance will make sence? There is a huge voltage drop across the ULN IC and I suppose that is the issue. The power supply I am using is a 12V 1A Approx DC for the ULN and motor circuit. I run the PICAXE on a 4.5V DC battery.

    I had tried the H bridge with 8 2N2222 transistors initially and failed in that too. There is not reason it should fail as I have gone through the circuit a thousand times. For testing and troubleshooting. I just used two transistors and ran a single step repetitive code [one step forward, one step backward and then repeat]. For this I wired the motor coils this way. 1 lead each of both winding2 to positive and the other 2 leads to the respective transistor base. 2 outputs of the PICAXE will drive the transistors. This worked well. But when I wire the transistor into an H bridge I am loosing it somewhere. I do not know how to go forward with further troubleshooting.

    I am a novice in the field and I am doing this out of interest. Thanks for all the support and advice. :)

    • Hi again, Kiran. 2N2222 is an NPN transistor. It looks like for a bridge built on discrete transistors you would need to use NPN-PNP pairs, because, again, you need to be able to both source and sink current. So, you’d use 2 x 2N2222 and 2 x 2N2907. I don’t have a schematics handy but Google search turned up a page at Solarbotics on this H-bridge design: http://library.solarbotics.net/circuits/driver_4varHbridge.html check it out, this looks like a good way to build it if you have to use discrete transistors. I have to admit though, it’s been awhile since I used discrete anything, really. I have a little stash of SN754410 ICs and use them instead. They also have “Enable” input which helps to keep power consumption low.

      Anyhow, as far as the ULN2803-based circuit, since you are using 12V for the source, you’ll need to use higher value resistors (say, 50 Ohm) and be warned: they will get hot as hell! That’s because of all the energy you are wasting on the resistors. This circuit would not be of much use for anything other than the smaller DVD-drive steppers precisely because of that energy waste. The more powerful the motor, the more current has to go through the resistors and the more you’ll just heat them up.

      Also, I don’t believe you’ll get anywhere by just parallelling the windings (as you said 1 lead of each winding to +, other leads to -) – that will be pulling the rotor in opposite directions and it would not move. You won’t be able to see any movement at all until you properly connect each winding to its own control circuit and only after you energise them in a very precise sequence. That’s what the forward() and backward() functions are doing in this Arduino code.

      • Kiran:

        Thank you so much. I will try this and let you know the outcome.

        I am using discrete components as I thought that will help me grasp the basics. Learning it the hard way. The satisfaction is also a factor I should say.

        About the wiring of the winding, I was able to make a single movement back and forth but just one step. I mentioned it just to explain the transistor-PICAXE circuit I was using.

        I will keep you posted. Good Day. :)

  • Ricardo Lima Caratti:

    It works but the resistors get very very hot.

    • Yes, it’s true: the whole circuit is designed so as to waste at least as much energy heating those resistors as turning the rotor of the stepper. It’s the price that we have to pay for drive a bipolar stepper, which needs both high and low levels using a ULN chip that can only create low. Like I said in the post, there are better ways of driving a bipolar stepper but if you’re stuck without a proper chip (H-bridge), you can still make it work (heating of the resistors noted). Thanks for stopping by!

  • OliGlaser:

    The resistors are not required, – just the direct connection to V+. For example, when one darlington is open (say O1 – i.e. sinking current) and the other is shut (O2 – not sinking current) the supply current flows directly through the coil and is sunk to ground through the open darlington (O1).
    If you reverse this, the current flows the other way (from V+ through O2 to ground). The only wasted power is due to the darlingtons Vsat (saturation voltage, typically between 0.9V and 1.3V).

    So it’s basically like you have it now but without the resistors that do nothing but drop voltage and waste power. Try it and you should see the improvement.

    Also, I’m not sure what you are trying to do with the 12V zener – it will negate the purpose of the back EMF diodes on the common pin (for when the current to the coil is stopped, it will attempt to keep the current flowing and create a large spike – V = L*(dI/dt)). If you are trying to use it to prevent spike on the power rail, wire the cathode (flat side) to V+ and the anode to ground.

    • Hi OliGlaser, thanks for stopping by! I think hear what you are suggesting but if an end of a winding is connected directly to V+, the darlington array will not be able to bring it to 0 on the next step. This is a bipolar stepper and each end of each winding has to be able to go from 0 to V+ (or Vmotor anyway) if the step requires it. An H-bridge would do this but not a Darlington array, unless I did not get your meaning right.

      • OliGlaser:

        Sorry, scratch the first comment, you can delete it if you wish. I didn’t notice it was a bipolar stepper at a glance, without the resistors V+ gets shorted. You do need an H-bridge set up.

        • OliGlaser:

          An interesting thing to try would be to replace the resistors with a PNP or P-ch MOSFET and pullup resistor to V+ driven from the other pin (e.g. O2s transistor base is connected to O1), so when the opposite pin is high it switches the transistor off (i.e. gate/base is pulled to V+) so the open pin cannot short the supply. A small amount of “dead time” would be a good idea to prevent a short on switch over.
          I haven’t thought it through too much but it’s worth a try. I just simulated it and it seems to work okay – I’d post the schematic but it seems I can’t post images here. I’ll link to it somewhere if you are interested.

          • OliGlaser, thanks for the suggestion. I would love to see your schematic (and a SPICE sim if you have it) – you can post images, zip files and a better formatted text in the forums – I think the motor control section is just right for this. I would be glad to take a look, thanks for the offer!

  • OliGlaser:

    Okay, I added a couple of snapshots to Photobucket (if I have time later I’ll join the forums and post the LTSpice files) Here they are:

    Schematic – http://i740.photobucket.com/albums/xx46/oliglaser/ULN2803StepperDrive2.pngSchmatic

    Simulation – http://i740.photobucket.com/albums/xx46/oliglaser/ULN2803StepperDrive2Sim.pngSimulation

    The various signals are shown – the third plot down is the transistor power dissipation, it averages around 25mW with a short spike on switching. As mentioned, some dead time is necessary between switching (as would be in a standard H-bridge)
    It’s a bit of a hack, and it may be easier just to build your own H-bridge rather than going to the trouble of this with a ULN2803, but I though it would be interesting to post in case anyone wants to try it out. Obviously the transistors need to be sized for the current required, and some adjustment of values may be required – all parts shown are just guidleines (the 1N4148s probably need to be replaced with something a little beefier like a 1N4xxx – I just used the first diode on the list)
    P-ch MOSFETs would probably be a little easier to work with and more efficient with higher currents, but more expensive for little benefit in most applications.

    P.S – please forgive my initial stupid comment, can’t quite believe I didn’t notice it was a bipolar coil :-S (must go and get some sleep, I think my brain has already gone off to bed before the rest of me :-) )

    • OliGlaser, thank you again for the time you put into the research, it looks great and I have to say – I just went a very similar way for driving a small BLDC motor. Using a complimentary pair of a PNP and NPN transistors for an H-bridge was rather convenient, also helped in my case that a BLDC motor has one less pair to worry about – only three ends of the windings. Also, I could not easily find a ready-made chip that had 3 gates rather than 4 and was able to float each output separately (SN754410 floats them in pairs – great for steppers and DC motors but not BLDC). I’m sure such IC exists, I just did not have much time to look and wait for the order to come in, so it was quicker to just build my own set of 3 H-bridges out of discrete transistors.

      And I think this is what I would do in this case, too – I think by the time you build the circuitry around the ULN2803 to create the source, you might have as well just put an extra NPN transistor per output (and a flyback diode) in there and be done with it, as you’ve suggested yourself. And save the ULN for some LED-based project or something like that :)

      Thank you again for the mental exercise, I am glad my post has provoked some thought and appreciate the time you spent following this through.

      Cheers!

  • [...] Driving a Bipolar Stepper Motor with Arduino and ULN2803AG – tutorial where is explained how a bipolar stepper motor can be controlled using eight identical Darlington inverting amplifier circuits and an Arduino board. [...]

  • LUTHFI:

    Hi there,

    I am really new in this stepper motor stuff and my search (after two days) is end up in this site and its amazing for what I can learn within this one hour, for me … your conversation from since 2011 in this site until now is precious for me.

    As a starter, I manage to salvage a motor from DVD Rom
    DVD-R Motor
    Well … my guess it should be bipolar (rite?) and it has 4 wire, now the problem is how to identify those wire correctly ? and … I only some stash of L293D from friend of mine, is it possible to control it with that ? (or two L293D perhaps). Big thanks and my best regards to all of you in here from Me@Jakarta.

    • Yes, that is most certainly a bipolar stepper motor. Most likely with 20 steps per revolution (20 SPR). The pinout of the windings is usually very easy on these motors: the ribbon cable contacts go like this: A+A-B+B- and you can easily just flip the cable and it will still work except it will turn in opposite direction. In any case, you should be able to test it with a multimeter in resistance mode. There’s about 4-10Ohm between the ends of one winding and no connectivity at all between the windings.

      You should be able to control one such motor with one L293D (or its newer functional equivalent SN754410
      ) – it’s a quadruple half-H driver, just enough for one bipolar motor with four ends of the winding. You can drive the motor in either full or half-step with these chips very easily.

      Unfortunately, I don’t have a ready-made diagram for L293D specifically, but it is very similar to the circuit on this page except there’s no need for those 4 resistors R1-R4 and the zener D4. Connect L293D in such a way that those I1-I4 inputs on this diagram connect to L293’s A1-A4 inputs and O1-O4 outputs connect to L293’s Y1-Y4 outputs. It’s just how they label the inputs and outputs – A for input and Y for output. Other than those differences in hardware, the software should still work.

      Thanks for stopping by my blog!
      Good luck!

  • LUTHFI:

    Big Thanks !

    Just want to let you know, that it is working !! following the pin out from you and total SPR … reading datasheet L293D … and it works !!! Now I can control that motor easily … once again, thanks !

  • Sachin:

    Hi, nice topic been on since 2011…xD so let me forward it in 2014..

    I am having a hard time with my bipolar motor, tried it with l293d but no success, motor is not moving a bit.

    Motor draws about 2.7A and 2.5V, can i use above top page circuit to drive this motor, or any other method,.
    Please help..

    • If the motor is not moving at all, not even twitching, chances are – you have a problem with its wiring (assuming the software is working correctly). I would not advise to use this circuit with any kind of seriously powerful motor, such as yours. It is not an efficient way of driving a stepper, it was simply an exercise “what if” just to see if its doable. You will do much better with a specialized chip for driving a bipolar motor. There are quite a few on the market now, starting with the venerable EasyDriver and there’s quite a few newer models out there with prices all the way down to $6-$10 for the chip on a breakout PCB plus all required components. Definitely look into using a specialized chip to drive your bipolar stepper.

  • 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 project but have no idea how to a do this I would assume you just replicate but with all the correct pins and things, any chance you can help me out?

    Cheers

    Awesome blog by the way.

  • Mark:

    Good day Sir just finished reading this thread while browsing for driving bipolar stepper motor. I just wanted to ask sir if what exactly the pins of my salvaged bipolar stepper motor (4pins) from a broken printer connects/belongs to. It has a 4 color coded wire (red,blue,white, and yellow). Thanks in advance for your help sir. This is the only hinder in our foregoing project. :(

    Excellent and User-Friendly Blog by the way sir!

    • It’s hard to tell which wire is exactly which end of the winding. But with only 4 wires, they should be easy enough to identify with an multimeter. There are only 2 winding in the bipolar motor (or, more accurately, only two sets of winding ends). So, you should see some resistance ( 10-20Ohm for a small motor) between the ends of the same winding, but not between wires belonging to different winding. Once you’ve identified the two set of wires, polarity within the set does not matter – the direction of rotation will depend on that polarity, but you will just have to try both ways and find which is the direction you need.

      Hope this helps

  • Mark:

    Okay sir I see. I thought the two pieces of wire (Red and Blue) belongs to the Power Supply (+5V) and the other two wires (Yellow and White) belongs to the signal(pulses) needed for the bipolar motor to rotate sir.

  • Mark:

    Thanks by the way for the reply sir. Sorry for my late reply.

  • Mark:

    Hi sir good day. It’s me again Mark. Just wanted to ask if driving a bipolar motor (4 leads) needs a certain motor driver (SN754410NE or L293D) before it rotates? I have done experimenting it with a digital trainer by giving +5V for each wire following certain steps (e.g. Step1 : 1st wire = HIGH 2nd wire = LOW 3rd wire = HIGH 4th wire = LOW) and so on. Also, I have determined the pair of wires as what you’ve told me. I have found out that wire 1 and 3 are paired with each other as well as wire 2 and 4. And, I have verified the connectivity with each wire to check if there is a shorted connection and gladly there is none. Thanks sir!

  • Mark:

    Hi Sir it’s me again Mark. Just wanted to ask another one thing sir. Just wanted to ask if there are such inter-connections on each pins of a unipolar motor and also resistance which can be measured out of each pins. (i.e: does pin1 of a unipolar motor connected to pin 2 to 5? vice-versa). Thanks in advance Sir!

    • If we are talking about unipolar (not bipolar, as in the title of this post), then yes, you may have the 5-pin configuration, and then there will be some resistivity between every lead of the motor. That’s because the #5 is the center point of each of the two windings. You can still tell which end is which by looking at the actual resistivity value – it will be the highest between #1 and #4 (because it goes through most distance in the coil) and smallest between #5 and every other lead. So, when you’ve found the smallest resistivity, you’ve found #5. When you’ve found the highest, you’ve found #1 and #4, and the other ones are #2 and #3. You don’t have to know exactly which is #1 or #4 – you can easily swap them if you want the motor to turn in the opposite direction. Same with #2 and #3.

      Hope this helps

  • Mark:

    All right sir I got it. Like any other post in some websites, I have found out that pins 5&6 (which are tied together to become a pin 5 which is a common pon)is the most common wire for unipolar motors. But in the case of my borrowed unipolar stepper motor, I have traced it’s connection and then found out that pin 3 (out of 5 pins) is the common pin. I can gladly tell it because its the one who has a 2 pin connected to each other in their printed circuit board design. Sadly, I don’t have pictures to support my statement but then, I’ll post this in as soon as I get a picture of it. Also sir, the ones marked at the chassis of the motor is 20 ohms. Then I tried verifying it by connecting the common pin into any other pins (with a multi-tester)and then got a 20 ohms resistance reading (i.e: pin 3(common) to pin 1,2,4,and 5) and then pins 1 & 2, 2 & 4 , and so on got a 40 ohms resistance reading just like what I’ve read on a certain pdf concerning motors and then you’re recent post. Thanks again Sir for the eagerness to reply on my posts. Thumbs UP!

  • Mark:

    Hi Sir. Just dropped by to report that I have made the unipolar stepper motor rotated clockwise and counter-clockwise by just shorting the two pins (not the common pins) to arduino with a uln2003 driver. Strange but anyway a big HOORAY!! Thanks again sir!

    • That sounds great! Sorry I did not have a chance to follow your previous comment. But in general terms this is exactly what you would expect the ULN2003 to do: sink current, i.e. connect something to ground. For motor to work, the common would have to be connected to the positive rail of the power supply. It is hard to go by the wires’ numbers because they are all relative, and all motors are wired differently, but I am glad your figured out the numbering on your own.
      Cheers!

  • Mark:

    Yeah sir. Anyway, We will just have to reconsider the theory of those motors again because it would be asked (maybe) on our upcoming defense. I am facing another problem now sir. It’s the 20×4 LCD, it’s all wired up correctly yet it only shows block boxes on first and third row like this.

    PS: (I can’t post a pic sir,couldn’t find a way to post it sorry..)

    • Hard to tell what’s going on with your LCD – probably hasn’t been initiated or some kind of a communication issue like, using 4-wire protocol with an 8-wire configured LCD or some such.

      You can always post pictures in the forums on this site: http://elabz.com/forums/post-your-projects/ – that is a projects section of the forum, or pick the one you think is more appropriate

  • Mark:

    Sorry for the late reply of you’re comment too sir. Been busied for a while troubleshooting our project.

  • Mark:

    It’s kinda like an internal problem on the circuitry sir. Have done series of tests to check if the arduino or the lcd is damaged. Found out that the LCD is damaged because I happened to replace it by another LCD and the other LCD works. Looks like I have to replace them. Thanks sir!

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
  • Dani: Thanks for your reply! :)
  • Andreas Carmblad: Thanks for answer :) I use easydriver yes. The problem is solved though. I thought I was supposed...
  • admin: Hi Andreas, You did not specify which stepper motor controller you are using and it is an important bit of...
  • Andreas Carmblad: I would really need some help with this. I can’t get it to work. The axel of the motor is...
  • jordan: whoops just realised the error in my previous post, 250mW is the output but has nothing to do with the input...
  • jordan: hi, i managed to get my hands on two laser diodes and was a little too eager with the first one (it blew out)...
  • admin: I think you are correct, LinuxCNC should be able to control it using a more widely available CNC servo...
  • Kunkmiester: Do you know what kind of encoders the motors use? Gecko and others make servo drivers, so if the encoder...
  • admin: Hello Dani, thanks for checking in. No, in this particular case the common wire should be left unconnected....
  • Dani: Your code worked well on my salvaged spindle motor, thanks for sharing!! By the way, I found other spindle...
Meta