A PWM (Pulse Width Modulation) wave is a digital square wave signal where the ratio of ON time to OFF time (duty cycle) is varied to simulate an analog voltage level. In a real circuit, it changes the average power delivered to a load without dropping the peak voltage, allowing 3.3V or 5V microcontroller pins to control high-power analog behaviors like motor speed or LED brightness. Beginners commonly confuse a PWM wave with a true analog voltage from a Digital-to-Analog Converter (DAC) or a Variable Frequency Drive (VFD); unlike a DAC, a PWM wave never smooths out into steady DC without a low-pass filter, and unlike a VFD, the frequency stays constant while only the pulse width changes.
The Core Mechanics of a PWM Wave
To master PWM, you must separate the signal into two independent variables: frequency and duty cycle. The frequency dictates how many complete ON/OFF cycles occur per second (measured in Hertz), while the duty cycle dictates the percentage of time the signal spends in the HIGH (ON) state during each cycle.
Imagine you are flicking a light switch ON and OFF exactly once every second. If you leave it ON for half a second and OFF for half a second, the room receives 50% of its maximum possible light. If you flick it faster (say, 1,000 times a second) but keep the same 50% ratio, the human eye stops seeing the flicker and just perceives a dimmer bulb. The speed of your flicking is the frequency; the ratio of ON to OFF time is the duty cycle.
Mathematically, the average voltage ($V_{avg}$) delivered to a resistive load is calculated using a straightforward formula:
Example: A 5V peak signal at a 20% duty cycle yields an average voltage of 1.0V.
However, this average voltage only behaves like true DC when the load has high inertia (like a spinning motor rotor) or high persistence (like the human eye viewing an LED). If you connect a standard multimeter to a raw PWM pin, it will likely read erratic values because it cannot sample the high-speed transitions accurately. You need an oscilloscope to see the actual square wave.
Worked Numeric Example: Sizing a PWM Wave for a 12V DC Motor
Let us design a drive circuit for a 12V nominal DC gearmotor with a stall current of 2.5A and a running current of 1.2A. We want to run it at roughly 75% speed using an ESP32-WROOM-32 (3.3V logic) and an N-channel logic-level MOSFET.
1. Selecting the Frequency: We choose 5,000 Hz (5 kHz). This is high enough to sit above the human hearing range (preventing the motor from emitting an audible whine) but low enough to keep the MOSFET switching losses minimal. According to Espressif's MCPWM documentation, modern ESP-IDF v5.x firmware uses the dedicated MCPWM peripheral for motor control rather than the older LEDC peripheral, allowing hardware-deadtime insertion to prevent shoot-through in H-bridges.
2. Setting the Duty Cycle: We target a 75% duty cycle.
- Average Voltage: $12V \times 0.75 = 9V$.
- Average Current: Assuming a roughly linear mechanical load for this estimation, the motor will draw about $1.2A \times 0.75 = 0.9A$.
3. Calculating MOSFET Heat Dissipation: We select the IRLZ44N logic-level MOSFET. Because it is 'logic-level', its gate threshold is low enough to fully turn on with the ESP32's 3.3V GPIO output. At $V_{GS} = 3.3V$, its $R_{DS(on)}$ (drain-source on-resistance) is approximately 0.022Ω.
$P = I^2 \times R_{DS(on)}$
$P = (0.9A)^2 \times 0.022\Omega = 0.81 \times 0.022 = 0.0178W$
At less than 18 milliwatts of heat, the MOSFET will remain completely cool to the touch. No heatsink is required.
4. Gate Charge Check: The IRLZ44N has a total gate charge ($Q_g$) of roughly 72nC. At 5kHz, the average gate current required to charge and discharge the gate is $I_g = Q_g \times f = 72nC \times 5000 = 0.36mA$. The ESP32 GPIO can safely source up to 20mA, meaning we can drive this MOSFET directly without a dedicated gate driver IC.
Where You Meet This in Practice
While the math remains the same, the physical implementation of a PWM wave changes drastically depending on the load. As detailed in All About Circuits' PWM guide, the load's electrical characteristics dictate your frequency and filtering needs.
- LED Dimming: LEDs react instantly to voltage. If your PWM frequency is below 100Hz, human eyes will perceive a strobe effect, and smartphone cameras will capture severe banding. For LEDs, use 1kHz to 5kHz. No low-pass filter is needed because the eye acts as the integrator.
- DC Brushed Motor Speed Control: Motors are highly inductive loads. They resist changes in current, which naturally smooths the PWM square wave into a roughly steady current flow. Frequencies between 5kHz and 20kHz are standard. You must include a flyback diode to absorb inductive kickback when the PWM wave transitions from HIGH to LOW.
- Hobby Servo Positioning: Servos do not use PWM for power delivery; they use it for data. The frequency is strictly locked at 50Hz (a 20ms period). The absolute width of the HIGH pulse (typically between 1.0ms and 2.0ms) tells the internal potentiometer what angle to hold.
- Switching Regulators (Buck/Boost): Inside a DC-DC converter, the PWM wave switches at ultra-high frequencies (50kHz to 2MHz) to minimize the physical size of the inductors and capacitors required to smooth the output into clean DC.
Decision Tree: Selecting Your PWM Frequency and Driver Component
Choosing the right hardware to handle your PWM wave is where most hobbyist builds fail. A 5V Arduino Uno can drive a small LED directly, but an ESP32 cannot drive a 12V motor without a translator. Use this decision matrix to select your exact component.
| If Your Load Is... | Target Frequency | Driver Requirement | Concrete Part Pick (2026 Standard) |
|---|---|---|---|
| Standard LED (< 200mA) | 1 kHz - 5 kHz | Small signal N-channel MOSFET | 2N7000 (TO-92 package, 5V logic) |
| High-Power LED Strip (up to 3A) | 1 kHz - 5 kHz | Logic-level power MOSFET | IRLML2502 (SOT-23, fully enhanced at 2.5V $V_{GS}$) |
| DC Brushed Motor (Uni-directional) | 5 kHz - 20 kHz | Logic-level MOSFET + Flyback Diode | IRLZ44N + 1N5819 Schottky diode |
| DC Motor (Bi-directional / H-Bridge) | 5 kHz - 20 kHz | Dual H-Bridge IC with logic translation | TB6612FNG (Avoid the ancient L298N; it wastes 2V as heat) |
| Multiple Hobby Servos (>2) | 50 Hz (Strict) | I2C PWM Driver IC (saves GPIO pins) | PCA9685 (16-channel, hardware-timed pulses) |
Note on the TB6612FNG: As highlighted in Pololu's TB6612FNG documentation, this chip uses MOSFET-based H-bridges rather than the bipolar junction transistors found in the older L298N. This means it drops less than 0.5V across the bridge at 1A, compared to the L298N's massive 2V to 3V dropout, making it vastly superior for battery-powered PWM motor control.
Common PWM Pitfalls and Troubleshooting
Why does my motor emit a high-pitched whine when driven by PWM?
Your PWM frequency is set within the human audible range (typically 20Hz to 16kHz). The physical windings inside the motor are vibrating at the switching frequency like a speaker cone. The Fix: Increase your PWM frequency to at least 18kHz or 20kHz to push it above human hearing. If your microcontroller's timer cannot reach 20kHz at your desired resolution, drop the bit-resolution (e.g., from 10-bit to 8-bit) to allow a higher base clock frequency.
My MOSFET is getting burning hot, even though the math says it shouldn't.
You are likely using a standard-level MOSFET (like the IRF520 or IRFZ44N) with a 3.3V microcontroller like the ESP32. Standard MOSFETs require 10V on the gate to fully turn on and achieve their rated $R_{DS(on)}$. At 3.3V, the MOSFET is only partially opening, acting as a large resistor rather than a closed switch, and dissipating massive heat in its linear region. The Fix: Replace it with a true logic-level MOSFET (look for the 'I' prefix, like IRLZ44N, or check the datasheet for an $R_{DS(on)}$ specification explicitly tested at $V_{GS} = 2.5V$ or $3.3V$).
My ESP32 randomly resets or brownouts the moment the PWM motor starts.
This is caused by inductive kickback or sudden current sag on the power rail. When the PWM wave transitions from HIGH to LOW, the motor's collapsing magnetic field generates a massive reverse voltage spike that couples back into your microcontroller's ground plane. The Fix: You must place a flyback diode (1N4007 for slow switching, 1N5819 Schottky for fast PWM) in reverse parallel across the motor terminals. Additionally, ensure the motor power supply and the ESP32 power supply share a common ground reference, and place a 100µF decoupling capacitor directly across the motor's power input terminals.






