Skip to content
RFrftools.io
MotorFebruary 27, 202611 min read

DC Motor Control: PWM, Drivers, and Encoders Explained

Complete guide to controlling DC motors with PWM: selecting the right H-bridge driver, sizing the MOSFET, and closing the loop with an encoder.

Contents

Introduction

Varying voltage to change DC motor speed sounds straightforward on paper. In practice, you're juggling inrush current that can spike 10× higher than the nameplate rating, back-EMF that fights your supply voltage, thermal limits that sneak up on you during sustained loads, and position accuracy requirements that demand feedback loops. This guide breaks down each piece of the control stack so you actually understand what's happening under the hood.


The DC Motor Model

A brushed DC motor isn't just a resistor — it's got armature resistance, inductance, and a voltage source (back-EMF) all working together. The circuit model looks like this:

Vsupply=IaRa+LadIadt+VemfV_{supply} = I_a R_a + L_a \frac{dI_a}{dt} + V_{emf}

The back-EMF is proportional to shaft speed: Vemf=KeωV_{emf} = K_e \cdot \omega. Torque comes from current: T=KtIaT = K_t \cdot I_a. These constants KeK_e and KtK_t are usually buried somewhere in the datasheet, often in mixed units that make you want to scream.

Once the motor reaches steady state and the inductor stops fighting you, the equation simplifies:

ω=VsupplyIaRaKe\omega = \frac{V_{supply} - I_a R_a}{K_e}

This tells you why loaded motors slow down — the IaRaI_a R_a term eats into your effective voltage. A motor pulling 5A through 0.5Ω loses 2.5V right there, which directly translates to lost speed.

Play with these relationships using the DC Motor Speed calculator to see how armature resistance and load current affect your final RPM.


PWM Fundamentals

PWM (Pulse-Width Modulation) is how you control motor voltage without burning power in a series resistor like it's 1985. You're rapidly switching the supply on and off — the motor's inductance smooths out the pulses into an effective DC voltage:

Veff=D×VsupplyV_{eff} = D \times V_{supply}

where DD is your duty cycle from 0 to 1. Running 75% duty at 12V gives you 9V effective. Simple math, but the frequency choice matters more than most people realize.

FrequencyProsCons
1–5 kHzLow switching losses, easy to implementAudible whine drives you insane
20–50 kHzSilent operation, good efficiencyModerate switching losses
> 100 kHzLightning-fast transient responseEMI becomes a nightmare, switching losses climb
Rule of thumb: Stick with 20–25 kHz for typical brushed DC motors. It's above the audible range (no annoying whine), switching losses stay reasonable, and most microcontroller timers handle it easily. I've seen engineers go to 100 kHz thinking faster is always better, then spend weeks debugging radiated EMI and dealing with gate driver ringing.

The PWM Duty Cycle calculator lets you calculate effective voltage and estimate what your stall current will look like before you blow up your driver.


H-Bridge Drivers

Bidirectional control requires an H-bridge — four switches arranged so you can flip the polarity across the motor terminals. The name comes from the circuit topology, which literally looks like an H.

Discrete vs. Integrated

Integrated drivers like the DRV8833, TB6612, or L298N are the way to go unless you have a specific reason not to. They handle dead-time insertion (so you don't short the supply through both high-side and low-side MOSFETs), thermal shutdown, and over-current protection. The L298N is ancient and inefficient but practically indestructible — great for learning, terrible for battery-powered projects. Discrete MOSFETs make sense when you need to push serious current or want maximum efficiency. You'll need gate drivers (high-side bootstrap circuits are fun to debug), careful PCB layout to avoid shoot-through, and proper dead-time management in your control code. The efficiency gain is real though — discrete designs can hit 95%+ while the L298N struggles to break 70%.

MOSFET Selection

When you're picking MOSFETs for an H-bridge, four specs matter:

  1. VDSV_{DS} — Must exceed your supply voltage with margin. Use VDS1.5×VsupplyV_{DS} \geq 1.5 \times V_{supply} as a starting point. Transients and inductive spikes will bite you otherwise.
  1. IDI_D — Must handle peak inrush current, not just rated current. Apply ID1.5×IinrushI_D \geq 1.5 \times I_{inrush} at minimum. That inrush current can be 10× the steady-state value.
  1. RDS(on)R_{DS(on)} — Lower is always better. This determines your conduction losses. A MOSFET with 10 mΩ vs. 50 mΩ makes a huge difference at high currents.
  1. QgQ_g — Gate charge determines how fast you can switch and how much power your gate driver burns. Lower is better for high-frequency PWM.
Conduction loss per MOSFET works out to:
Pcond=I2×RDS(on)×DP_{cond} = I^2 \times R_{DS(on)} \times D

where DD is the duty cycle that particular switch is on for. High-side and low-side losses are different because they're conducting at complementary duty cycles.

The H-Bridge Selection calculator helps you figure out peak current requirements and minimum MOSFET ratings. Use the Motor Driver Power calculator to estimate total power dissipation and see if you need a heatsink.


Inrush and Starting Current

Here's the thing that catches people: when you first apply voltage to a stationary motor, the back-EMF is zero. There's nothing opposing the applied voltage except the tiny armature resistance. Initial current becomes:

Iinrush=VsupplyRaI_{inrush} = \frac{V_{supply}}{R_a}

Let's say you have a motor with 0.5Ω armature resistance running on 12V. Inrush current is 24A — even though the motor's nameplate says 2A continuous. That's a 12× multiplier. Your driver needs to handle this without letting the magic smoke out.

Mitigation strategies that actually work:
  • Soft-start the PWM duty cycle — ramp from 0% to target over 100–500ms. Simple, effective, costs you nothing but a few lines of code.
  • Use a current-limiting controller — Parts like the DRV8434 have built-in current chopping that limits peak current automatically.
  • Size the H-bridge for inrush, not rated current — This is non-negotiable. A 2A motor needs a 20–30A capable driver if you want reliability.
Most engineers skip soft-start and wonder why their drivers keep dying. Don't be that engineer.

Encoders for Closed-Loop Control

Open-loop PWM control works fine for fans, pumps, and other applications where you don't care about exact speed or position. The moment you need precision — robotics, CNC, anything with position control — you need feedback from an encoder.

Types of Encoders

Optical incremental encoders use a slotted disk and photointerrupters to generate AB quadrature pulses. They're the most common type, available from 100 to 10,000 pulses per revolution (PPR). Clean signals, good resolution, but they don't like dust or vibration. Magnetic encoders use Hall effect sensors and a magnetized ring. Much more robust to contamination and shock. You'll find these in industrial motors and automotive applications. Resolution is typically lower than optical, but they'll survive environments that would kill an optical encoder instantly. Absolute encoders output the actual shaft position as a digital word — no counting required, no homing sequence needed after power-up. They're expensive and overkill for most projects, but essential for multi-turn position tracking in things like telescope mounts or industrial robots.

Quadrature Decoding

Two channels A and B run 90° out of phase. By watching both rising and falling edges on both channels, you get 4× the resolution of the base PPR:

CPR=4×PPR\text{CPR} = 4 \times \text{PPR}

A 1000 PPR encoder gives you 4000 counts per revolution, which works out to 0.09° angular resolution. The direction of rotation comes from which channel leads — if A leads B you're going forward, if B leads A you're going backward.

Most microcontrollers have hardware quadrature decoder peripherals that handle this automatically. If you try to do it in software with interrupts, you'll start missing counts above a few thousand RPM.

Use the Encoder Resolution calculator to figure out your actual CPR, angular resolution, and maximum pulse frequency your counter needs to handle.


PID Speed Control

Once you have encoder feedback telling you the actual shaft speed, you can close the loop with a PID controller. The classic PID equation:

u(t)=Kpe(t)+Kie(t)dt+Kdde(t)dtu(t) = K_p e(t) + K_i \int e(t)\,dt + K_d \frac{de(t)}{dt}

where e(t)=ωsetpointωmeasurede(t) = \omega_{setpoint} - \omega_{measured} is your speed error.

The proportional term KpK_p gives you immediate response proportional to error. The integral term KiK_i eliminates steady-state error by accumulating error over time. The derivative term KdK_d damps oscillations by responding to the rate of change. Getting all three to play nicely together is more art than science.

Ziegler-Nichols Tuning

Ziegler-Nichols gives you a practical starting point based on the open-loop step response. It won't be perfect, but it beats random guessing:

  1. Apply a step input (say, jump from 0% to 50% PWM) and measure the motor's speed response
  2. Extract three parameters: process gain KK, dead time LL, and time constant τ\tau
  3. Calculate initial PID gains:
- Kp=1.2τ/(KL)K_p = 1.2\tau / (K \cdot L) - Ki=Kp/(2L)K_i = K_p / (2L) - Kd=Kp×0.5LK_d = K_p \times 0.5L

These won't be optimal, but they'll get you in the ballpark. From there, you tune empirically — increase KpK_p until you get oscillations, back off 50%, then adjust KiK_i and KdK_d to taste.

The PID Tuning calculator calculates initial gains from your measured step response parameters. It saves you from doing the math by hand and making arithmetic errors at 2 AM.


Thermal Management

Motors generate heat in the windings from resistive losses: P=I2RaP = I^2 R_a. Your driver generates heat from conduction losses in the MOSFETs: P=I2RDS(on)P = I^2 R_{DS(on)}. Run too hot for too long and you'll hit thermal derating or outright failure.

Operating temperature works out to:

Tmotor=Tambient+Ploss×RθT_{motor} = T_{ambient} + P_{loss} \times R_{\theta}

where RθR_{\theta} is the thermal resistance from the motor case to ambient. Datasheets usually give you this number, or you can measure it empirically by running the motor at known power and checking temperature rise with a thermocouple.

Here's the thing that bites people: copper winding resistance increases with temperature at about 0.39% per °C. A motor that's 50°C hotter than ambient has roughly 20% higher winding resistance. That means less torque for the same current, which means you need more current to maintain torque, which generates more heat. It's a vicious cycle if you're running near the thermal limit.

Check your motor's thermal derating curve in the datasheet. Most motors start derating around 100°C case temperature and are completely derated by 150°C. If you're planning to run continuous duty at high load, you need forced air cooling or a bigger motor.


Summary

Getting DC motor control right means understanding the full system:

  1. Model the motor properly — Use V=IR+KeωV = IR + K_e\omega to predict speed and current under load, not just no-load specs
  2. Size the driver for reality — Design for inrush current (5–10× rated current), not the nameplate rating
  3. Pick your PWM frequency carefully — 20–25 kHz hits the sweet spot for silence and efficiency in most applications
  4. Add feedback when you need precision — Quadrature encoders give you 4× resolution and direction sensing
  5. Tune your PID controller — Start with Ziegler-Nichols, then refine based on actual system response
  6. Don't ignore thermal limits — Calculate motor and driver temperature at maximum continuous load, not peak load
The difference between a motor control system that works and one that works reliably comes down to handling these details properly. Size everything for worst-case conditions, add margin, and test at temperature extremes before you commit to production.

Related Articles