Pulse Width Modulation (PWM) is a digital switching technique that controls the average power delivered to a load by rapidly toggling a signal on and off at a fixed frequency while varying the duty cycle. In a real circuit or installation, PWM changes the average energy transfer without altering the source's peak voltage, allowing a binary digital pin to simulate a variable analog output. Beginners commonly confuse PWM electronics with true analog voltage (generated by a Digital-to-Analog Converter, or DAC) and with Variable Frequency Drives (VFDs), where the frequency itself shifts to control AC motor speed.
The Core Mechanics of Pulse Width Modulation
To understand PWM, imagine a garden hose with a rapid shut-off valve. If you snap the valve fully open for one second, then fully closed for one second, repeatedly, the average water flow is 50% of maximum, even though the water pressure (voltage) when open never changes. The duty cycle is simply the percentage of time the signal is HIGH (on) during one complete period.
The mathematical relationship is straightforward: V_avg = V_peak × Duty Cycle. If you output a 5V square wave at a 20% duty cycle, a multimeter set to DC will read approximately 1.0V. However, an oscilloscope will still show the signal slamming between 0V and 5V. This distinction is critical when selecting components, as insulation and semiconductor breakdown voltages must be rated for the peak voltage, not the average.
Microcontroller PWM Hardware Specifications
Not all microcontrollers generate PWM signals equally. Hardware timers dictate the resolution (how fine your duty cycle steps are) and the maximum frequency. Below is a comparison of the hardware PWM capabilities across four popular development boards used in modern embedded projects.
| Microcontroller Board | Core / Architecture | Logic Level | Default Freq. | Max Frequency | Resolution | Hardware Channels |
|---|---|---|---|---|---|---|
| Arduino Uno R3 | ATmega328P (AVR) | 5.0V | 490 Hz / 980 Hz | ~31.25 kHz | 8-bit (256 steps) | 6 (Timer0, 1, 2) |
| ESP32 DevKit V1 | Xtensa LX6 (Dual-core) | 3.3V | 5.0 kHz | 40 MHz (theoretical) | Up to 20-bit | 16 (LEDC peripheral) |
| Raspberry Pi Pico | RP2040 (Dual M0+) | 3.3V | 125 MHz base | ~100+ MHz (divided) | 16-bit (65536 steps) | 16 (8 slices, 2 ch each) |
| Teensy 4.1 | ARM Cortex-M7 (i.MX RT1062) | 3.3V | 488 Hz | ~150+ MHz | 16-bit | 32+ (FlexPWM & QuadTimer) |
When programming the ESP32, you do not use the standard Arduino analogWrite() function for optimal control. Instead, you use the Espressif LEDC (LED Control) API, which allows you to configure hardware fade interrupts and precise frequency targeting. Conversely, the Arduino analogWrite() reference abstracts the ATmega328P timers, which is convenient but locks you into 490 Hz or 980 Hz unless you manipulate the TCCR registers directly.
Worked Example: Switching a 48W Resistive Load
Let's calculate the real-world behavior of driving a 12V, 4A (48W) resistive cartridge heater using an Arduino Uno (5V logic) and an IRLZ44N logic-level MOSFET.
- Target Duty Cycle: We want to deliver exactly 30% power to maintain a specific thermal setpoint.
- Average Voltage & Power:
V_avg = 12V × 0.30 = 3.6V.P_avg = 48W × 0.30 = 14.4W. - Frequency Selection: The Arduino defaults to 490 Hz on Pin 3. Should we change it to 25 kHz to eliminate any potential acoustic noise?
P_sw = 0.5 × V × I × (t_rise + t_fall) × Frequency. At 490 Hz, switching losses in the IRLZ44N are negligible. If you push the frequency to 25 kHz without adding a dedicated gate driver IC (like a TC4420) to speed up the gate charge time, the MOSFET will overheat and fail due to excessive switching losses.
By sticking to the default 490 Hz, the IRLZ44N spends almost all its time fully enhanced (R_DS(on) ≈ 0.022Ω at 5V Vgs). Conduction loss is I² × R = (4A)² × 0.022Ω = 0.352W, which the TO-220 package can dissipate into ambient air without a heatsink. This is a prime example of why understanding PWM electronics theory prevents hardware failures that pure code-level tutorials miss.
Where You Meet PWM Electronics in Practice
You will encounter PWM in almost every power-control scenario in embedded systems. Here is how the parameters shift based on the application:
- LED Dimming: Requires frequencies above 1 kHz to prevent visible flicker on camera sensors, and often uses 10-bit to 12-bit resolution for smooth low-end dimming curves. The RP2040 datasheet details how its 16-bit PWM slices can achieve massive resolution at standard LED frequencies.
- DC Motor Speed Control: Typically set to 20 kHz to push the switching frequency above the threshold of human hearing, eliminating the high-pitched whine that occurs at 1 kHz.
- Switching Power Supplies (Buck/Boost): Uses ultra-high frequencies (100 kHz to 2 MHz) to minimize the physical size of the inductors and capacitors required to smooth the output.
- Servo Motors: A special, low-frequency edge case. Standard RC servos expect a 50 Hz signal (20 ms period) where the width of the pulse (1 ms to 2 ms) dictates the absolute shaft angle, not the average power.
Frequently Asked Questions
Q: Why does my DC motor whine loudly at low PWM duty cycles?
A: The whine is magnetostriction and coil vibration caused by the PWM frequency falling within the 20 Hz to 20 kHz human hearing range. Increase your microcontroller's timer frequency to at least 21 kHz to make the switching ultrasonic and silent.
Q: Can I connect a PWM pin directly to a high-power LED?
A: No. Microcontroller GPIO pins are typically limited to 20mA–40mA. You must use the PWM signal to drive the gate of a MOSFET or the base of a BJT, which then switches the high current from a separate power supply to the LED.
Q: Why does my multimeter read 0V when measuring a PWM pin?
A: Standard multimeters sample voltage slowly. If they don't have a dedicated 'duty cycle' or 'low-pass filter' mode, they will fail to average the rapid 0V/5V transitions correctly. Use an oscilloscope to verify PWM signals.






