Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Arduino & Microcontrollers

Arduino PWM Tutorial: Analogwrite, Frequency & Duty Cycle

Arduino PWM Tutorial: Analogwrite, Frequency & Duty Cycle

March 11, 2026 /Posted byJayesh Jain / 0

Pulse Width Modulation (PWM) is one of the most powerful techniques in the Arduino programmer’s toolbox. Whether you want to dim an LED smoothly, control the speed of a DC motor, or generate analog-like output from a digital pin, PWM is your go-to solution. In this comprehensive tutorial, you will learn everything about Arduino PWM — from the basics of analogWrite() to tweaking timer frequencies and building real projects.

Table of Contents

  • What Is PWM and How Does It Work?
  • Arduino PWM Pins and Timer Mapping
  • Using the analogWrite() Function
  • Understanding Duty Cycle
  • Changing PWM Frequency on Arduino
  • Practical PWM Projects
  • Troubleshooting Common PWM Issues
  • Frequently Asked Questions

What Is PWM and How Does It Work?

PWM stands for Pulse Width Modulation. It is a technique where a digital signal rapidly switches between HIGH (5V) and LOW (0V) at a fixed frequency. By varying the proportion of time the signal stays HIGH versus LOW in each cycle, you can simulate an intermediate voltage level.

Think of it like a light switch that you flick on and off very fast. If it is on 50% of the time and off 50% of the time, your eye perceives it as a light glowing at half brightness. This is exactly how LED dimming works with PWM.

The key parameters of a PWM signal are:

  • Frequency: How many on/off cycles happen per second (measured in Hz). Arduino Uno defaults to about 490 Hz or 980 Hz depending on the pin.
  • Duty Cycle: The percentage of one cycle during which the signal is HIGH. 0% means always OFF, 100% means always ON, and 50% means equal time on and off.
  • Period: The time for one complete on/off cycle (1 / frequency).

PWM is used in motor speed control, servo positioning, audio generation, power regulation, and countless other applications in embedded systems.

Recommended: Arduino Uno R3 Beginners Kit — the ideal starting point for learning PWM, comes with an LED, resistors, and a motor so you can try every example in this tutorial right away.

Arduino PWM Pins and Timer Mapping

Not every digital pin on an Arduino supports PWM. On the Arduino Uno and Nano, only 6 pins are PWM-capable, and they are marked with a tilde (~) on the board silkscreen: pins 3, 5, 6, 9, 10, and 11.

Each PWM pin is driven by one of the Arduino’s internal hardware timers:

Pin Timer Default Frequency
3 Timer2 (OC2B) 490 Hz
5 Timer0 (OC0B) 980 Hz
6 Timer0 (OC0A) 980 Hz
9 Timer1 (OC1A) 490 Hz
10 Timer1 (OC1B) 490 Hz
11 Timer2 (OC2A) 490 Hz

Important note: Timer0 is also used by Arduino’s millis(), micros(), and delay() functions. If you modify Timer0’s frequency to change PWM on pins 5 or 6, these time-keeping functions will return incorrect values. Be careful when changing Timer0 prescaler settings.

The Arduino Mega 2560 has many more PWM pins — 15 in total — spread across pins 2–13 and 44–46, giving you much more flexibility for complex projects.

Recommended: Arduino Mega 2560 R3 Board — with 15 PWM pins and far more memory, it is perfect for projects that need simultaneous control of multiple motors, servos, or LED channels.

Using the analogWrite() Function

The simplest way to output a PWM signal in Arduino is through the built-in analogWrite() function. Despite the name, it does not produce a true analog voltage — it produces a PWM signal whose average voltage simulates an analog level.

Syntax:

analogWrite(pin, value);
  • pin — A PWM-capable pin number (3, 5, 6, 9, 10, or 11 on Uno)
  • value — An integer from 0 to 255, where 0 = 0% duty cycle (always LOW) and 255 = 100% duty cycle (always HIGH)

LED Fade Example:

int ledPin = 9;  // PWM pin

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // Fade in
  for (int brightness = 0; brightness = 0; brightness--) {
    analogWrite(ledPin, brightness);
    delay(10);
  }
}

This code smoothly fades an LED connected to pin 9 (through a 220-ohm resistor) in and out. Each step changes the duty cycle by roughly 0.4%, giving a very smooth visual effect.

You can also use analogWrite() to control DC motor speed via an L298N or similar motor driver module by connecting the motor driver’s enable pin to a PWM pin on the Arduino.

Recommended: Arduino Nano Every with Headers — a compact board with 6 PWM pins and the upgraded ATmega4809 processor, great for space-constrained PWM motor or LED projects.

Understanding Duty Cycle

The duty cycle is the percentage of time the PWM signal remains HIGH within a single period. It directly determines how much power is delivered to the load:

  • 0% duty cycle (value = 0): Pin stays LOW. Load receives 0V average.
  • 25% duty cycle (value ≈ 64): Pin is HIGH 25% of the time. Average ≈ 1.25V.
  • 50% duty cycle (value = 127): Pin is HIGH half the time. Average ≈ 2.5V.
  • 75% duty cycle (value ≈ 191): Pin is HIGH 75% of the time. Average ≈ 3.75V.
  • 100% duty cycle (value = 255): Pin stays HIGH. Load receives 5V average.

The formula to convert the analogWrite value to duty cycle percentage is:

Duty Cycle (%) = (value / 255) * 100

And to get the average output voltage:

Average Voltage = (value / 255) * VCC

Where VCC is 5V for the Uno or 3.3V for boards like the Arduino Nano 33 IoT.

Important: Inductive loads like motors have natural low-pass filtering. The motor’s inductance averages the PWM pulses into a smooth current flow. Resistive loads like LEDs also respond to the average power, which is why LED brightness changes smoothly with duty cycle.

Changing PWM Frequency on Arduino

The default PWM frequency of 490 Hz or 980 Hz works fine for most applications. However, there are cases where you need different frequencies:

  • Audio generation: You may need frequencies in the audible range (20 Hz – 20 kHz).
  • Motor control: Some motor drivers prefer higher frequencies (above 20 kHz) to eliminate audible whine.
  • Switch-mode power supplies: Require specific frequencies for efficiency.

You can change PWM frequency by directly modifying the Timer Control Registers (TCCR) in the ATmega328P. This is done by changing the timer’s prescaler value:

// Change Timer2 frequency for pins 3 and 11
// Prescaler settings for Timer2 (OC2A/OC2B):
// 0x01 = no prescaling  → ~31,372 Hz
// 0x02 = /8            → ~3,921 Hz
// 0x03 = /32           → ~980 Hz
// 0x04 = /64           → ~490 Hz (default)
// 0x05 = /128          → ~245 Hz
// 0x06 = /256          → ~122 Hz
// 0x07 = /1024         → ~30 Hz

void setup() {
  // Set Timer2 prescaler to 1 (no prescaling) for high frequency
  TCCR2B = (TCCR2B & 0b11111000) | 0x01;
  // Now pins 3 and 11 output ~31,372 Hz PWM
  analogWrite(3, 128);  // 50% duty cycle at 31 kHz
}

For Timer1 (pins 9 and 10), you can use a similar approach but Timer1 also supports 16-bit operation, giving you much finer frequency control:

// Set Timer1 for a specific frequency using ICR1
void setPWMFrequency(int pin, long frequency) {
  // Only works for Timer1 pins (9, 10)
  long period = F_CPU / frequency;  // Clock cycles per period
  ICR1 = period - 1;                // Set TOP value
  OCR1A = period / 2;               // 50% duty cycle on pin 9
  
  // Fast PWM mode, ICR1 as TOP, prescaler = 1
  TCCR1A = _BV(COM1A1) | _BV(WGM11);
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
}
Recommended: Arduino Frequency Counter Kit with 16×2 LCD Display — measure and verify your custom PWM frequencies in real time. A great companion tool when experimenting with timer register changes.

Practical PWM Projects

Project 1: RGB LED Color Mixing

By connecting the R, G, and B pins of an RGB LED (each through a 220-ohm resistor) to pins 9, 10, and 11, you can mix any color using three analogWrite() calls:

int redPin   = 9;
int greenPin = 10;
int bluePin  = 11;

void setup() {
  pinMode(redPin,   OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin,  OUTPUT);
}

void setColor(int r, int g, int b) {
  analogWrite(redPin,   r);
  analogWrite(greenPin, g);
  analogWrite(bluePin,  b);
}

void loop() {
  setColor(255, 0,   0);   // Red
  delay(1000);
  setColor(0,   255, 0);   // Green
  delay(1000);
  setColor(0,   0,   255); // Blue
  delay(1000);
  setColor(255, 255, 0);   // Yellow
  delay(1000);
  setColor(128, 0,   128); // Purple
  delay(1000);
}

Project 2: DC Motor Speed Control

Connect a small DC motor to an L298N motor driver module. Connect the driver’s ENA pin to Arduino pin 9. Now you can control motor speed:

int enablePin = 9;   // PWM speed control
int in1Pin    = 7;   // Direction control
int in2Pin    = 8;   // Direction control

void setup() {
  pinMode(enablePin, OUTPUT);
  pinMode(in1Pin,    OUTPUT);
  pinMode(in2Pin,    OUTPUT);
  // Set direction: forward
  digitalWrite(in1Pin, HIGH);
  digitalWrite(in2Pin, LOW);
}

void loop() {
  // Ramp up speed
  for (int speed = 0; speed = 0; speed -= 5) {
    analogWrite(enablePin, speed);
    delay(50);
  }
  delay(1000);
}

Project 3: Reading Potentiometer to Control PWM

This is a classic beginner project — read an analog value from a potentiometer and map it to a PWM brightness level:

int potPin = A0;
int ledPin = 9;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int potValue = analogRead(potPin);     // 0–1023
  int brightness = potValue / 4;         // Map to 0–255
  analogWrite(ledPin, brightness);
}
Recommended: Multifunction Shield for Arduino Uno / Leonardo — includes a potentiometer, LED array, and display on a single shield, perfect for experimenting with PWM brightness control without extra wiring.

Troubleshooting Common PWM Issues

1. LED doesn’t dim smoothly near 0: Human eyes are not linear. PWM value 10 looks much brighter than 0, but the jump from 50 to 60 is barely visible. Use a gamma correction table or map the potentiometer value through a square or cube function for a perceptually linear response.

2. Motor vibrates or makes noise at low duty cycles: This is normal for DC motors at low PWM frequencies. Increase the PWM frequency (above 20 kHz using Timer2 or Timer1 adjustments) to push the switching noise above audible range.

3. millis() and delay() are wrong after Timer0 change: Timer0 drives the Arduino’s time functions. Changing Timer0 prescaler will make delay(1000) not actually wait 1 second. Use Timer1 or Timer2 for frequency changes to avoid breaking timing functions.

4. PWM pin stays at constant voltage: Make sure you are calling analogWrite() inside loop() or at least once after setup(). Also confirm you are using a real PWM pin (marked with ~).

5. Servo jitters when using analogWrite() on Timer1: Standard servo libraries use Timer1. If you change Timer1 for PWM, servo control will break. Use the Servo library on pins 9 or 10 only if you are NOT manually adjusting Timer1.

Frequently Asked Questions

What is the difference between analogWrite() and true analog output on Arduino?

analogWrite() produces a PWM (digital) signal, not a true analog voltage. The pin rapidly switches between 0V and 5V. For a true analog output, you need an external DAC (Digital to Analog Converter) chip or use a low-pass RC filter after the PWM pin to smooth the signal into a true DC voltage level.

Can I use all 6 PWM pins simultaneously on Arduino Uno?

Yes, you can call analogWrite() on all 6 PWM pins at the same time. Each pin has its own timer compare register (OCR), so they operate independently. The only shared resource is the timer clock, which means pins on the same timer (like 5 and 6 on Timer0) share the same frequency but can have different duty cycles.

What PWM frequency should I use for motor speed control?

For DC motors, anything from 490 Hz to 20 kHz works electrically. Higher frequencies (15–25 kHz) reduce audible whine from motor windings, which improves user experience in quiet environments. For servo motors, use the dedicated Servo library instead, which generates the correct 50 Hz signal with precise pulse widths.

Why does my PWM output measure a fixed voltage on a multimeter?

A standard DC multimeter measures the average voltage of a PWM signal, not its instantaneous value. So a 50% duty cycle on a 5V pin will read approximately 2.5V. This is the expected behavior. To see the actual PWM waveform, use an oscilloscope.

Does the Arduino Nano 33 IoT support PWM?

Yes, the Arduino Nano 33 IoT supports PWM on pins 2, 3, 5, 6, 9, 10, 11, 12, A2, A3, and A5 — far more than the classic Uno. It operates at 3.3V logic, so the maximum average voltage from PWM is 3.3V instead of 5V. Be careful when interfacing with 5V peripherals.

Start Your Arduino PWM Journey Today

PWM is a foundational skill that unlocks a huge range of Arduino projects — from simple LED dimmers to sophisticated motor controllers and audio synthesizers. The key concepts to remember are: analogWrite() takes values from 0–255, duty cycle is the ratio of on-time to total period, and you can change PWM frequency by modifying timer prescaler registers (with care not to break millis() and delay()).

Once you are comfortable with the basics, explore more advanced techniques like complementary PWM for H-bridge control, phase-correct PWM mode for precise motor control, and interrupt-driven PWM for tight timing requirements.

Browse the full range of Arduino boards and accessories at Zbotic.in — India’s trusted electronics components store — and start building your next PWM-powered project today.

Tags: analogWrite, arduino motor control, arduino pwm, arduino tutorial, duty cycle, led dimming, pwm frequency
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Watchdog Timer Arduino: Preven...
blog watchdog timer arduino prevent program freeze and auto reset 594920
blog arduino tft display st7789 full color screen projects 594924
Arduino TFT Display ST7789: Fu...

Related posts

Svg%3E
Read more

Arduino Batch Programming: Flash Multiple Boards Quickly

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Based Radar System with Ultrasonic Sensor

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Automatic Plant Monitor: Sunlight, Moisture, Temperature

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Lie Detector: GSR Sensor Polygraph Project

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading
Svg%3E
Read more

Arduino Metal Detector: Build a Treasure Finder

April 1, 2026 0
Table of Contents Introduction Components and Hardware Setup Wiring Diagram and Connections Complete Code with Explanation Customization and Improvements Troubleshooting... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now