Pulse Width Modulation (PWM) is a digital signaling technique that controls the average power delivered to a load by rapidly switching a fixed-frequency square wave between fully on and fully off states. In a physical circuit, PWM modulation changes the effective voltage and thermal energy delivered to a component without altering the actual peak voltage rails of your microcontroller or power supply. Makers frequently confuse PWM with true analog output (like a DAC), mistakenly believing the chip is outputting a variable voltage level, or they conflate the signal's switching frequency with its duty cycle percentage.

The Core Mechanics: Duty Cycle, Frequency, and Real-World Math

To use PWM effectively, you must separate the concept of time (frequency) from the concept of proportion (duty cycle). The frequency dictates how many complete on/off cycles occur per second, measured in Hertz (Hz). The duty cycle is the percentage of that single cycle where the signal remains HIGH (active).

Think of it like rapidly flipping a mechanical light switch. If you flip it on and off once per second (1 Hz), the room flashes. If you flip it 1,000 times per second (1 kHz), your eye's persistence of vision integrates the light, and it simply appears dimmer. The speed of your flipping is the frequency; the ratio of time the switch spends in the "on" position versus the "off" position is the duty cycle.

Critical Distinction: Average vs. RMS Voltage
When calculating the effect of PWM on a load, you must distinguish between average voltage (which dictates steady-state speed or brightness) and RMS voltage (which dictates heating and I²R power losses).

Worked Numeric Example: Driving a 12V DC Motor

Let’s drive a 12V brushed DC motor using an ESP32 and a DRV8871 motor driver. The ESP32 outputs a 3.3V logic PWM signal to the driver's IN pin, which in turn switches the 12V battery feed to the motor terminals.

  • Parameters: 12V supply, 5 kHz PWM frequency (200 µs period), 25% duty cycle.
  • On-time (t_on): 50 µs (the motor sees 12V).
  • Off-time (t_off): 150 µs (the motor sees 0V).

Average Voltage (V_avg): 12V × 0.25 = 3.0V. This is the voltage that determines the motor's target rotational speed.

RMS Voltage (V_rms): 12V × √0.25 = 6.0V. This is the voltage that determines the heating effect in the motor's copper windings. Because the RMS voltage (6V) is double the average voltage (3V), a motor running at 25% PWM duty cycle will run significantly hotter than a motor connected directly to a pure 3V DC battery. This thermal reality is why heavily loaded motors driven by low-duty-cycle PWM often require active cooling or derating.

Microcontroller PWM Hardware Specifications

Not all microcontrollers generate PWM signals equally. While the Arduino analogWrite() reference abstracts this into a simple 0-255 call, the underlying hardware timers vary wildly in resolution and base clock speeds. Below is a comparison of the native PWM peripherals across popular maker boards.

Microcontroller / Board PWM Resolution Default Base Freq Max Independent Channels Hardware Peripheral
Arduino Uno (ATmega328P) 8-bit (0-255) 490 Hz (980 Hz on pins 5,6) 6 Timer/Counters 0, 1, 2
ESP32-WROOM-32 Up to 20-bit 5 kHz (configurable to 40MHz) 16 (LEDC) LED Control (LEDC) / MCPWM
Raspberry Pi Pico (RP2040) Up to 16-bit 125 MHz base (divided) 16 (8 slices, 2 chans each) PWM Slices / PIO State Machines
STM32F103C8T6 (Blue Pill) Up to 16-bit 72 MHz base (divided) 15 Advanced/General Timers (TIM1-4)

Architectural Note for ESP32 Users: If you are writing code for the ESP32 in the Arduino IDE, be aware of the breaking changes introduced in ESP32 Arduino Core v3.x. The legacy channel-based API (ledcSetup() and ledcAttachPin()) has been deprecated. You must now use the pin-centric API: ledcAttach(pin, freq, resolution) followed by ledcWrite(pin, duty). For deep register-level control, refer to the official Espressif ESP-IDF LEDC API documentation.

Where You Meet PWM Modulation in Practice

The ideal frequency and resolution for PWM modulation depend entirely on the physical characteristics of the load you are driving. Using the wrong parameters will result in audible noise, visible flicker, or destroyed components.

1. LED Dimming and Display Backlights

Human vision integrates light over time, but digital camera sensors do not. For general LED dimming, a frequency of 1 kHz to 5 kHz with 8-bit or 10-bit resolution is ideal. If you drop the frequency below 100 Hz, the LED will visibly flicker when viewed through a smartphone camera due to the beat frequency between the PWM signal and the camera's rolling shutter. For high-end displays, frequencies are pushed above 20 kHz to eliminate any risk of eye strain or stroboscopic effects.

2. DC Motor Speed Control

When driving brushed DC motors via an H-bridge or MOSFET driver, the PWM frequency must be carefully selected to avoid acoustic resonance. Motor windings and the laminated steel core act as mechanical speakers. If you use a 1 kHz PWM signal, the motor will emit a loud, annoying whine. To achieve silent operation, push the PWM frequency above the human hearing range—typically 18 kHz to 22 kHz. Ensure your motor driver's logic gates and MOSFETs are rated for these higher switching speeds to prevent excessive switching losses.

3. Hobby Servos (SG90, MG996R)

Servos use a highly specific, non-standard variant of PWM. The frequency is strictly locked at 50 Hz (a 20 ms period). In this application, the microcontroller does not vary the duty cycle percentage; instead, it varies the absolute pulse width. A 1.0 ms HIGH pulse commands 0°, a 1.5 ms pulse commands 90°, and a 2.0 ms pulse commands 180°. Sending a standard 5 kHz variable-duty-cycle signal to a servo signal wire will result in erratic twitching or no movement at all.

4. Switch-Mode Power Supplies (Buck/Boost Converters)

In DC-DC converters, PWM modulation controls the gate of a power MOSFET to regulate output voltage. These applications demand extremely high frequencies (100 kHz to over 2 MHz) to allow for physically smaller inductors and capacitors. At these frequencies, PCB layout becomes critical; parasitic trace inductance can cause massive voltage spikes that destroy the switching MOSFET.

Debugging Common PWM Failures on the Bench

When a PWM-controlled circuit misbehaves, the issue is rarely the concept itself, but rather a mismatch between the signal parameters and the physical load. Here is a diagnostic framework for the most common bench failures.

Why does my DC motor whine loudly at low speeds?

Cause: Your PWM frequency is set within the human audible range (typically 500 Hz to 4 kHz), causing the motor coils to vibrate mechanically.
Fix: Increase the PWM frequency to at least 18 kHz. If using an Arduino Uno, you will need to manipulate the Timer 1 prescaler registers (TCCR1B) directly, as the default analogWrite() is locked to 490 Hz.

Why does my ESP32 brownout and reset when the motor starts?

Cause: PWM allows a motor to draw massive inrush current the moment the signal goes HIGH, causing a voltage sag on the shared power rail that drops the ESP32's 3.3V regulator below its brownout threshold.
Fix: Never power motors and microcontrollers from the same unregulated rail without isolation. Add a bulk electrolytic capacitor (e.g., 470µF to 1000µF) directly across the motor driver's VCC and GND terminals to supply transient current, and use separate voltage regulators for the logic and motor supplies.

Why is my LED flickering when I use a potentiometer to dim it?

Cause: You are reading the analog pin (ADC) and immediately writing to the PWM pin in the main loop without smoothing. ADC noise causes the duty cycle to jitter by 1-2% on every loop iteration, which is highly visible at low brightness levels.
Fix: Implement a software low-pass filter (exponential moving average) on the ADC reading before mapping it to the PWM duty cycle, or use a hardware RC low-pass filter on the potentiometer wiper.

Mastering PWM modulation requires looking past the software abstraction. By understanding the physical realities of RMS heating, acoustic resonance, and hardware timer limits, you can design embedded systems that are not only functional but thermally and acoustically optimized.