Advertisement
Loading...

Arduino PWM Frequency Calculator

Default 16 MHz for standard Arduino boards. Use 8000000 for 8 MHz boards.

Enter the target output frequency in Hz. Typical ranges: 50 Hz (servo), 490–980 Hz (default), 20 kHz (motor).

Configure Your PWM Settings

Select a board, timer, PWM mode, and desired frequency above. The calculator will instantly compute the optimal prescaler, register values, and generate Arduino C++ code.

Advertisement
Loading...

How to Use the Arduino PWM Frequency Calculator

1

Select Your Board and Timer

Choose Arduino Uno/Nano for ATmega328P or Arduino Mega for ATmega2560. Then select the timer you want to configure: Timer0 (8-bit, avoid — used by millis/delay), Timer1 (16-bit, most flexible), Timer2 (8-bit, extra prescaler options), or Timer3/4/5 (Mega 16-bit). The calculator automatically adjusts available prescalers and output pins based on your selection.

2

Choose PWM Mode and Enter Frequency

Select Fast PWM for highest frequency and simpler counting (counts up only), Phase Correct PWM for symmetric pulses ideal for motor control (counts up and down), or CTC for interrupt-based timing. Enter your desired PWM frequency in Hz — for example, 490 (default), 1000 (1 kHz), 20000 (20 kHz for silent motor control), or 50 (RC servo). The auto prescaler mode finds the combination with the lowest frequency error.

3

Set Duty Cycles for Both Channels

Enter the duty cycle percentage for Channel A and Channel B independently (0–100%). Channel A corresponds to the OC1A/OC2A pin and Channel B to OC1B/OC2B. The calculator computes the exact OCR register value for each channel and displays a bar showing the duty cycle proportion. The waveform diagram at the top of the results card shows a visual preview of Channel A's pulse shape.

4

Copy the Generated Code

The Generated Arduino Code section at the bottom shows a complete setup() function with all TCCR register assignments, the ICR/OCR TOP value, both OCR duty cycle values, and pinMode calls for the output pins. Click 'Copy Code' to copy it to your clipboard, then paste directly into your Arduino sketch. Use 'Print' to print all register values and code for your project notes.

Frequently Asked Questions

Why is Timer0 dangerous to modify on Arduino?

Arduino's core library uses Timer0 for three critical functions: millis(), micros(), and delay(). These functions rely on Timer0's overflow interrupt to count time since the sketch started. If you change Timer0's prescaler or mode registers, the timing reference shifts — millis() will return incorrect values, delay() will wait for the wrong duration, and any library that depends on them (such as SoftwareSerial, the Servo library on Timer0-assigned pins, and PWM on pins 5 and 6) will malfunction. For custom PWM, use Timer1 or Timer2 on Uno, or Timer3/4/5 on Mega, which do not interfere with the Arduino core timing.

What is the difference between Fast PWM and Phase Correct PWM?

Fast PWM uses single-slope counting: the timer counts from 0 up to TOP, resets to 0, and the output pin is set and cleared based on the OCR compare value within that one-way count. This produces the highest frequency for a given prescaler and TOP. Phase Correct PWM uses dual-slope counting: the timer counts from 0 up to TOP, then counts back down to 0, with the output toggling on the way up and again on the way down. This produces exactly half the frequency of Fast PWM but creates symmetrically centered pulses, which reduces harmonic distortion. For motor control and servo driving, Phase Correct PWM is preferred because the symmetric pulses minimize ripple current and electromagnetic interference. For audio DAC or high-frequency switching, Fast PWM is typically chosen.

What is the highest PWM frequency achievable on an Arduino Uno?

The theoretical maximum PWM frequency on an Arduino Uno (16 MHz) depends on the timer. With Timer1 in Fast PWM mode and prescaler 1, the formula gives f = 16,000,000 / (1 × (1 + TOP)). Setting TOP = 1 gives 8 MHz, but the duty cycle resolution drops to only 1 bit (2 steps: 0% or 50%). A more practical maximum is around 4 MHz with TOP = 3 (4 steps of resolution). For Timer0 and Timer2 in Fast PWM with prescaler 1, the fixed TOP of 255 gives f = 16,000,000 / (1 × 256) = 62,500 Hz with full 8-bit resolution. The highest frequency with reasonable resolution is generally considered around 1 MHz for Timer1 (TOP ~15, prescaler 1).

What is the lowest PWM frequency achievable on Arduino?

The lowest frequency is achieved with the largest prescaler and the highest TOP value. For Timer1 (16-bit) in Phase Correct PWM mode with prescaler 1024: f = 16,000,000 / (2 × 1024 × 65535) ≈ 0.119 Hz — about one cycle every 8.4 seconds. For Fast PWM: f = 16,000,000 / (1024 × 65536) ≈ 0.238 Hz. For 8-bit timers with prescaler 1024 and fixed TOP of 255, Phase Correct gives f = 16,000,000 / (1024 × 510) ≈ 30.6 Hz. Timer1's 16-bit range makes it far more capable than Timer0 or Timer2 for very low frequency applications such as slow LED breathing effects or long-period control signals.

Why does my achieved frequency not exactly match my target?

The TOP register only accepts integer values (0–65535 for 16-bit, 0–255 for 8-bit), which means the achievable frequencies are quantized — you can only hit exact multiples of the base tick frequency (clock / prescaler). For example, with a 16 MHz clock and prescaler 8, the timer ticks at 2 MHz, so Fast PWM frequencies are available only at 2,000,000 / (TOP + 1) for integer TOP values. If your target frequency does not land exactly on one of these quantized values, there will be a small error. The calculator shows this frequency error as a percentage and picks the prescaler/TOP combination that minimizes it. Switching to a different prescaler or using Timer1's variable-TOP mode usually yields a smaller error than 8-bit timers.

How do I set different duty cycles on Channel A and Channel B?

Each output compare channel (A and B) on a timer has its own OCR register: OCR1A for Channel A, OCR1B for Channel B (and OCR1C on Mega timers). Both channels share the same TOP value and therefore the same output frequency, but you set OCR1A and OCR1B independently to control their individual duty cycles. The duty cycle percentage maps to a register value via: OCR = round(TOP × duty% / 100). Both channels' output pins must be configured with pinMode(pin, OUTPUT) in setup(). In the generated code, the calculator includes both OCR assignments and both pinMode calls so that both channels work immediately after uploading.