The Core Mechanism: How PWM Speed Control Actually Works
PWM (Pulse Width Modulation) speed control varies the average power delivered to a load by rapidly switching the voltage on and off at a fixed frequency while changing the ratio of on-time to off-time (duty cycle). It changes the effective average voltage and current seen by an inductive or inertial load without burning off excess energy as heat, which is exactly what happens when you use a linear resistor to drop voltage. Think of it like flipping a room's light switch on and off ten times a second: if you leave it on for half the time, the room looks half as bright to your eye, even though the bulb only ever experiences full voltage or zero voltage.
The most common confusion among hobbyists is mixing up duty cycle (the percentage of time the signal is HIGH) with frequency (how many complete on/off cycles occur per second), or assuming the microcontroller GPIO pin outputs a smooth, variable analog DC voltage. It does not. It outputs a harsh digital square wave that the motor's internal inductance and physical inertia naturally smooth out into an average rotational speed.
The Math on the Bench: A Worked Numeric Example
Let us put real numbers on the workbench to see why PWM is mandatory for motor control. You have a 12V DC brushed motor that draws 1.5A under normal load, and you want to run it at 25% speed (which requires a 3V average).
To drop 12V down to 3V at 1.5A, you need a resistor to drop 9V. Using Ohm's Law (R = V/I), you need a 6Ω resistor. The power dissipated as heat is P = V × I = 9V × 1.5A = 13.5W. You would need a massive, expensive ceramic power resistor bolted to a heatsink, wasting 75% of your battery's energy.
Instead, you use a logic-level N-channel MOSFET like the IRLZ44N, which has an Rds(on) of 0.022Ω. You feed it a 5 kHz PWM signal at a 25% duty cycle. The MOSFET acts as a near-perfect switch. The conduction power loss is calculated as I² × R × Duty = (1.5)² × 0.022 × 0.25 = 0.012W. The MOSFET dissipates virtually zero heat, and the motor's inductance integrates the 12V pulses into a smooth 3V average.
Where You Meet PWM Speed Control in Practice
You will encounter PWM speed control across almost every embedded project that involves moving air or turning shafts:
- 4-Pin PC Case Fans: These have a dedicated PWM control wire that expects a 25 kHz open-collector signal to adjust the internal commutation without stalling the fan blades at low speeds.
- 3D Printer Part-Cooling Fans: Typically 2-pin 12V or 24V brushless fans driven by low-side MOSFETs on the printer mainboard, usually toggled between 100 Hz and 500 Hz.
- RC Car Electronic Speed Controllers (ESCs): The microcontroller sends a 50 Hz PWM servo-style pulse to the ESC to dictate throttle position, while the ESC internally uses high-frequency PWM (often >16 kHz) to drive the heavy brushless or brushed traction motor.
- CNC Spindle Routers: VFDs (Variable Frequency Drives) accept a 0-10V analog signal or a PWM-to-analog filtered signal to dictate spindle RPM.
The Frequency Trap: What People Commonly Confuse
Getting the duty cycle right only solves half the problem; choosing the wrong PWM frequency will ruin your project. According to the All About Circuits PWM Motor Control Guide, frequency dictates how the load and the environment react to the switching.
If you set your ESP32 or Arduino frequency too low (e.g., 50 Hz) on a 2-pin cooling fan, the fan's internal electronics will physically click on and off 50 times a second, creating an unbearable mechanical hum and potentially stalling the motor. If you set the frequency too high (e.g., 50 kHz) on a heavy brushed motor with long wire runs, parasitic capacitance in the cables and inductive kickback from the motor windings will cause massive voltage ringing. This ringing causes electromagnetic interference (EMI) that resets your microcontroller, and ground-bounce can permanently fry your GPIO pins.
Rule of thumb: Keep PWM frequencies above 20 kHz for small fans to push the switching noise out of human hearing range, but keep it below 5 kHz for heavy, high-current brushed DC motors to minimize MOSFET switching losses and inductive ringing.
Decision Tree: Picking Your PWM Frequency and Driver IC
Never wire a motor directly to a microcontroller pin. GPIO pins can only source 12mA to 40mA; a motor stall current will instantly destroy the silicon. Use this decision matrix to select the correct driver topology and specific part number for your load.
| Load Type | Ideal PWM Frequency | Driver Topology | Concrete Part Pick |
|---|---|---|---|
| 4-Pin PC Fan (PWM wire) | 25,000 Hz | Open-collector NPN BJT | 2N3904 or 2N7000 (with 1kΩ base/gate resistor) |
| 2-Pin 3D Printer Fan (12V/24V) | 200 - 500 Hz | Low-side Logic N-MOSFET | IRLZ44N or IRLB8721 |
| 12V-24V Brushed DC Motor (up to 3.6A) | 1,000 - 5,000 Hz | Integrated H-Bridge / Driver | TI DRV8871 |
| High-Current DC Motor / Solenoid (10A+) | 500 - 2,000 Hz | Smart High-Side Switch | Infineon BTS6143D (includes built-in flyback clamp) |
Embedded Implementation and FAQ
Why does my ESP32 PWM code throw errors or act weird in 2026?
If you are copying tutorials from 2021, they likely use ledcSetup() and ledcWrite(). In ESP-IDF v5.x and modern Arduino-ESP32 cores, these legacy functions are deprecated. You must now use the Espressif LEDC API structs: ledc_timer_config() to set the frequency and resolution, and ledc_channel_config() to bind the GPIO pin and duty cycle. Failing to update your API calls is the number one cause of compilation errors for embedded builders right now.
Can I just use a potentiometer and an L298N for speed control?
The L298N is a bipolar junction transistor (BJT) based driver from the 1990s. It suffers from a massive internal voltage drop (often 2V to 3V lost as heat across the darlington pairs). For modern PWM speed control, use MOSFET-based drivers like the DRV8871 or TB6612FNG, which have Rds(on) values in the milliohm range, delivering nearly 100% of your battery voltage to the motor.
Do I need a flyback diode?
Yes, if you are using a discrete MOSFET (like the IRLZ44N) to switch an inductive load. When the MOSFET turns off, the motor's collapsing magnetic field generates a massive reverse voltage spike that will punch through the MOSFET's drain-source junction. Place a Schottky diode (like a 1N5819 or SS34) in reverse bias across the motor terminals. If you use an integrated driver like the DRV8871 or a smart high-side switch like the BTS6143D, the flyback clamping circuitry is already built into the silicon.






