Stepper motors

  • Stepper motor variants
    image.png (124.26 KiB)
    Stepper motor variants Viewed 5305 times
    The image showcases three examples of stepper motors. Miniature motors like the one depicted on the left are used for adjusting lens components in compact cameras or smartphones. In the center, there is a 5V stepper motor with a built-in gearbox, which houses both the stepper motor and the reducer. On the right, you can see a stepper motor typical for printers.

    As implied by their name, stepper motors rotate in a series of short steps. This sets them apart from free-rotating motors. A stepper motor will take as many steps as specified, allowing you to precisely determine how many steps it has taken. This characteristic is one of the reasons why stepper motors are widely used in both conventional and 3D printers. In regular printers, they precisely position paper, while in 3D printers, they control the movement of the print bed and nozzle.
  • The diagram below illustrates the operation of a stepper motor, more specifically, the operation of a bipolar stepper motor. Another type of stepper motor, unipolar stepper motors, will be discussed in the section "Unipolar Stepper Motors" later.

    In a bipolar stepper motor, there are typically four coils. The coils that are positioned opposite each other are connected in such a way that they operate synchronously. All the coils are located on the stationary stator of the motor, eliminating the need for a rotating commutator and brushes as found in DC motors.
    Schematic diagram of bipolar stepper motor operation
    image.png (87.39 KiB)
    Schematic diagram of bipolar stepper motor operation Viewed 5305 times
    The rotor of a stepper motor is designed as a series of magnetized teeth with alternating north (N) and south (S) poles (there are usually more teeth on the rotor than shown in the diagram). Each coil can be energized to become either a north or a south pole, depending on the current direction through the coil (reminding you of H-bridges, isn't it?). Coils 1 and 3 work together so that when coil 1 becomes a south pole, coil 3 also becomes a south pole. The same applies to coils 2 and 4.

    Let's start with figure a: when coil 1 (and consequently, coil 3) are energized to become south poles (S), the rotor rotates counterclockwise until the nearest rotor teeth with a north pole (N) magnetization align with coils 1 and 3 (as shown in figure b). To continue rotating counterclockwise, on the next step (figure c), current needs to be applied to coils 2 and 4 to make them north poles (N). Then, the nearest rotor teeth with south pole (S) magnetization will be attracted to coils 2 and 4 (figure d).

    Each of these actions rotates the motor's rotor by one step. To continue rotating counterclockwise, coil 1 needs to be magnetized as north (N) again, as shown in the table.

    Table: Sequence of actions for counterclockwise rotation of a stepper motor
    Sequence of operations for counterclockwise rotation of the stepper motor
    image.png (10.76 KiB)
    Sequence of operations for counterclockwise rotation of the stepper motor Viewed 5305 times
    Dashes in the table indicate that the coil does not influence the rotor's rotation at that moment and should be de-energized. To enhance the motor's torque, these de-energized coils can be energized in such a way that their magnetization polarity matches the polarity of the rotor tooth beneath them (as shown in the table below).

    Revised sequence of coil switching for counterclockwise rotation of a stepper motor
    Refined sequence of coil switching during stepper motor rotation
    image.png (11.98 KiB)
    Refined sequence of coil switching during stepper motor rotation Viewed 5305 times
    You might wonder what would happen if you started with coils 2 and 4 instead of coils 1 and 3. In that case, a different pair of coils would facilitate bringing the rotor teeth to the correct position. To change the direction of the rotor's rotation, you would simply reverse the order of coil switching indicated in the table above.
  • As there are two pairs of coils in a stepper motor, to control it, you'll need to reverse the current direction in each such pair, which means you'll need two H-bridges. It seems like the job for the L293D microchip.

    That's correct - in this experiment, both for Arduino and Raspberry Pi, the control of a bipolar stepper motor is achieved using the L293D microchip, which is installed on the prototype board.
    Bipolar stepper motor control circuit assembly (Raspberry Pi variant)
    image.png (239.48 KiB)
    Bipolar stepper motor control circuit assembly (Raspberry Pi variant) Viewed 5305 times
    Although the stepper motor used in the experiment has a nominal voltage of 12 V, it will work with a 6 V battery pack as well. The motor's torque will decrease, but it will still rotate effectively.

    DEFINITION OF STEPPER MOTOR PINOUT

    Every new stepper motor should have a technical datasheet as well as a label on its housing, indicating the purpose of each of its four pins. The key thing to know here is which pins form a pair connected to the same coil.

    To figure this out, there's a simple trick. Take any two wires and hold them between your thumb and index finger while turning the motor's shaft. If you feel resistance to rotation, then these two wires form a pair.

    Components

    For this experiment, you will need the following components to work with Arduino and Raspberry Pi:
    IC1 - L293D H-Bridge microchip
    C1 - 100nF capacitor
    C2 - 16V 100µF capacitor
    M1 - Bipolar stepper motor 12V
    4 AA battery compartment (6V)
    400-point solderless prototype board
    Jumper wires

    Construction

    The schematic diagram of this experiment is shown below. In this case, PWM is not used, so both Enable inputs of the L293D microchip are connected to a 5V power source to keep both H-bridges permanently enabled. The stepper motor is controlled by four channels: In1, In2, In3, and In4, to which control signals from Arduino or Raspberry Pi will be applied.

    Experimenting with Arduino

    In this version of the Arduino experiment, we will use the serial monitor window to send commands to the Arduino that control the motor. There are three types of commands, each consisting of a single letter followed by a number. For example:

    f100 - sets the motor to move 100 steps forward;
    r100 - sets the motor to move 100 steps in reverse;
    p10 - sets the delay time between step pulses to 10 milliseconds.
    Circuit diagram for controlling a bipolar stepper motor
    image.png (46.22 KiB)
    Circuit diagram for controlling a bipolar stepper motor Viewed 5305 times
    Stepper motor control circuit from Arduino assembly
    image.png (213.42 KiB)
    Stepper motor control circuit from Arduino assembly Viewed 5305 times
    Connecting Arduino

    When connecting Arduino to the L293D microchip, the following pins are used.
    Contacts for connecting Arduino to L293D chip
    image.png (21.17 KiB)
    Contacts for connecting Arduino to L293D chip Viewed 5305 times
    The layout of the prototype board for the Arduino version is shown in the figure below. Ensure that the microchip is correctly installed (the notch on the chip's housing should be facing upwards), and that the 100µF capacitor C2's positive terminal is connected to pin 8 of the L293D. To make it easier for you to orient, remember that the positive lead of an electrolytic capacitor is usually longer than the negative one. The negative terminal of the capacitor can also be marked on its body with a "-" symbol or a diamond.
    Layout of breadboard for controlling bipolar stepper motor with Arduino
    image.png (106.54 KiB)
    Layout of breadboard for controlling bipolar stepper motor with Arduino Viewed 5305 times
    Arduino Programs

    For this experiment, there are two program variants. The first one is more complex and involves setting up the L293D microchip's pins to control the stepper motor coils according to the description provided earlier in the "Bipolar Stepper Motors" section. This is a useful exercise for gaining a precise understanding of how a stepper motor works.

    The second variant uses a sketch that calls the Arduino Stepper library, which handles all the work. Therefore, the second variant is much shorter.

    Complex Program Variant

    The first Arduino sketch is as follows:

    Code: Select all

    const int in1Pin = 10;   // (1)
    const int in2Pin = 9;
    const int in3Pin = 11;
    const int in4Pin = 8;
    
    int period = 20;      // (2)
    
    void setup() {        // (3)
      pinMode(in1Pin, OUTPUT);
      pinMode(in2Pin, OUTPUT);
      pinMode(in3Pin, OUTPUT);
      pinMode(in4Pin, OUTPUT);
      Serial.begin(9600);
      Serial.println("Command letter followed by number");
      Serial.println("p20 - set the inter-step period to 20ms (control speed)");
      Serial.println("f100 - forward 100 steps");
      Serial.println("r100 - reverse 100 steps");
    }
    
    void loop() {      // (4)
      if (Serial.available()) {
        char command = Serial.read();
        int param = Serial.parseInt();
        if (command == 'p') {        // (5)
          period = param;
        }
        else if (command == 'f') {   // (6)
          stepForward(param, period);
        }
        else if (command == 'r') {
          stepReverse(param, period);
        }   
      } 
      setCoils(0, 0, 0, 0); // power down
    }
    
    void stepForward(int steps, int period) {     // (7)
      for (int i = 0; i < steps; i++) {
        singleStepForward(period);
      }
    }
    
    void singleStepForward(int period) {       // (8)
      setCoils(1, 0, 0, 1);
      delay(period);
      setCoils(1, 0, 1, 0);
      delay(period);
      setCoils(0, 1, 1, 0);
      delay(period);
      setCoils(0, 1, 0, 1);
      delay(period);
    }
    
    void stepReverse(int steps, int period) {
      for (int i = 0; i < steps; i++) {200
        singleStepReverse(period);
      }
    }
    
    void singleStepReverse(int period) {          // (9)
      setCoils(0, 1, 0, 1);
      delay(period);
      setCoils(0, 1, 1, 0);
      delay(period);
      setCoils(1, 0, 1, 0);
      delay(period);
      setCoils(1, 0, 0, 1);
      delay(period);
    }
    
    void setCoils(int in1, int in2, int in3, int in4) {    // (10)
      digitalWrite(in1Pin, in1);
      digitalWrite(in2Pin, in2);
      digitalWrite(in3Pin, in3);
      digitalWrite(in4Pin, in4);
    }
    
    Let's clarify some points of the sketch step by step, using the comments made in the code:

    1. The program begins by defining the pins that will be used to control the motor. You can, of course, change the pins according to how they are connected on the prototype board.

    2. The variable period sets the delay between activating the coils at each step during motor rotation. Initially, the delay is set to 20 ms. You can adjust this delay through the serial port monitor window to speed up or slow down the motor.

    3. The setup() function configures the control pins as outputs, initiates the serial communication channel with the serial port monitor window, and then prints a message containing the command formats that can be used.

    4. In the main loop() program loop, it waits for commands through the serial channel and processes these commands when received. If a command is received (as indicated by Serial.available in the loop() loop), it first reads the command letter and then the parameter following the letter.

    Next, there are a series of expressions that define specific actions based on the command.

    5. If a letter is specified, the variable "roy" takes the value equal to the command parameter.

    6. If the "f" or "r" command is specified, it calls the stepForward or stepReverse functions with the number of steps and delay time between pulses as parameters.

    7. The stepForward and stepReverse functions are very similar. They call the singleStepForward or singleStepReverse functions as many times as the specified steps.

    8. Next, we move on to the singleStepForward function, which contains the polarity patterns of the four-phase coil switching for moving one step. You can see the polarity patterns as parameters for setCoils.

    9. The singleStepReverse function works the same way as singleStepForward, but in the reverse sequence. Compare these steps with the data in the last table.

    10. Finally, the function sets the state of the control pins according to the pattern provided as parameters.

    Lightweight Program Variant

    The Arduino IDE includes the Stepper library, which works well and can significantly reduce the size of the sketch.

    Code: Select all

    #include <Stepper.h>    // (1)
    
    const int in1Pin = 10;
    const int in2Pin = 9;
    const int in3Pin = 8;
    const int in4Pin = 11;
    
    Stepper motor(200, in1Pin, in2Pin, in3Pin, in4Pin);     // (2)
    
    void setup() {       // (3)
      pinMode(in1Pin, OUTPUT);
      pinMode(in2Pin, OUTPUT);
      pinMode(in3Pin, OUTPUT);
      pinMode(in4Pin, OUTPUT);
      while (!Serial);
      Serial.begin(9600);
      Serial.println("Command letter followed by number");
      Serial.println("p20 - set the motor speed to 20");
      Serial.println("f100 - forward 100 steps");
      Serial.println("r100 - reverse 100 steps");
      motor.setSpeed(20);       // (4)
    }
    
    void loop() {        // (5)
        if (Serial.available()) {
        char command = Serial.read();
        int param = Serial.parseInt();
        if (command == 'p') {
          motor.setSpeed(param);
        }
        else if (command == 'f') {
          motor.step(param);
        }
        else if (command == 'r') {
          motor.step(-param);
        }   
      } 
    }
    
    Let's clarify some aspects of the sketch step by step, using the comments provided in the code:

    1. In the first line of the sketch, the Stepper library is imported, which is already included in the Arduino IDE, so you don't need to install it separately.

    2. To use the library, you need to define the type of stepper motor in the motor variable. The first parameter is the number of steps the motor takes in one revolution. For the Adafruit stepper motor used in this project, the value is set to 200 steps. In reality, this means 200 coil phase switches per revolution, which corresponds to 50 physical steps per revolution. The other four parameters are the pins used for the coils.

    3. The setup function setup() is almost the same as in the complex version of the sketch. However, the message differs slightly because in this case, the command sets the motor's rotation speed in RPM (revolutions per minute), which was previously adjusted by changing the delay between pulses. Either way, you can adjust the motor's speed using both methods.

    4. By default, the rotation speed of the motor in the setup() function is set using the motor.setSpeed function, which is initially set to 20 RPM.

    5. The main program loop loop() is also very similar to the complex version of the sketch. However, in this case, the number of steps and the direction of rotation are specified as positive when moving forward and negative when moving backward.

    The number of "quarter steps" specified in the f and r commands here represents the number of coil phase switches. To make the Adafruit stepper motor used here complete one full revolution, you need to enter the number 200.

    Uploading and Running the Program

    You can try both programs for stepper motors in all modes, but we will assume that the last sketch is loaded into Arduino. Open the serial port monitor, and you will see the message:
    Stepper motor control from the port monitor
    image.png (81.34 KiB)
    Stepper motor control from the port monitor Viewed 5305 times
    Enter the command f200 and press the Send button - the motor shaft should make one full revolution. If it doesn't rotate and instead vibrates or makes noise, one of the coils is likely connected incorrectly. Swap the jumpers going from the stepper motor to pins 3 and 6 of the L293D chip and try the command again.

    Execute the r200 command, after which the motor shaft should make one revolution in the opposite direction.

    Next, you can experiment with the speed using the command and the subsequent speed value in RPM - for example, p5 followed by f200. The motor shaft will rotate again, but very slowly. You can increase the rotation speed by setting a higher value, for example, p100. However, you'll find that somewhere around 130 RPM, there's a speed limit above which some steps will be lost, and the motor shaft won't be able to complete a full revolution.
  • Unipolar stepper motors operate almost the same way as bipolar motors but do not require H-bridges for control. This is due to their more complex coil structure. The diagram below illustrates the operation of a unipolar stepper motor.

    A unipolar motor has five coil leads, unlike the four leads of a bipolar motor. Four of these leads are equivalent to the leads of a bipolar motor, representing the coil ends A, B, C, and D. So, if desired, you can use the ends of coils A, B, C, and D and control them with H-bridges as if it were a bipolar motor, and everything will work fine.
    Unipolar stepper motor operation diagram
    image.png (51.48 KiB)
    Unipolar stepper motor operation diagram Viewed 5305 times
    The fifth lead of a unipolar stepper motor connects to the midpoints of each coil's windings. By connecting this lead to the ground (GND), you can magnetize the coil's north pole when supplying power to lead A, or the south pole when supplying power to lead B. This eliminates the need for H-bridges.
  • The absence of a need for H-bridges to control unipolar stepper motors does not negate the fact that the motor coils consume too much current to be powered directly from the outputs of an Arduino or Raspberry Pi.

    An obvious way to increase the current is to use transistors, as demonstrated in the "Experiment: Motor Control" section. You will need four transistors, one for each of the leads A, B, C, and D. Additionally, current-limiting resistors will be required in the base circuit of these transistors, along with protective flyback diodes for each coil. The diagram below illustrates how to connect each coil of a unipolar motor, and you will need four such circuits for complete motor control.
    Power key of unipolar stepper motor on one transistor
    image.png (60.55 KiB)
    Power key of unipolar stepper motor on one transistor Viewed 5304 times
    These circuits can be readily assembled on a prototyping board, but it will require quite a few jumpers.

    A more elegant solution is to use a specialized integrated circuit (IC), such as the ULN2803. This affordable IC contains eight individual Darlington transistor pairs in a single package. Moreover, it already includes base resistors and protective diodes. The only additional component required would be a capacitor in the power supply circuit.

    The ULN2803 IC (www.adafruit.com/datasheets/ULN2803A.pdf) can handle currents up to 500 mA in each channel at a maximum voltage of 50 V.

    In the upcoming section, "Experiment: Controlling a Unipolar Stepper Motor," we will utilize one of these devices to control a unipolar stepper motor from both Arduino and Raspberry Pi.
  • The image below illustrates a Raspberry Pi board controlling a unipolar stepper motor of one of its widely used types, equipped with a 1:16 reduction gearbox. Although the motor itself takes 32 steps per revolution, the presence of the reducer means that 513 phase transitions must be executed for one full revolution, equivalent to 128 steps per revolution.
    Unipolar stepper motor control circuit assembly
    image.png (138.84 KiB)
    Unipolar stepper motor control circuit assembly Viewed 5304 times
    Equipment

    The diagram below shows the connection scheme of unipolar motor coils modified for use with the ULN2003 microchip. Note that there are still four unused composite transistors that can be used to control a second stepper motor. For stepper motors with higher operating currents, the transistors of the microchip can be paired by connecting two of their inputs and two corresponding outputs together.

    In this setup, a low-power motor with a 5 V power supply and a relatively low working current is used, making it possible to power it directly from a Raspberry Pi or Arduino. With two coils energized, the current consumption is approximately 150 mA. If a more powerful motor or one with a higher supply voltage is used, a separate power source will need to be connected, as was done with the bipolar stepper motor.

    Finding out which lead is connected to what inside the motor can be done in the same way as recommended for the bipolar motor. Additional complexity here arises from the presence of a common wire. Therefore, you should start by finding the common wire that resists rotation while being connected to any of the other leads. Then, to find the other wires, you can use the same method as for the bipolar motor.
    Unipolar stepper motor control circuit (wire colors of the real circuit may differ from those shown here)
    image.png (67.94 KiB)
    Unipolar stepper motor control circuit (wire colors of the real circuit may differ from those shown here) Viewed 5304 times
    Components

    For this experiment, you will need the following components to work with Arduino and Raspberry Pi:

    IC1 - ULN2803 Microchip
    C2 - 16V 100uF Capacitor
    M1 - 5V Unipolar Stepper Motor
    4xAA Battery Holder (6V)
    400-Point Breadboard
    Jumper Wires

    Connecting Arduino

    The diagram shows how you can connect an Arduino Uno to the ULN2803 microchip.
    Connecting Arduino to ULN2803 chip
    image.png (102.32 KiB)
    Connecting Arduino to ULN2803 chip Viewed 5304 times
    You just need to make sure the capacitor is installed correctly, with its longer positive lead oriented to the right. The microchip should be positioned so that the notch on the housing faces the top side of the prototyping board.

    As you can see, the assembly is neater compared to the setup for a bipolar motor.

    Arduino Program

    Code: Select all

    #include <Stepper.h>
    
    const int in1Pin = 9;
    const int in2Pin = 11;
    const int in3Pin = 8;
    const int in4Pin = 10;
    
    Stepper motor(513, in1Pin, in2Pin, in3Pin, in4Pin);  
    
    void setup() {
      pinMode(in1Pin, OUTPUT);
      pinMode(in2Pin, OUTPUT);
      pinMode(in3Pin, OUTPUT);
      pinMode(in4Pin, OUTPUT);
      while (!Serial);
      Serial.begin(9600);
      Serial.println("Command letter followed by number");
      Serial.println("p20 - set the motor speed to 20");
      Serial.println("f100 - forward 100 steps");
      Serial.println("r100 - reverse 100 steps");
      motor.setSpeed(20);
    }
    
    void loop() {
        if (Serial.available()) {
        char command = Serial.read();
        int param = Serial.parseInt();
        if (command == 'p') {
          motor.setSpeed(param);
        }
        else if (command == 'f') {
          motor.step(param);
        }
        else if (command == 'r') {
          motor.step(-param);
        }   
      } 
    }
  • You may have noticed that the movement of a stepper motor is not always very smooth, even when the rotation speed is relatively high. For most applications, this is not a problem, but sometimes it would be better if the movement were smoother.

    Microstepping is a method that allows for smoother motor movement. Instead of simply turning the coils on and off, microstepping uses PWM (Pulse Width Modulation) to smoothly power the coils, resulting in smoother motor rotation.

    Microstepping can be implemented programmatically, but it's generally much easier to use specialized hardware designed for stepper motors capable of operating in microstepping mode. One such hardware solution is the EasyDriver board based on the A3967 microchip, developed by Brian Schmalz.

    A great tutorial on using the EasyDriver board with Arduino can be found online on Sparkfun's website, dedicated to this board (product ROB-12779).
  • Brushless DC motors (BLDC) are small yet powerful motors commonly found in quadcopters and radio-controlled model airplanes. Despite their small size, they can generate much greater torque compared to traditional DC motors of the same weight. They are included in this chapter because they share many similarities with stepper motors, although they are formally categorized as DC motors.
    Collectorless DC motor
    image.png (141.96 KiB)
    Collectorless DC motor Viewed 5302 times
    Unlike brushed DC motors, brushless DC motors do not have a mechanical commutator-collector that changes the current direction during motor rotation. In terms of construction, they are more similar to stepper motors, with the difference being that instead of two pairs of coils, they contain several sets of three coils. Based on this characteristic, they can be considered more like three-phase electric motors, and the drives for brushless motors are significantly more complex than traditional H-bridges. Indeed, each coil can conduct current in both forward and reverse directions and can also be in a "high-impedance," i.e., disconnected state. To efficiently control the motor, its control microchip (driver) must measure the voltage across the "disconnected" coil to adjust the switching time to the next phase of operation.

    Unfortunately, it is practically impossible to find brushless DC motor control chips that can be easily mounted on a prototype board. Therefore, it is better to look for ready-made driver boards.

    To obtain the power and dimensions of a brushless DC motor without the hassle of control boards, you can purchase a motor with a built-in controller and only two wires coming out of the casing. You can then connect it like a regular DC motor.