About this calculator
A microcontroller pin can only be fully on or fully off, but switching between the two quickly enough and filtering the result gives you any voltage in between. That is PWM used as a digital-to-analogue converter — motor speed control, LED dimming, analogue setpoints, all from a single pin.
This calculator converts between duty cycle and average voltage in both directions, shows the register value for your timer resolution, and works out how much ripple survives your output filter.
How it works
The average of a square wave is just the high level weighted by the fraction of time it spends there: Vavg = Vlow + duty × (Vhigh − Vlow). At 50% duty on a 5 V pin you get 2.5 V.
Resolution comes from the timer. An 8-bit PWM has 256 steps, so each one is 1/255 of the full swing — about 19.6 mV on a 5 V rail. That step size is the smallest change you can command, and there is no point filtering to a precision finer than it.
Getting a steady DC out means filtering the switching frequency away, usually with an RC low-pass. The ripple that survives is approximately V_span × D × (1−D) / (f × R × C), which is worst at 50% duty and vanishes at the extremes.
The design tension is straightforward: a lower filter cutoff means less ripple but slower settling. A useful target is a cutoff at least 100× below the PWM frequency, with ripple under one LSB — beyond that the extra resolution is not real.
For driving motors and LEDs you often want no filter at all. The inertia of the motor or the response of your eye does the averaging, and switching the load hard keeps the driver efficient.
Worked example
Generating a steady 3.3 V analogue reference from a 5 V Arduino using its default 490 Hz PWM.
- duty = 3.3 / 5 = 0.66 → analogWrite value = round(0.66 × 255) = 168
- Actual output: 168/255 × 5 = 3.294 V
- Filter: pick R = 10 kΩ, C = 10 µF → τ = 0.1 s, fc = 1.59 Hz
- Ripple = 5 × 0.66 × 0.34 / (490 × 0.1) = 22.9 mV
- One LSB is 5/255 = 19.6 mV, so ripple is about 1.2 LSB
- Settling time: 5τ = 0.5 s
3.294 V with about 23 mV of ripple, settling in half a second. Fine for a slow reference; for anything that has to move quickly you would raise the PWM frequency rather than the filter time constant.
Practical notes
- Raise the PWM frequency if you can. Every doubling halves the ripple for the same filter, and lets you use a faster filter for the same ripple.
- Arduino Uno defaults to 490 Hz on most pins and 980 Hz on pins 5 and 6. The ESP32's LEDC peripheral goes into the hundreds of kHz, which makes filtering far easier.
- A filtered PWM output has the filter resistor in series with it. Draw any current and you get a voltage divider — buffer it with an op-amp follower if the load is not high-impedance.
- The pin does not swing exactly 0 V to Vcc. Output drivers have a little resistance, so at any real load the high level sags slightly below the supply — which sets your accuracy, not the timer.
- For audio, keep the PWM frequency well above 20 kHz or you will hear it. For motors, above 20 kHz also stops the audible whine.
- If you genuinely need clean, fast analogue output, a real DAC (MCP4725 and similar) costs little and avoids all of this.
Frequently asked questions
How do I convert PWM duty cycle to voltage?
Multiply the duty cycle by the supply voltage, assuming the low level is 0 V. 50% duty on 5 V averages 2.5 V. You need a low-pass filter to actually see that as a steady DC.
Can I use PWM as a DAC?
Yes, with an RC filter on the output. It works well for slowly changing signals — references, setpoints, bias voltages. It struggles when you need fast changes, because reducing ripple means slowing the filter.
What PWM frequency should I use?
Higher is easier to filter. For a DAC, as high as your timer allows. For motors and LEDs, above 20 kHz to stay out of the audible range. For heaters and other slow loads, a few hertz is fine.
Why is my PWM output voltage not what I calculated?
Most often the filter is loaded — anything drawing current through the filter resistor forms a divider. Also check that the pin actually reaches the rails under load, and that your duty cycle is what you think after integer rounding.
What does analogWrite(128) produce?
About 50% duty. On an 8-bit Arduino the range is 0–255, so 128 gives 128/255 = 50.2%, which averages 2.51 V from a 5 V pin — unfiltered, it is still a square wave.