Source: https://mokxi.com/learn/pwm
Updated: 2026-09-27

Learn

# PWM: a pin that can only be on or off, faking an in-between

Written by the Mokxi team, updated September 27, 2026

Sign up free or see every lesson

- 192 parts on the bench
- 25 boards running now
- 1.00x real time, on every board

Click to open it in the editor

Real hardware PWM on timer 1, breathing an LED on pin 9 at 490 Hz.

A digital output pin has exactly two states. It cannot sit at 2.5 V to make an LED half as bright. Pulse-width modulation gets the same effect a different way: switch the pin on and off fast enough, and vary how much of each cycle it spends on, and anything downstream that cannot react as fast as the switching sees only the average, which behaves like a real in-between voltage.

The circuit above is the Arduino Uno's built-in `fade` program, running for real. `analogWrite()` on pin 9 puts timer 1 into 8-bit phase-correct PWM with a 64 prescaler, which works out to 16 MHz divided by 64 times 510, about 490 Hz. That number is not a guess; it is what the timer hardware actually produces at that prescaler and mode, and once it is set the timer holds the duty cycle on its own. The sketch only changes the compare register, thirty times a second, stepping through a 64-entry table shaped like one cycle of (1 - cosine) divided by 2, which is what makes the light look like it is breathing rather than ramping in a straight line: the eye reads brightness roughly logarithmically, so a linear ramp looks like it rushes the top end.

That is hardware PWM: once the timer is configured, the CPU is free to do something else between updates, and the waveform on the pin never glitches even if the sketch is briefly busy. Software PWM, the fallback on a pin with no timer behind it, has the CPU flip the pin itself on a schedule, which costs CPU time in proportion to the frequency and can jitter if something else needs the processor at the wrong moment.

What you see on the LED is not the instantaneous on-off switching either. Mokxi's LED probe is a short-lived average of its own brightness, with a time constant close to 8 milliseconds, which is in the same range as how long the eye's own response takes to a change. At 490 Hz, each PWM cycle is about 2 milliseconds, comfortably faster than that average can follow, so the LED reports its duty cycle to within a couple of percent instead of flickering once per cycle. That is not a rendering trick standing in for a blur; it is the same averaging a real retina does, computed the same way.

Open the circuit and watch the breathing settle into its rhythm. The comparison worth making next is on the ESP32-C3, which ships the same breath two ways: `fade` bit-bangs it in software and `pwmfade` hands it to LEDC, the chip's own PWM controller, on any pin rather than on six fixed ones. Both are on the board simulator pages.

Related

## Keep going

Picking a Resistor for an LED The 555 Astable: Timed by a Capacitor, Not a Crystal PWM to an Analog Voltage With an RC Filter

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building Open the editor
