Unipolar Stepper Motors: Arduino Code and Driver

 Author:   Posted on:   Updated on:  2017-12-02T17:03:42Z
A stepper motor is a brushless electric motor that rotates in small equal steps, as opposed to the continuous rotation of regular motors. It has the ability to rotate a predefined number of steps, which makes it useful for precision mechanical devices. To do this, it uses multiple coils that are energized in regular sequences by trains of digital pulses. The speed of these pulses determines also the speed of the motor. The pulse sequence determines the rotation direction.

There are two main types of stepper motors. There are bipolar motors which contain two coils (4 wires). To drive these kind of motors, coils are energized one after another, then polarity is changed and the coils are energized again. Tow H-bridge circuits are required in this case. Unipolar motors use two coils, each of them having a center tap. The center taps from both coils connect to a power line and the remaining four coil terminals are powered sequentially (5 wires). This simplifies a bit the driving circuit. Some manufacturers offer steppers that can be used either as unipolar or as bipolar. These kind of motors have the center taps not connected together (6 wires motor) and if the center taps are not used, the motor is bipolar.
Unipolar Stepper Motors: Arduino Code and Driver
This post will be about unipolar motors. Although there are libraries for steppers, generating the pulses is a very easy task for any microcontroller. But, a microcontroller can't be connected directly to a high current inductive load. A driver is required. You can buy ICs designed for this task or you can make it using 4 power transistors. For this, I used some old N-channel FETs that I had around (2SK2382). Usually, N-FETs from power supplies are the best choice: they support high currents and the include protection diodes. Just make sure gate threshold is less than Arduino high levels (so that the transistors can be switched on).

You can power steppers from constant voltage supplies. But a constant current supply is a better choice especially when you want good performance and don't know motor's ratings. I got my motor from some old hardware and all I can find out about it is the coil resistance (it's printed on it). So, I decided to supply a maximum of 500 mA to the motor using a simple LM317 circuit.

If you, like me, don't know the motor current or voltage, try with increasing currents. The motor can get warm but it shouldn't be hot enough so you can't keep your hand on it. If this happens, lower the current. Let's have a look at the schematic of my driver and power circuit.

Unipolar stepper motor driver with Arduino
Unipolar stepper motor driver with Arduino
The schematic is complete. For most motors, the diodes can be usual rectifier types rated at 1A (i.e. 1N4004). Fast rectifier types are usually a better choice. If you're using N-FETs with included protection diodes, there is no need for external diodes. Also, with FET transistors, the gate can be connected directly to Arduino pin, without 1k resistors. Those resistors are required if you use bipolar transistors instead of FETs. Yes, you can use NPN transistors. Darlington transistors are recommended. Just make sure the transistor can handle load current (drain-source current, collector-emitter current) and it can be fully switched on by Arduino (gate threshold voltage, DC gain).

The resistor connected between OUT and ADJ pins of LM317 controls the constant current. For 2.4 ohms, the current is 1.25/2.4 = 0.5A. Use a correct wattage resistor (2-3W). Replace the resistor with a suitable value for the motor rated current. The voltage at LM317 input cannot exceed 35V.

I built the simplified driver on the breadboard.

Unipolar stepper motor driver on breadboard
Unipolar stepper motor driver on breadboard
All it needs now is the software. Rotating a stepper is very simple, that's why I wrote my own code instead of using a library. To simplify the code I didn't use standard digitalWrite routines. I wrote directly to the port. First the port must be set as output in setup() with DDRB = 0x3F;. This sets digital pins 8 to 11 as outputs. Check Arduino Port Manipulation page.

The coils must be energized in a specific order: a half of one coil (A), then a half of the other (B). Pulses should then energize the remaining coil halves (C half of the first coil, then D half of the other coil). The order determines direction. Just remember: you should not energize in a sequence one half of a coil, then the other half of the same coil. The motor will make a step in one direction and one step backwards. It doesn't harm the motor though. A-B-C-D and A-D-C-B are valid sequences, but A-C-B-D is not.

Because you can power 4 coils, there are actually 3 ways of doing it. You can use wave drive. Each of the 4 coils is powered sequentially so that only one coil is powered an any time. This results in less power consumption and less torque. Below is the pulse train and the code used to generate it.

Unipolar stepper wave drive
Unipolar stepper wave drive
void waveDrive(unsigned int numSteps, unsigned int stepDelay = 5) {
  for (unsigned int i = 0; i < numSteps; i++) {
    PORTB = B00000001;
    delay(stepDelay);
    PORTB = B00000010;
    delay(stepDelay);
    PORTB = B00000100;
    delay(stepDelay);
    PORTB = B00001000;
    delay(stepDelay);
  }
}
The motor can be rotated in half drive mode too. In this mode a pulse is kept high when the next starts. Half of the time, two adjacent coils are energized, resulting in higher torque. When both adjacent coils are on, the axis turns one half of the step, resulting in a smoother rotation. With the same delay, pulse width increases, meaning you can use lower step delays.

Unipolar stepper half drive
Unipolar stepper half drive
void halfDrive(unsigned int numSteps, unsigned int stepDelay = 5) {
  for (unsigned int i = 0; i < numSteps; i++) {
    PORTB = B00000001;
    delay(stepDelay);
    PORTB = B00000011;
    delay(stepDelay);
    PORTB = B00000010;
    delay(stepDelay);
    PORTB = B00000110;
    delay(stepDelay);
    PORTB = B00000100;
    delay(stepDelay);
    PORTB = B00001100;
    delay(stepDelay);
    PORTB = B00001000;
    delay(stepDelay);
    PORTB = B00001001;
    delay(stepDelay);
  }
}
The third way is called full drive. Two adjacent coils are on at the same time, resulting in highest torque possible.

Unipolar stepper full drive
Unipolar stepper full drive
void fullDrive(unsigned int numSteps, unsigned int stepDelay = 5) {
  for (unsigned int i = 0; i < numSteps; i++) {
    PORTB = B00000011;
    delay(stepDelay);
    PORTB = B00000110;
    delay(stepDelay);
    PORTB = B00001100;
    delay(stepDelay);
    PORTB = B00001001;
    delay(stepDelay);
  }
}
These are basic and lightweight functions for driving a stepper. The numSteps argument is a multiple of 4 steps. That is, for numSteps=1, the motor will make 4 steps. For the common 1.8 degree, 200 steps/turn motors, set numSteps to 50 to make a full rotation. These functions do not support changing direction.

Improvements of these functions and animations of driving methods can be found here.

No comments :

Post a Comment

Please read the comments policy before publishing your comment.