Motors and Drives
How robots move: brushed DC motors, hobby servos, stepper and brushless motors, gearboxes and strain wave gears, and the H-bridges and motor drivers that sit between a microcontroller and a motor.
From signal to motion
Between the program that decides "move joint 2 to 45 degrees" and the joint that moves, there is always the same chain:
- A controller — a microcontroller in a hobby robot, a motion controller in an industrial one — computes a command, usually as a PWM signal or a step pulse.
- A driver turns that weak signal into motor current, from a battery or a power supply.
- A motor turns current into rotation.
- A gearbox turns fast, weak rotation into slow, strong rotation at the joint or wheel.
- A sensor — an encoder, or the potentiometer inside a servo — reports what really happened, closing the loop (see Sensors for Robots).
The motor is an actuator in the sense of the IoT topic. What makes robot motors special is that their position and speed must be controlled precisely, not just switched on and off.
Brushed DC motors
A brushed DC motor is the simplest electric motor: connect it to a DC voltage and it turns; reverse the voltage and it turns the other way. Inside, carbon brushes rub on a segmented ring (the commutator) that switches the current through the rotating coils as the shaft turns. They are in toy cars, small robot cars, power windows and cordless drills — cheap and easy to drive, but the brushes wear out and spark.
Two rules from the motor maker maxon describe how a DC motor behaves. First, "the torque constant links the mechanical torque M with the electrical current I":
where \tau is the torque in newton meters, I the current in amperes and k_M the motor's torque constant from its datasheet. Second, "No-load speed and stall torque change proportionally to the applied voltage". So to control the speed, you control the voltage — in practice with PWM, switching the full supply on and off thousands of times a second (see duty cycle). The torque, and with it the current, follows from the load: a motor that is blocked (stalled) draws its highest current, turns it all into heat and can burn out.
Gearboxes
Small DC motors spin fast — thousands of revolutions per minute — with little torque. A robot wheel or joint needs the opposite. A gearbox with ratio N multiplies the torque by N and divides the speed by N; in the ideal case nothing is lost, and in reality some power turns into heat in the gears, expressed as an efficiency \eta below 1:
The example works through a small motor with a 30:1 gearbox driving a wheel with a radius of 3.3 cm. The motor numbers and the 80% efficiency are example values:
import math
# A small brushed DC motor with a 30:1 gearbox driving a wheel.
# Motor figures are example values; check your motor's datasheet.
motor_torque = 0.020 # N·m at the operating point
motor_rpm = 6000
RATIO = 30 # gear ratio: 30 motor turns per output turn
EFFICIENCY = 0.80 # assumed; real gearboxes lose some power as heat
WHEEL_RADIUS = 0.033 # m
out_torque = motor_torque * RATIO * EFFICIENCY
out_rpm = motor_rpm / RATIO
print(f"output: {out_torque:.2f} N·m at {out_rpm:.0f} rpm")
force = out_torque / WHEEL_RADIUS # push at the floor
speed = out_rpm / 60 * 2 * math.pi * WHEEL_RADIUS # wheel rim speed
print(f"wheel : {force:.1f} N of push, {speed:.3f} m/s")
output: 0.48 N·m at 200 rpm wheel : 14.5 N of push, 0.691 m/s
Gears have a weakness: backlash, the small play between meshing teeth. When the motor reverses, the output does not move until the teeth meet on the other side. For a wheel that hardly matters; for a robot joint it means the tool can wobble by the amount of play, multiplied by the length of the arm.
Strain wave and cycloidal gears
Robot joints therefore use special reduction gears with very little backlash and high ratios in a small space. The best known is the strain wave gear, sold under the trademark Harmonic Drive. It has three parts: an oval wave generator turns inside a thin, flexible steel cup with teeth on the outside (the flexspline), which meshes with a rigid ring with slightly more teeth on the inside (the circular spline). As the oval turns, the flexspline creeps round by the difference in teeth, giving ratios such as 30, 50, 80, 100, 120 and 160 in one stage (the maker's CSF series). The manufacturer states that its gearheads have "Zero Backlash". The principle was patented by C. Walton Musser in the 1950s.
Cycloidal reducers are another choice for robot joints that carry heavy loads. For its RV series, Nabtesco gives a backlash of less than one arcminute and a shock resistance "up to 500% of the rated torque" — useful when a robot stops hard.
Hobby servos
A hobby servo (or RC servo, from radio-controlled models) is a small DC motor, a gearbox, a potentiometer on the output shaft and a control circuit in one plastic case. You send it the angle you want; its circuit compares that with the potentiometer and drives the motor until the two match. Three wires: power, ground and signal.
The angle is set by the width of a pulse repeated every 20 ms (50 Hz). Nominally 1.5 ms means the center and about 1.0 to 2.0 ms covers the range, but there is no standard for the minimum and maximum, and the numbers in use differ:
- The datasheet of Parallax's (digital) Standard Servo accepts "500 µs to 2530 µs" and maps 620, 1520 and 2420 µs to 0°, 90° and 180°.
- The Arduino Servo library defaults to 544 µs and 2400 µs for the ends, 1500 µs in the middle, and a 20,000 µs refresh interval.
-
The gpiozero
Servoclass for the Raspberry Pi defaults to 1 ms and 2 ms with a 20 ms frame, "a common value for servos".
In MicroPython, machine.PWM sets either the duty cycle
as "a ratio duty_u16 / 65535" or the pulse width directly with
duty_ns — use only one of the two. The example converts
pulse widths at 50 Hz into duty_u16 values, and angles
into pulse widths with the Parallax mapping:
# Hobby servo: pulse width at 50 Hz (a 20 ms frame) as a MicroPython duty_u16.
FRAME_US = 20_000 # 50 Hz
def duty_u16(pulse_us):
return round(pulse_us / FRAME_US * 65535)
for pulse in (1000, 1500, 2000):
print(f"{pulse} µs = {pulse / FRAME_US:5.1%} duty -> duty_u16 {duty_u16(pulse)}")
# The Parallax Standard Servo datasheet maps 620, 1520 and 2420 µs
# to 0, 90 and 180 degrees. In between, interpolate linearly:
def pulse_for_angle(angle, min_us=620, max_us=2420):
return min_us + angle / 180 * (max_us - min_us)
for angle in (0, 45, 90, 180):
p = pulse_for_angle(angle)
print(f"{angle:3} degrees -> {p:6.0f} µs -> duty_u16 {duty_u16(p)}")
1000 µs = 5.0% duty -> duty_u16 3277 1500 µs = 7.5% duty -> duty_u16 4915 2000 µs = 10.0% duty -> duty_u16 6554 0 degrees -> 620 µs -> duty_u16 2032 45 degrees -> 1070 µs -> duty_u16 3506 90 degrees -> 1520 µs -> duty_u16 4981 180 degrees -> 2420 µs -> duty_u16 7930
On an ESP32 with MicroPython, setting the Parallax servo to 45° looks like this:
from machine import Pin, PWM
# 50 Hz is a 20 ms frame; 1070 µs is about 45 degrees on this servo.
servo = PWM(Pin(18), freq=50, duty_ns=1_070_000)
A continuous-rotation servo is a servo without the position feedback: 1.5 ms means stop (adjusted with a small trim potentiometer), and shorter or longer pulses make it turn one way or the other, faster the further from 1.5 ms. It is an easy way to drive the wheels of a small robot.
Stepper motors
A stepper motor turns in fixed steps: each pulse to its driver moves the shaft by one step and holds it there. A typical hybrid stepper has 1.8° steps, so 200 steps per revolution. NEMA 17, a common size in small machines, is generally described as a faceplate of about 1.7 inches (42 mm) square — a size, not a strength: NEMA 17 motors differ a lot in torque.
Because each pulse is one step, a controller can move a stepper to an exact position by counting pulses, without any sensor. That is also its weakness. As the motor maker Oriental Motor explains, "the motor cannot follow the pulse speed beyond a certain point, so that missteps result" — and nothing tells the controller. A 3D printer whose print suddenly shifts sideways has typically lost steps.
Drivers can also microstep: they divide each step into smaller ones by sharing the current between the coils, for smoother and quieter motion. Two common driver chips:
- DRV8825 (Texas Instruments): up to 1/32 microstepping, 8.2–45 V, up to 2.5 A at 24 V.
- A4988 (Allegro): up to 1/16 microstepping, up to 35 V and ±2 A, with a logic supply that is "3.3 and 5 V compatible".
Both limit the coil current with a sense resistor and a reference voltage (VREF) you set with a small potentiometer: for the DRV8825 the datasheet gives I = V_\text{REF} / (5 \cdot R_\text{SENSE}), for the A4988 I = V_\text{REF} / (8 \cdot R_S). The example computes the resolution of a lead-screw axis and the VREF for a few current limits:
# Stepper motor on a lead screw (for example the Z axis of a small machine).
STEPS_PER_REV = 200 # 1.8 degrees per full step
MICROSTEPS = 16 # driver set to 1/16 microstepping
LEAD_MM = 8 # the nut moves 8 mm per screw turn
steps_per_mm = STEPS_PER_REV * MICROSTEPS / LEAD_MM
print(f"{steps_per_mm:.0f} microsteps per mm, {1000 / steps_per_mm:.1f} µm per microstep")
speed_mm_s = 10
print(f"{speed_mm_s} mm/s needs {speed_mm_s * steps_per_mm:,.0f} step pulses per second")
# DRV8825 current limit: I = VREF / (5 * RSENSE). Check the sense
# resistor on your board; 0.1 ohm is used here as an example.
RSENSE = 0.1
for amps in (0.5, 1.0, 1.5):
print(f"limit {amps:.1f} A -> set VREF to {amps * 5 * RSENSE:.2f} V")
400 microsteps per mm, 2.5 µm per microstep 10 mm/s needs 4,000 step pulses per second limit 0.5 A -> set VREF to 0.25 V limit 1.0 A -> set VREF to 0.50 V limit 1.5 A -> set VREF to 0.75 V
A microstep of 2.5 µm is a commanded position, not a measured one. Steppers suit printers, plotters and small linear axes, where loads are known; they are less common in industrial robot arms, which carry changing loads and must know their position for certain.
Brushless motors
A brushless DC motor (BLDC) turns the brushed motor inside out: the magnets turn and the coils stand still, and electronics switch the current through the coils in the right order — electronic commutation. No brushes means no wear, no sparks, more power for its size and a long life. The price is that a brushless motor cannot run without a driver that knows where the rotor is, either from sensors in the motor (sensored) or from the voltages the coils produce (sensorless).
Drivers use one of two methods:
- Trapezoidal (block) commutation switches the coils in a fixed sequence of steps: easy and cheap, with some torque ripple.
- Field-oriented control (FOC), "a motor control strategy that orients the stator current vector" (imperix), computes sine-shaped currents so the magnetic field always pulls the rotor at the best angle: smooth, quiet and efficient, at the cost of more computation.
Drones use brushless motors with a small driver per motor, usually called an electronic speed controller (ESC). The joints of industrial robots typically use brushless servo motors with an encoder and a servo drive that controls current, speed and position in nested loops — see Motion Control and PID.
H-bridges
To run a DC motor in both directions, the current must be able to flow through it either way. An H-bridge is a circuit of four switches — transistors in practice — arranged in an H around the motor: closing one diagonal pair sends current through the motor one way, closing the other pair sends it the other way.
The four useful states are:
- Forward and reverse: one diagonal pair closed. PWM on one of the switches sets the speed.
- Brake: both lower (or both upper) switches closed. The motor's terminals are shorted together, and the voltage it generates while spinning brakes it quickly.
- Coast: all switches open. The motor spins down freely.
Driver chips name these states in their own way; the Toshiba
TB6612FNG, for example, lists CW, CCW, short brake and stop.
Libraries hide the switches entirely: the gpiozero
Motor class for the Raspberry Pi "represents a generic
motor connected to a bi-directional motor driver circuit (i.e. an
H-bridge)".
A motor's coils resist sudden changes in current. When a switch opens, the coil's current must go somewhere, and it produces a voltage spike that can destroy transistors. Diodes across the switches give that current a safe path. MOSFET drivers usually rely on the diodes built into their transistors (check the datasheet), while the L298's datasheet says external diodes are required (see the flyback diode on Building Your First Robot).
Motor drivers
A motor driver is the component between a controller and a motor: it takes logic-level signals (direction, PWM, step pulses) and switches the motor supply's current accordingly. For small DC motors that means one or two H-bridges on a chip or a small board; for steppers, a chip that also sequences and limits the coil currents; for brushless motors, a driver that also commutates. Three common dual H-bridge drivers for small DC motors, from their datasheets:
| Driver | Switches | Motor voltage | Current per channel | Note |
|---|---|---|---|---|
| L298 (ST) | bipolar transistors | up to 46 V | 2 A DC (4 A total) | drops 1.80–3.2 V at 1 A, up to 4.9 V at 2 A; needs external diodes |
| TB6612FNG (Toshiba) | MOSFETs | 2.5–13.5 V (15 V absolute max.) | 1.0 A average (1.2 A absolute max.), 3.2 A peak (pulsed) | modes CW, CCW, short brake, stop |
| DRV8833 (TI) | MOSFETs | 2.7–10.8 V | 1.5 A RMS (PWP/RTY packages), 500 mA RMS (PW package); 2 A peak | check which package a breakout board uses |
The L298 still appears in countless kits and tutorials, but its bipolar switches lose a lot of voltage. For the 3–6 V motors of a small robot that matters, as the example shows:
# What a 6 V battery pack leaves for the motor behind an L298 driver.
# The datasheet gives a total voltage drop of 1.80 to 3.2 V at 1 A,
# and up to 4.9 V at 2 A.
SUPPLY_V = 6.0
for amps, drop_v in [(1.0, 1.80), (1.0, 3.2), (2.0, 4.9)]:
motor_v = SUPPLY_V - drop_v
heat_w = drop_v * amps
print(f"{amps:.0f} A, drop {drop_v:4.2f} V -> motor gets {motor_v:4.2f} V "
f"({motor_v / SUPPLY_V:.0%}), driver heats with {heat_w:.1f} W")
1 A, drop 1.80 V -> motor gets 4.20 V (70%), driver heats with 1.8 W 1 A, drop 3.20 V -> motor gets 2.80 V (47%), driver heats with 3.2 W 2 A, drop 4.90 V -> motor gets 1.10 V (18%), driver heats with 9.8 W
At 1 A, a third to half of the battery's voltage goes into heating the driver; at 2 A it is more than four fifths. A MOSFET driver such as the TB6612FNG or the DRV8833 loses much less, which is why Building Your First Robot recommends one of those for small motors. The L298 remains a reasonable choice only for higher voltages and currents within its ratings, with a heat sink.
Choosing a motor
| Motor | Position known? | Typical use | Needs |
|---|---|---|---|
| Brushed DC + gearbox | only with an encoder | wheels of small robots, toys | H-bridge driver, PWM |
| Hobby servo | yes, inside (not reported back) | grippers, pan-tilt heads, small arms | one PWM pin, its own supply |
| Stepper | counted, not measured | printers, plotters, linear axes | stepper driver, step and direction pulses |
| Brushless (BLDC) | with sensors or an encoder | drones, robot joints, high power | ESC or servo drive |
Whatever the motor, its position is only as good as the sensor that measures it. The encoders that close the loop are on Sensors for Robots.
Working safely with motors
Even small motors deserve respect, and industrial drives demand it.
- Keep hobby projects on low voltage. Use battery packs or a certified power supply; do not wire anything to 230 V (or 120 V) mains yourself.
- Separate motor and logic power. Motors pull current spikes when they start and reverse. Feed them from their own supply, and connect the grounds of the motor supply and the microcontroller together so the control signals share a reference.
- Mind stall current and heat. A blocked motor draws its highest current; size the driver and the wiring for it, and feel for hot drivers and motors after a test run.
- Batteries store a lot of energy. LiPo packs in particular need careful charging and storage — see Building Your First Robot.