Pulse Width Modulation (PWM) is a technique that simulates an analog voltage by rapidly switching a digital signal on and off and varying the ratio of on-time to the total cycle time. In a real circuit, PWM changes the average power delivered to a load without altering the actual peak supply voltage, allowing 3.3V or 5V digital microcontroller pins to dim lights, control motor speeds, and position actuators. People most commonly confuse PWM with a voltage divider or linear regulator, mistakenly believing it physically drops the voltage level rather than chopping the time the voltage is applied.

The Core Mechanism: Duty Cycle vs. Frequency

To understand how PWM works, you must separate its two independent variables: duty cycle and frequency. They control entirely different aspects of the signal.

  • Duty Cycle: The percentage of one complete cycle that the signal remains HIGH (on). A 25% duty cycle means the pin is HIGH for one-quarter of the time and LOW for three-quarters.
  • Frequency: How many complete on/off cycles occur per second, measured in Hertz (Hz). This dictates how fast the switching happens.
Standard Microcontroller Defaults:
Arduino Uno (ATmega328P): Default PWM frequency is ~490 Hz on most pins, and ~980 Hz on pins 5 and 6.
ESP32 (LEDC Peripheral): No single default; you configure the frequency in software, typically setting it between 1 kHz and 5 kHz for general prototyping.

What PWM Actually Changes (And What It Doesn't)

When you output a 50% duty cycle PWM signal from a 5V Arduino pin to an LED, the pin is not outputting 2.5V. It is outputting exactly 5V for half the time, and 0V for the other half. The average voltage over time is 2.5V, which is why the LED appears half as bright.

Think of a light switch in a room. Flipping it on and off rapidly doesn't change the brightness of the bulb when it's on; it just changes how long the room is illuminated. If you flip it fast enough, your eye's persistence of vision averages the light, making it look dimmer. This is exactly how PWM works on human perception and slow-reacting mechanical loads like DC motors.

This distinction is critical for component selection. If you are driving a 12V Peltier cooler with a 50% duty cycle, the Peltier still experiences the full 12V potential during the ON state. You must ensure the semiconductor junction can handle the 12V peak, not just the 6V average.

Worked Numeric Example: Driving a 4-Pin 12V PC Fan

Let's look at a real-world scenario: controlling a Noctua NF-A12x25 PWM cooling fan. According to the Intel 4-Wire PWM specification, these fans require a 25 kHz PWM signal on the control wire to operate silently. If the frequency is too low, the internal motor driver whines audibly.

  1. Calculate the Period: Frequency is 25,000 Hz. The total time for one cycle (Period) is $1 / 25,000 = 0.00004$ seconds, or 40 µs.
  2. Set the Target Speed: We want the fan to run at 30% speed. Therefore, the duty cycle is 30%.
  3. Calculate ON/OFF Times:
    • $T_{on} = 40 \text{ µs} \times 0.30 = \textbf{12 µs}$
    • $T_{off} = 40 \text{ µs} - 12 \text{ µs} = \textbf{28 µs}$

If you try to use the standard Arduino analogWrite() function, it will output ~490 Hz (a 2.04 ms period). The fan will run, but it will emit a loud, annoying buzzing sound because the 490 Hz frequency falls squarely in the middle of the human audible range. To fix this, you must bypass the standard function and manually reconfigure the ATmega328P's Timer1 registers (TCCR1A and TCCR1B) to achieve the 25 kHz hardware requirement.

Where You Meet PWM in Practice

PWM is the bridge between digital logic and analog physical control. Here is where you will encounter it on the bench:

  • LED Dimming: Used to control brightness without shifting the LED's color temperature (which happens if you use analog voltage reduction). Frequencies above 100 Hz are required to beat the human flicker fusion threshold.
  • DC Motor Speed Control: Fed into the enable pins of H-bridges like the TB6612FNG or L298N. The motor's inductance naturally smooths the chopped voltage into a steady current.
  • Servo Positioning: Standard RC servos (like the SG90) use a fixed 50 Hz frequency. The duty cycle is strictly mapped to a 1 ms to 2 ms HIGH pulse to dictate the shaft angle.
  • Switch-Mode Power Supplies (Buck/Boost): Microcontrollers or dedicated ICs use high-frequency PWM (100 kHz to 2 MHz) to switch MOSFETs, transferring energy through inductors to step voltages up or down efficiently.

Decision Tree: Picking the Right Frequency and Hardware

Choosing the wrong frequency or microcontroller peripheral leads to noisy motors, flickering cameras, or bricked timers. Use this decision path to select your setup.

Application Target Frequency Resolution Concrete Hardware Pick
Visual LED Dimming 1 kHz - 5 kHz 8-bit (256 steps) Arduino: Default analogWrite
ESP32: LEDC Channel 0-7
DC Motor Speed (H-Bridge) 1 kHz - 20 kHz 8-bit to 10-bit ESP32: LEDC at 10-bit resolution
Arduino: Timer1 modified
4-Pin PC Fans 25 kHz (Strict) N/A (Open-drain) ATmega328P: Timer1 Fast PWM mode
RC Servos 50 Hz (Strict) Pulse width (1-2ms) Any MCU: Hardware Servo Library
Default Recommendation: If you are prototyping a generic DC motor or LED project on an ESP32 and don't have strict datasheet requirements, configure the ESP32 LEDC peripheral to 5,000 Hz at 8-bit resolution. This avoids audible motor whine, prevents LED camera flicker, and leaves plenty of processing headroom.

Common Confusions and Hardware Mistakes

Understanding the theory is only half the battle; the physics of the load will punish you if you ignore the hardware realities of PWM.

Mistake 1: Driving Inductive Loads Without a Flyback Diode

When a PWM signal switches OFF, a DC motor's collapsing magnetic field generates a massive reverse voltage spike (inductive kickback). If you are switching a motor directly with a MOSFET, this spike will punch through the MOSFET's drain-source junction and destroy it. Always place a flyback diode (like a 1N4007 or a fast-recovery Schottky like the 1N5819) in reverse parallel across the motor terminals.

Mistake 2: Exceeding GPIO Current Limits

A standard Arduino Nano or ESP32 GPIO pin can only safely source about 20mA to 40mA. You cannot use analogWrite to directly drive a 12V, 2A LED strip. You must use the PWM signal to switch the gate of a logic-level MOSFET (like the IRLZ44N), which handles the heavy current from a separate 12V power supply.

Mistake 3: Confusing ESP32 Channels with GPIO Pins

Unlike the Arduino Uno, where PWM is hardwired to specific pins (marked with a ~), the ESP32 uses a matrix router. You generate a PWM signal on a virtual 'LEDC Channel' and then attach that channel to almost any available GPIO pin in software. If you try to use Arduino-style analogWrite(pin, value) on older ESP32 Arduino cores without setting up the LEDC parameters first, the function will fail silently or throw a compilation error.