Pulse Width Modulation (PWM) is a technique that simulates a variable analog voltage by rapidly switching a digital signal on and off at a fixed frequency while varying the ratio of on-time to off-time. Instead of dropping excess voltage across a linear resistor and wasting it as heat, modulation PWM controls the average power delivered to a load by chopping the full supply voltage into precise, high-speed time slices.

The Core Mechanics: Duty Cycle vs. Frequency

To use modulation PWM effectively, you must separate two distinct variables: duty cycle and frequency. The duty cycle is the percentage of time the signal spends in the HIGH (on) state during a single period. A 25% duty cycle means the pin is HIGH for one-quarter of the time and LOW for three-quarters. The frequency dictates how many of these on/off periods occur per second, measured in Hertz (Hz).

What it changes in a real circuit: Modulation PWM changes the average power delivered to the load without altering the peak voltage. If you drive a 12V DC motor with a 50% duty cycle PWM signal, the motor terminals still see harsh 12V peaks, but the mechanical inertia of the motor averages this out, causing it to behave as if it is receiving 6V continuous.

Think of it like filling a bucket with a hose. If you turn the hose on full blast for 1 second, then off for 1 second, the bucket fills at the exact same average rate as if you pinched the hose to let a steady, half-strength trickle flow. The full-blast method is PWM; the pinched hose is a linear voltage regulator.

Microcontroller PWM Resolution and Frequency Limits

Not all microcontrollers handle modulation PWM the same way. The hardware timers dictate your maximum frequency and resolution (the number of discrete steps between 0% and 100% duty cycle). Higher resolution requires lower maximum frequencies because the timer has to count more steps per cycle. Below is a reference chart for common maker boards running at their default clock speeds.

Microcontroller Hardware Peripheral Max Frequency (Approx) Resolution (Bits) Default analogWrite Freq
Arduino Uno (ATmega328P) Timer 1 / Timer 2 ~62.5 kHz (at 8-bit) 8-bit (0-255) ~490 Hz (980 Hz on pins 5/6)
ESP32-WROOM-32 LEDC Peripheral 40 MHz (at 1-bit res) 1 to 16-bit configurable 5000 Hz (Arduino core default)
Raspberry Pi Pico (RP2040) Hardware PWM Slices ~125 MHz (system clock) 16-bit (0-65535) Variable, typically 1 kHz - 10 kHz
STM32F103C8T6 (Blue Pill) Advanced Timers (TIM1-4) ~72 MHz / 36 MHz 16-bit (0-65535) 1 kHz (HAL default)

When configuring an ESP32 via the Espressif LEDC API, you must explicitly define both the frequency and the bit resolution. If you request a 20 kHz frequency, the hardware timer mathematically cannot support 16-bit resolution at that speed; it will max out around 10 or 11 bits before overflowing.

Worked Example: Sizing a PWM Signal for a 12V DC Motor

Let's look at a real-world scenario. You are driving a 12V brushed DC motor (2A stall current) using an IRLZ44N logic-level MOSFET controlled by an ESP32 (3.3V logic). You want the motor to run at roughly 60% of its maximum speed, and you want to eliminate the high-pitched whine that PWM often causes in motors.

Step 1: Determine the Target Average Voltage
Target Voltage = Supply Voltage × Desired Speed
Target Voltage = 12V × 0.60 = 7.2V average.

Step 2: Set the Duty Cycle
Since the peak voltage remains 12V, a 60% duty cycle will yield the required 7.2V average.

Step 3: Calculate the Microcontroller Register Value
Assume we configure the ESP32 LEDC peripheral for 10-bit resolution (values from 0 to 1023).
Duty Value = Max Resolution × Duty Cycle
Duty Value = 1023 × 0.60 = 613.8.
We round to the nearest integer: 614.

Step 4: Select the Frequency
Human hearing ranges from 20 Hz to 20 kHz. If you run the PWM at 1 kHz, the motor's stator will physically vibrate at that frequency, creating an annoying whine. To push the switching noise above human hearing, we set the frequency to 25 kHz (25,000 Hz).

Safety Note: Inductive Kickback
When driving motors or relays with modulation PWM, the magnetic field collapses during the "off" cycle, generating a massive reverse voltage spike. Always place a flyback diode (like a 1N4007 or a faster 1N5819 Schottky) in reverse parallel across the motor terminals. Without it, this spike will arc across your MOSFET or instantly fry your microcontroller's GPIO pin.

Where You Meet Modulation PWM in Practice

Modulation PWM is ubiquitous in embedded systems, but the required frequency and resolution change drastically depending on the load.

  • LED Dimming: Requires frequencies above 1 kHz to prevent visible flicker. If you use a standard 490 Hz Arduino PWM signal for high-end lighting, video cameras will capture a strobing effect due to shutter sync. For architectural lighting, 10 kHz to 20 kHz is standard.
  • RC Servo Motors: This is a unique edge case. Standard analog servos expect a very specific 50 Hz frequency (a 20 ms period). Here, the absolute pulse width (typically 1 ms to 2 ms) dictates the shaft angle, not the percentage duty cycle. A 1.5 ms pulse centers the servo, regardless of the total period.
  • Switching Power Supplies (Buck/Boost): DC-DC converters use PWM to switch a MOSFET driving an inductor. These operate at extremely high frequencies (100 kHz to 2 MHz) so that the required inductors and capacitors can remain physically small and cheap.
Common Confusion: PWM vs. True Analog (DAC)
Many beginners assume a PWM pin outputs a smooth, variable DC voltage. It does not. It outputs a harsh 0V-to-Vcc digital square wave. If you measure a 50% duty cycle 5V PWM pin with a standard multimeter, it will average out and display ~2.5V. But if you connect it to a fast-responding load without a low-pass RC filter, the load sees the full 5V slamming on and off. True Digital-to-Analog (DAC) output, like the DAC pins on an ESP32 or an MCP4725 module, actually generates a continuous, smooth voltage level.

Frequently Asked Questions

Why does my LED flicker when I dim it with PWM?
If your LED flickers to the naked eye, your PWM frequency is likely below 60 Hz. If it only flickers when viewed through a smartphone camera, the frequency is clashing with the camera's rolling shutter. Increase your timer frequency to at least 2 kHz to solve both issues.

Can I just use a potentiometer instead of PWM to control a motor?
You can, but it is highly inefficient. A potentiometer or linear regulator drops excess voltage by converting it directly into heat. If you run a 12V motor at 6V drawing 1A through a linear resistor, you waste 6 Watts of power as heat. Modulation PWM switches the power fully on or fully off, resulting in >90% efficiency with minimal heat generation.

Do I need a low-pass filter for my PWM output?
It depends on the load. Motors and incandescent bulbs have natural physical inertia or thermal mass that acts as a low-pass filter, smoothing the pulses automatically. If you are feeding a PWM signal into an audio amplifier or a sensitive analog sensor input, you must build a hardware RC (resistor-capacitor) low-pass filter to smooth the square wave into a true DC voltage before it reaches the load.