PWM stands for Pulse Width Modulation, a technique that simulates analog voltage levels by rapidly switching a digital signal on and off at varying duty cycles. In a real circuit or installation, it changes how a strictly digital microcontroller pin—which can physically only output 0V or its logic high (like 3.3V or 5V)—interacts with a load, allowing it to control the average power delivery to dim LEDs, spin motors, or position servos without wasting energy as heat. People commonly confuse PWM with a true Digital-to-Analog Converter (DAC); while a DAC outputs a smooth, continuous voltage, PWM outputs a harsh square wave that only averages out to a target voltage over time. The core mathematical relationship governing this behavior is: Average Voltage = Supply Voltage × Duty Cycle.
The Core Mechanics: Duty Cycle and Frequency
To use PWM effectively, you must configure two distinct parameters: the duty cycle and the frequency. The duty cycle is the percentage of time the signal remains HIGH (on) during a single complete cycle. A 50% duty cycle means the pin is HIGH for exactly half the time and LOW for the other half. The frequency dictates how many of these complete cycles occur per second, measured in Hertz (Hz).
Think of a heavy mechanical flywheel connected to a motor. If you push the motor for one full second, then let go for one full second, the flywheel's physical inertia keeps it spinning smoothly between your pushes. The flywheel only 'feels' the average effort. If you instead push for 0.01 seconds and rest for 0.01 seconds (a much higher frequency), the flywheel spins even smoother because the gaps between pushes are too short for it to decelerate noticeably. This is exactly how electrical loads with inductance (like motors) or capacitance (like LEDs with internal parasitic capacitance) respond to high-frequency PWM.
| Duty Cycle (%) | 8-Bit Value (0-255) | 10-Bit Value (0-1023) | Average Output Voltage |
|---|---|---|---|
| 0% | 0 | 0 | 0.00V |
| 25% | 64 | 256 | 1.25V |
| 50% | 128 | 512 | 2.50V |
| 75% | 191 | 768 | 3.75V |
| 100% | 255 | 1023 | 5.00V |
Worked Numeric Example: Dimming a 12V Fan with an ESP32
Let's look at a real-world scenario. You want to run a standard 12V PC cooling fan at roughly 60% speed. Your microcontroller is an ESP32 DevKit V1, which operates at 3.3V logic. Because the ESP32 cannot output 12V directly, we use a logic-level N-channel MOSFET (like the IRLZ44N) as a switch. The ESP32's 3.3V PWM signal drives the MOSFET gate, which in turn switches the 12V supply to the fan.
First, we calculate the duty cycle value. PC fans typically expect a 25 kHz PWM signal on their blue control wire to avoid audible whine. We will use an 8-bit resolution (values from 0 to 255). To achieve a 60% duty cycle:
- Target Duty Cycle = 60% (0.60)
- Resolution = 8-bit (Max value 255)
- PWM Value = 0.60 × 255 = 153
In modern ESP32 Arduino Core (v3.x), the legacy ledcSetup functions are deprecated in favor of the simplified ledcAttach API. Here is the exact, compilable code to achieve this:
// ESP32 PWM Fan Control (Arduino Core v3.x syntax)
const int fanPin = 18; // GPIO 18 connected to MOSFET gate
const int pwmFreq = 25000; // 25 kHz to avoid audible motor whine
const int pwmResolution = 8; // 8-bit resolution (0-255)
void setup() {
// Configure the LEDC peripheral for hardware PWM
// ledcAttach automatically routes the PWM signal to the specified GPIO
ledcAttach(fanPin, pwmFreq, pwmResolution);
// Set initial speed to 60% (0.60 * 255 = 153)
ledcWrite(fanPin, 153);
}
void loop() {
// Main loop remains free for other tasks; hardware PWM runs in background
}Where You Meet PWM in Practice
You will encounter PWM across almost every embedded systems project, but the required frequency and duty cycle parameters change drastically depending on the load:
- Servo Motors (RC Servos): Require a very specific, low frequency of exactly 50 Hz. Instead of a percentage, the 'duty cycle' is measured in absolute pulse width: a 1.0 ms pulse moves the servo to 0°, and a 2.0 ms pulse moves it to 180°.
- DC Motor Speed Control: When driving motors via H-bridges (like the L298N or DRV8833), frequencies between 1 kHz and 5 kHz are standard. Going too low causes the motor to stutter; going too high increases switching losses in the MOSFETs.
- LED Dimming: Frequencies of 1 kHz to 5 kHz are ideal. If you use a frequency below 100 Hz, human eyes will perceive a flicker, and smartphone cameras will capture visible banding on video.
- Switching Power Supplies (Buck/Boost Converters): These use internal PWM often exceeding 100 kHz to 1 MHz. The high frequency allows the use of physically smaller inductors and capacitors.
Frequently Asked Questions
What does PWM stand for in Arduino and ESP32 environments?
In the Arduino ecosystem, PWM is the underlying technology behind the analogWrite() function. Despite the name 'analog', standard Arduino boards (like the Uno or Nano) do not have true analog output pins; they are outputting a 490 Hz (or 980 Hz on pins 5 and 6) PWM square wave. On the ESP32, PWM is handled by dedicated hardware peripherals called LEDC (LED Control) for general use, and MCPWM (Motor Control PWM) for advanced motor driving with dead-time control and fault handling.
What is the difference between PWM and a true analog DAC?
A Digital-to-Analog Converter (DAC) uses an internal resistor ladder or capacitor array to output a physically smooth, continuous voltage. If you set a DAC to 1.65V, an oscilloscope will show a flat, straight horizontal line at 1.65V. PWM, conversely, outputs a harsh digital square wave bouncing between 0V and 3.3V. To convert a PWM signal into a true analog voltage, you must pass it through a low-pass RC filter (typically a 1kΩ resistor in series followed by a 1µF capacitor to ground) to smooth out the high-frequency switching edges.
How do I choose the right PWM frequency for my project?
The rule of thumb is to push the frequency high enough that the load's physical or electrical inertia smooths out the pulses, but low enough to avoid excessive heat generation in your switching transistors. For audio applications (like generating sine waves), keep it above 20 kHz so humans cannot hear the switching carrier. For standard DC motors, 1 kHz to 5 kHz is the sweet spot. For 4-wire PC fans, check the datasheet, but 25 kHz is the Intel 4-wire fan specification standard.
Why does my PWM-controlled motor make a high-pitched whining noise?
This is caused by magnetostriction and coil whine. The rapid magnetic field changes in the motor's copper windings cause the physical wire and the stator laminations to vibrate at the exact frequency of your PWM signal. If your PWM frequency is set to 4 kHz, the motor will literally act as a speaker emitting a 4 kHz tone. The standard fix is to increase the PWM frequency above 20 kHz (the upper limit of human hearing), which is why modern ESCs (Electronic Speed Controllers) for drones often default to 24 kHz or 32 kHz 'DShot' protocols.






