stepper motor control with arduino uno and motor driver

How to Control a Stepper Motor with Arduino: Ultimate Guide

Introduction

Stepper motors are widely used in robotics, CNC machines, and automation projects. They offer precise control over position and speed, making them an excellent choice for Arduino enthusiasts. In this guide, we’ll cover everything you need to know about controlling a stepper motor with Arduino.

stepper motor control with arduino uno and motor driver

What is a Stepper Motor?

A stepper motor moves in fixed steps instead of spinning freely. Each pulse from the Arduino turns the shaft by one step — typically 1.8° (200 steps per revolution) for a NEMA 17, or 5.625° per step for a 28BYJ-48 (which has internal gearing, so it takes 2048 steps per revolution at the output shaft). Because the Arduino counts the steps, it always knows the shaft’s position — no encoder needed. That is why steppers are used in 3D printers, CNC machines and robot arms, where position matters more than speed.

Types of Stepper Motors

Stepper motors come in various types, but the most common are:

Unipolar Stepper Motors

These have a center tap in their coils, allowing simpler control but requiring more wiring. The 28BYJ-48 is the common unipolar motor for beginners — it runs on 5V with a ULN2003 driver board.

Bi-polar Stepper Motors

More efficient and powerful but needs an H-bridge driver like A4988 or DRV8825. The NEMA 17 is the common bipolar motor — it runs on 12V with an A4988 driver.

Step Angle and Torque Ratings

Step angle determines the precision of movement (1.8° per step is standard for NEMA 17); torque determines how much force the motor can apply. A bigger motor is not always better — match the torque to your load, and check the driver’s current rating before buying.

Understanding Stepper Motor Drivers

Stepper motors require special drivers for operation. Common options include:

  • ULN2003: Suitable for 28BYJ-48 motors, operates at 5V.
  • A4988: Used for NEMA 17 motors, supports micro-stepping.
  • DRV8825: Provides higher current capability for powerful motors.

The driver sits between the Arduino and the motor: the Arduino sends low-current step and direction signals, and the driver switches the higher motor current. The Arduino never powers the motor directly.

Wiring the Stepper Motor to Arduino

NEMA 17 + A4988

NEMA 17 stepper motor
A4988 PinConnects To
STEPArduino D10
DIRArduino D11
ENABLEArduino D12
VMOT12V power supply (+)
GND (motor side)12V power supply (−) and Arduino GND
1A, 1BOne motor coil
2A, 2BThe other motor coil
VDDArduino 5V

The one rule that matters: the 12V supply’s GND and the Arduino’s GND must be connected together (common ground). Without it, the STEP and DIR signals have no reference and the motor will not move — or will move randomly.

28BYJ-48 + ULN2003

ULN2003 PinConnects To
IN1Arduino D8
IN2Arduino D9
IN3Arduino D10
IN4Arduino D11
+ (5V)Arduino 5V (the motor only draws ~200 mA)
− (GND)Arduino GND

The 28BYJ-48 plugs straight into the ULN2003 board with its own connector — no coil wiring to work out.

Using an External Power Supply

Stepper motors draw significant currents. Using an external power supply prevents overheating and power issues. Connect the motor’s power to an external source while ensuring the ground is shared with Arduino.

Never power a NEMA 17 from the Arduino’s 5V pin. The Arduino’s regulator can supply about 500 mA; a NEMA 17 wants 1–1.5 A. It will brown out the Arduino, reset it, or damage the regulator. Use a 12V 2A adapter (Rs 275) for the motor side and USB for the Arduino. The 28BYJ-48 is the exception — at 5V and ~200 mA it can run from the Arduino’s 5V pin.

Programming the Stepper Motor in Arduino IDE

Here’s a basic code to control a stepper motor — NEMA 17 with an A4988 driver:

// NEMA 17 + A4988 — rotate forward 1 second, then backward 1 second
// STEP = D10, DIR = D11, ENABLE = D12

#define STEP_PIN    10
#define DIR_PIN     11
#define ENABLE_PIN  12

void setup() {
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(ENABLE_PIN, OUTPUT);

  // A4988 ENABLE is active LOW
  digitalWrite(ENABLE_PIN, LOW);
  digitalWrite(STEP_PIN, LOW);
}

void stepForOneSecond() {
  // 500 steps x 2 ms per step = 1000 ms = 1 second
  for (int i = 0; i < 500; i++) {
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(1000);
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(1000);
  }
}

void loop() {
  digitalWrite(DIR_PIN, HIGH);  // forward
  stepForOneSecond();
  delay(100);

  digitalWrite(DIR_PIN, LOW);   // backward
  stepForOneSecond();
  delay(100);
}

This code rotates the motor forward for one second, then backward for one second, and repeats. (The old code in this post only stepped in one direction — the text claimed forward-and-backward, but the code never changed direction. This version does what the text says.)

Advanced Stepper Motor Control

  • Speed Control: Adjusting RPM dynamically — shorten the delayMicroseconds() value for faster steps, lengthen it for slower. Too short and the motor stalls instead of turning.
  • Acceleration: Using libraries like AccelStepper — ramping the speed up and down instead of jumping straight to full speed, so the motor doesn’t skip steps.
  • Microstepping: Enhancing precision with A4988/DRV8825 — the MS1/MS2/MS3 pins divide each full step into 2, 4, 8 or 16 micro-steps for smoother, quieter motion.

Controlling Multiple Stepper Motors

For dual motor control, use multiple drivers and adjust the code accordingly:

#include <AccelStepper.h>

// Two 28BYJ-48 motors on ULN2003 boards (FULL4WIRE mode)
AccelStepper stepper1(AccelStepper::FULL4WIRE, 8, 9, 10, 11);
AccelStepper stepper2(AccelStepper::FULL4WIRE, 4, 5, 6, 7);

void setup() {
  stepper1.setMaxSpeed(500);
  stepper1.setSpeed(200);
  stepper2.setMaxSpeed(500);
  stepper2.setSpeed(200);
}

void loop() {
  stepper1.runSpeed();
  stepper2.runSpeed();
}

The fix in this sketch: the old version called setMaxSpeed() but never called setSpeed() — and runSpeed() runs at the speed set by setSpeed(), which defaults to 0. With speed 0, neither motor moves at all. Both motors now get setSpeed(200) in setup. (runSpeed() runs at a constant speed; if you want acceleration, use moveTo() + run() instead.)

Common Issues and Troubleshooting

  • The motor is not moving. Check the wiring and connections — especially the common ground between the power supply and the Arduino, and that ENABLE is LOW on the A4988.
  • The motor vibrates but doesn’t turn. Usually the step rate is too fast (increase delayMicroseconds()), or one coil wire is loose, or the driver current is set too low.
  • Overheating: Reduce current or improve cooling — set the A4988 current limit with its small potentiometer, and add a heatsink to the driver chip.
  • Skipping steps: Use micro-stepping and increase torque — or slow down the acceleration so the motor can keep up.

Applications of Stepper Motors with Arduino

  • 3D Printing: Controlling extruder and bed movement.
  • CNC Machines: High-precision cutting and engraving — see our CNC machine guide.
  • Robotics: Controlling arms and wheels — see our robot car guide.
  • Automation: Home automation, conveyor belts, etc.

Best Practices for Efficient Stepper Motor Control

  • Use a dedicated power source.
  • Implement acceleration and deceleration.
  • Utilize micro-stepping for smoother motion.
  • Keep wires short to reduce interference.

Where to Buy the Parts

For a DC motor instead of a stepper, see our L298N motor driver guide.

Conclusion

Controlling a stepper motor with Arduino opens up a world of possibilities in automation, robotics, and DIY electronics. By understanding the components, wiring, and programming techniques, you can create precise and efficient motor control systems for your projects.

Still Stuck?

If the motor vibrates but won’t turn, the driver gets hot, or nothing moves at all, message us on WhatsApp and we’ll help you debug it — or watch the build on our YouTube channel.

Frequently Asked Questions

Q1: My motor vibrates but doesn’t turn. What’s wrong?

Three usual causes: (1) the step rate is too fast — increase delayMicroseconds() from 1000 to 2000 and try again; (2) one coil wire is loose or swapped — check the 1A/1B and 2A/2B pairs with a multimeter (each pair should read a few ohms); (3) the driver current limit is set too low — turn the A4988’s small potentiometer slightly clockwise to raise it.

Q2: Why does the A4988 driver get so hot?

Steppers draw their full rated current even when standing still — that is normal, and the driver chip gets hot. A heatsink on the chip helps; so does setting the current limit to match your motor (not higher). If the driver is too hot to touch for more than a second, the current is set too high — turn the potentiometer down.

Q3: 28BYJ-48 or NEMA 17 — which should I buy?

For a first project, the 28BYJ-48 (Rs 405 with its ULN2003 board) — 5V, plugs straight in, and slow enough to learn on. For a CNC machine, 3D printer or anything that needs real torque, the NEMA 17 (Rs 670) with an A4988 driver and a 12V supply. They are not interchangeable: the 28BYJ-48 is unipolar (ULN2003), the NEMA 17 is bipolar (A4988/DRV8825).

Q4: How many steps make one full revolution?

A NEMA 17 takes 200 full steps per revolution (1.8° per step). With 16× microstepping that becomes 3200 micro-steps. A 28BYJ-48 takes 2048 steps per revolution at its output shaft because of its internal 1:64 gearing (the motor itself does 32 steps per revolution, the gearbox multiplies it).

Q5: Can the Arduino power the stepper motor directly?

No — never connect a motor to the Arduino’s 5V pin (except the small 28BYJ-48, which draws only ~200 mA). A NEMA 17 wants 1–1.5 A at 12V; the Arduino’s regulator can supply about 500 mA. Use a separate 12V supply for the motor and join its GND to the Arduino’s GND.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *