Pulse Width Modulation (PWM) is a technique that simulates an analog voltage by rapidly switching a digital pin on and off, controlling the average power delivered to a load by varying the ratio of on-time to the total cycle time. In a real circuit, PWM changes the average voltage and current delivered to a load while keeping the switching element (like a MOSFET or microcontroller GPIO) either fully on or fully off. This eliminates the massive I²R heat losses you would incur if you tried to drop the voltage using a linear resistor or a transistor operating in its linear region.
Think of a garden hose with a quick-shut-off nozzle. Instead of partially blocking the opening with your thumb—which wastes pressure, restricts flow, and creates a messy spray—you snap the nozzle fully open and fully shut several times a second. The pipe stays wide open when flowing, but the average water volume hitting the bucket is precisely controlled by how long you hold it open versus shut.
The Core Mechanism: Duty Cycle and Frequency
Two parameters define any PWM signal: duty cycle and frequency. The duty cycle is the percentage of one period that the signal remains HIGH. A 20% duty cycle on a 5V logic pin yields an average voltage of 1V. Frequency is how many of these on/off cycles occur per second, measured in Hertz (Hz).
Worked Numeric Example: Sizing ESP32 LEDC Timers
When you move beyond basic Arduino boards to the ESP32, you stop using software-timed analogWrite() and start using the hardware LED Control (LEDC) peripheral. The ESP32's LEDC timer is driven by an 80 MHz APB clock. You must mathematically balance your desired frequency against your desired bit resolution.
The formula governing this relationship is:
Max Frequency = Clock Speed / (2 ^ Resolution)
Let us say you are building a high-end LED dimmer and want 12-bit resolution (4,096 discrete brightness steps) for ultra-smooth fading at the low end.
- Clock Speed: 80,000,000 Hz
- Resolution Steps: 4,096
- Max Frequency = 80,000,000 / 4,096 = 19,531 Hz
If your project requires pushing the PWM frequency to 25 kHz to push motor whine completely out of the human hearing range, you can no longer afford 12-bit resolution. At 25 kHz, your maximum step count is 80,000,000 / 25,000 = 3,200 steps. The closest binary bit-depth is 11-bit (2,048 steps). For the definitive register-level math, refer to the Espressif LEDC API documentation.
Where You Meet PWM in Practice (And What People Confuse It With)
You will encounter PWM in almost every embedded subsystem that requires variable power or positioning:
- DC Motor Speed Control: Fed into the enable pin of an H-bridge or the IN pin of a half-bridge driver like the TI DRV8871.
- LED Dimming: Used to drive the gate of a logic-level MOSFET switching high-current LED strips.
- Servo Positioning: Standard RC servos (like the SG90) ignore duty cycle in the traditional sense and instead measure the absolute width of the HIGH pulse (typically 1ms to 2ms) at a fixed 50 Hz frequency.
- Switching Power Supplies: Buck and boost converters use PWM to toggle an inductor's charge/discharge cycles to regulate output voltage.
The Great Confusion: PWM vs. True DAC
The most common mistake hobbyists make is assuming PWM is a true analog signal. It is not. It is a square wave. If you feed a 1 kHz PWM signal directly into an audio amplifier, you will not hear a smooth sine wave; you will hear a harsh, buzzing square wave rich in odd harmonics. To convert PWM into a true analog DC voltage or audio waveform, you must pass it through a low-pass RC filter or an active op-amp filter to average out the square edges into a smooth curve. For a deeper look at the waveform math, All About Circuits provides an excellent breakdown of the harmonic content in square waves.
Decision Tree: Picking Your Frequency and Resolution
Do not guess your PWM settings. Use this decision matrix to select the exact parameters and hardware for your specific load.
| Application / Load | Target Frequency | Resolution | Concrete Pick / Peripheral |
|---|---|---|---|
| RC Servos (SG90, MG996R) | 50 Hz (Fixed) | 10-bit (1024 steps) | ESP32 LEDC or PCA9685 (I2C 16-channel) |
| DC Motors (via DRV8871 / L298N) | 20 kHz - 25 kHz (Ultrasonic) | 8-bit (256 steps) | Hardware Timer (AVR Timer1 or ESP32 LEDC High-Speed) |
| LED Strip Dimming (12V/24V) | 1 kHz - 5 kHz | 12-bit (4096 steps) | ESP32 LEDC or TLC5940 (SPI constant-current sink) |
| Audio / Analog Voltage Generation | > 44.1 kHz (or avoid PWM) | 8 to 10-bit | Skip PWM; use an I2S DAC like the MAX98357A |
Hardware vs Software PWM and Gate Drive Realities
On an 8-bit Arduino Uno, the analogWrite() function uses software-configured hardware timers that default to roughly 490 Hz on most pins, and 980 Hz on pins 5 and 6. This is fine for a basic LED, but if you use it to drive a DC motor, the 490 Hz frequency will cause the motor windings to vibrate audibly. Furthermore, software PWM (bit-banging a pin in a loop) is catastrophic for timing-sensitive tasks like servos, as any interrupt (like WiFi or Serial reads) will jitter the pulse width and cause the servo to twitch violently.
Always use hardware PWM peripherals. On the ESP32, this is the LEDC subsystem. On the Raspberry Pi Pico (RP2040), it is the dedicated PWM slice mapped to every GPIO. If your microcontroller runs out of hardware PWM pins, do not resort to software bit-banging. Instead, offload the task to a dedicated PWM IC like the Adafruit PCA9685, which generates 16 channels of 12-bit hardware PWM over a simple I2C bus.
The Gate Charge Trap at High Frequencies
When you push PWM frequencies above 10 kHz to switch high-current loads (like a 10A heater or a large motor) via a discrete MOSFET, you run into gate charge limitations. A microcontroller GPIO can typically source only 20mA to 40mA. A large MOSFET like the IRFZ44N has a high gate capacitance. At 20 kHz, the GPIO cannot charge and discharge the gate fast enough. The MOSFET spends too much time lingering in its linear (partially on) region, generating massive heat and eventually failing.
The Fix: If you are switching >5A at >5 kHz, place a dedicated gate driver IC (like the Microchip TC4427) between your microcontroller and the MOSFET, or use a pre-packaged motor driver IC that includes internal gate drivers and shoot-through protection.
The Default Recommendation
If you are starting a general-purpose embedded project and need a baseline PWM configuration before tuning for specific edge cases, configure your hardware timer for 5 kHz frequency and 10-bit resolution. This specific combination sits safely above the audible range for most small cooling fans, prevents visible flicker in standard LEDs, provides 1,024 steps for smooth fading, and keeps switching losses low enough that you can drive logic-level MOSFETs directly from a 3.3V GPIO without a dedicated gate driver.






