What is PWM
PWM (Pulse Width Modulation) is a way to control power delivery by rapidly turning a signal on and off. Instead of reducing voltage, you change the duty cycle — the percentage of time the signal is HIGH.
Why PWM
- LED dimming — PWM controls brightness without changing voltage
- Motor speed — PWM controls RPM without losing torque
- Servo position — PWM pulse width sets the servo angle
- Audio generation — PWM creates tones and melodies
How It Works
Duty Cycle = T(on) / T(total) × 100%
0% duty: ──────────────────────────── (always OFF)
25% duty: ████──────────────────────── (1/4 time ON)
50% duty: ████████──────────────────── (half time ON)
75% duty: ████████████──────────────── (3/4 time ON)
100% duty: ████████████████████████████ (always ON)
The frequency (how many cycles per second) stays constant. Only the ON/OFF ratio changes.
Arduino Example: LED Fade
int led = 9; // PWM-capable pin (~ on Uno)
void setup() { pinMode(led, OUTPUT); }
void loop() {
for (int brightness = 0; brightness < 255; brightness++) {
analogWrite(led, brightness); // 0-255 = 0-100% duty
delay(10);
}
for (int brightness = 255; brightness >= 0; brightness--) {
analogWrite(led, brightness);
delay(10);
}
}
Common Pitfalls
| Issue | Cause | Fix |
|---|---|---|
| LED flickers at low duty | Frequency too low | Default ~490 Hz is fine for LEDs; for motors use higher |
| Motor buzzes | PWM frequency in audible range | Use >20 kHz (above hearing) |
| Pin does not work | Not a PWM-capable pin | Check board pinout for ~ or PWM mark |
| Servo jitters | PWM frequency wrong for servo | Servos need exactly 50 Hz (20ms period) |
PWM Pins by Board
| Board | PWM Pins | Resolution | Frequency |
|---|---|---|---|
| Arduino Uno | 3,5,6,9,10,11 (~) | 8-bit (0-255) | ~490/980 Hz |
| ESP32 | All GPIOs | 16-bit (0-65535) | Adjustable |
| Raspberry Pi | GPIO12,13,18,19 | Hardware PWM | Adjustable |
| STM32 | Most timers | 16-bit | Up to MHz |
Related
- Arduino Getting Started
- [What is GPIO](coming soon)