Choosing DC, Servo and Stepper Motors for Your Robot Project
The motor is the part of a robot that does the actual work, and choosing the wrong type is an expensive mistake. A stepper motor on a fast wheeled robot wastes battery and loses steps; a cheap DC motor on a robot arm cannot hold a position; a small servo on a heavy pan mechanism strips its plastic gears. Each motor family is good at one kind of job.
In this tutorial you will learn how brushed DC gear motors, hobby servos and stepper motors work, which robot jobs suit each one, how to do a quick torque estimate, and how each type is driven from an Arduino. A single example sketch drives all three so you can compare them on your bench.
How Each Motor Type Works
Brushed DC gear motor
A brushed DC motor spins whenever voltage is applied, and its speed rises with voltage. Reversing the polarity reverses the direction. A gearbox trades the motor's high speed for higher torque at the output shaft. Common robot examples are the yellow plastic BO motors and the small metal N20 motors, both sold in many gear ratios. Speed is controlled with PWM through an H-bridge driver. On its own a DC motor has no idea where its shaft is, so position control needs an encoder.
Hobby servo
A hobby servo such as the SG90 or MG996R contains a DC motor, a gearbox, a potentiometer on the output shaft and a small control board. You send a pulse every 20 ms, and the pulse width, roughly 1 to 2 ms, sets the target angle, usually over a range of about 180 degrees. The servo holds that angle against load. Continuous-rotation servos exist too, where the pulse width sets speed instead of angle.
Stepper motor
A stepper motor moves in fixed steps when its coils are energised in sequence. The common NEMA 17 hybrid stepper has 200 full steps per revolution, which is 1.8 degrees per step, and drivers such as the A4988 or DRV8825 add microstepping for smoother motion. Because each step is a known angle, a stepper can position accurately without an encoder as long as the load never exceeds its torque. If it does, the motor silently skips steps and the controller loses track of position.
Side-by-Side Comparison
| Property | DC gear motor | Hobby servo | Stepper motor |
|---|---|---|---|
| Control input | PWM duty and direction | Pulse width every 20 ms | Step and direction pulses |
| Position feedback | None unless encoder fitted | Built-in potentiometer | None, counts steps open loop |
| Best at | Continuous wheel rotation | Holding an angle | Precise repeatable positioning |
| Driver needed | H-bridge (L298N, TB6612FNG) | None, signal pin only | Stepper driver (A4988, DRV8825) |
| Current when idle | Zero when stopped | Small, rises with load | Draws holding current while enabled |
| Typical robot use | Wheels of 2WD and 4WD cars | Arm joints, grippers, sensor pan | 3D printers, plotters, slow precise drives |
A Quick Torque Estimate for Wheels
To climb a slope or accelerate, the wheels must push the robot with enough force. A simple estimate takes the robot weight, the steepest slope you expect and a margin for rolling resistance and acceleration, then shares the load among the driven wheels.
Force along slope F = m * g * sin(angle) Torque per wheel T = (F * r) / N Example: m = 1.5 kg, slope 10 deg, wheel radius r = 0.033 m, N = 2 driven wheels F = 1.5 * 9.81 * sin(10 deg) = 1.5 * 9.81 * 0.174 = 2.56 N T = (2.56 * 0.033) / 2 = 0.042 N*m (about 0.43 kg*cm) Apply a safety factor of 2 to 3 for friction and acceleration -> ~1 kg*cm per motor
Compare that number with the rated torque on the motor's datasheet, not the stall torque. Stall torque is the maximum at zero speed, and running near it draws very high current and overheats the motor. For a servo arm, the torque at a joint is the weight of everything beyond the joint multiplied by its horizontal distance from the joint, which is covered in the robotic arm tutorial.
Driving All Three from an Arduino
Wiring for the sketch below: the DC motor goes through a TB6612FNG channel A (PWMA to pin 5, AIN1 to pin 7, AIN2 to pin 8, STBY to pin 4). The servo signal goes to pin 9. The A4988 STEP input goes to pin 2 and DIR to pin 3, with its SLEEP and RESET pins tied together and MS1 to MS3 left low for full steps. Each motor uses an external supply sharing ground with the Arduino.
#include <Servo.h>
// --- DC motor on TB6612FNG channel A ---
const int PWMA = 5;
const int AIN1 = 7;
const int AIN2 = 8;
const int STBY = 4;
// --- Servo signal ---
const int SERVO_PIN = 9; // note: Servo library disables PWM on pins 9 and 10 on the Uno
Servo armServo;
// --- Stepper on A4988 (full-step mode) ---
const int STEP_PIN = 2;
const int DIR_PIN = 3;
const int STEPS_PER_REV = 200; // 1.8 degree stepper
void dcMotor(int speed) { // speed -255..255
digitalWrite(AIN1, speed >= 0 ? HIGH : LOW);
digitalWrite(AIN2, speed >= 0 ? LOW : HIGH);
analogWrite(PWMA, abs(speed));
}
void stepperMove(int steps, bool clockwise, unsigned int usPerStep) {
digitalWrite(DIR_PIN, clockwise ? HIGH : LOW);
for (int i = 0; i < steps; i++) {
digitalWrite(STEP_PIN, HIGH); // A4988 steps on the rising edge
delayMicroseconds(5);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usPerStep); // larger delay = slower rotation
}
}
void setup() {
pinMode(PWMA, OUTPUT); pinMode(AIN1, OUTPUT);
pinMode(AIN2, OUTPUT); pinMode(STBY, OUTPUT);
digitalWrite(STBY, HIGH); // take TB6612FNG out of standby
pinMode(STEP_PIN, OUTPUT); pinMode(DIR_PIN, OUTPUT);
armServo.attach(SERVO_PIN);
}
void loop() {
// 1. DC motor: ramp up forward, then reverse, then stop
for (int s = 0; s <= 200; s += 10) { dcMotor(s); delay(50); }
delay(1000);
dcMotor(-150); delay(1000);
dcMotor(0); delay(500);
// 2. Servo: move to three angles and hold each one
armServo.write(0); delay(800);
armServo.write(90); delay(800);
armServo.write(180); delay(800);
// 3. Stepper: exactly one revolution each way
stepperMove(STEPS_PER_REV, true, 2000);
delay(500);
stepperMove(STEPS_PER_REV, false, 2000);
delay(1000);
}
Notice the difference in what each command means. The DC motor receives a speed and you have no idea how far it travelled. The servo receives an angle and goes there on its own. The stepper receives a number of steps, and exactly 200 of them brings the shaft back to the same position, provided no steps were lost.
Selection Mistakes to Avoid
- Choosing motors by RPM alone. Wheel speed is RPM times wheel circumference, and a higher gear ratio gives torque at the cost of speed.
- Powering several servos from the Arduino 5 V pin. Even SG90s can draw hundreds of milliamps when moving; use a separate 5 V to 6 V supply.
- Setting the A4988 current limit too high or not at all. Adjust its trimmer according to the driver documentation and your motor's rated current.
- Expecting a stepper to be fast. Torque drops as step rate rises, and beyond a certain speed it stalls.
- Forcing a servo against its mechanical stop, which makes it draw high current and heat up.
Summary
Use DC gear motors for wheels, servos for joints that must hold an angle, and steppers for slow, precise, repeatable motion. Estimate the torque you need with a simple force calculation and a safety factor, and pick a driver that matches the motor type and current. The next tutorial compares the two most popular DC motor drivers, the L298N and the TB6612FNG.