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

Fading LED with Arduino: PWM analogWrite Complete Guide

Fading LED with Arduino: PWM analogWrite Complete Guide

March 11, 2026 /Posted byJayesh Jain / 0

Fading an LED with Arduino is one of the first projects that teaches a crucial concept beyond simple on/off control: Pulse Width Modulation (PWM). Once you understand PWM and the analogWrite() function, you unlock smooth dimming, RGB colour mixing, servo control, motor speed control, and much more. This guide covers everything from the basics of duty cycle to advanced gamma correction for perceptually smooth brightness transitions.

Table of Contents

  • What is PWM and How Does It Work?
  • analogWrite() Basics and Syntax
  • Which Arduino Pins Support PWM?
  • Simple Fade In and Fade Out
  • Smooth Breathing Effect with Sine Wave
  • RGB LED Colour Mixing with PWM
  • Gamma Correction for Natural-Looking Fades
  • Troubleshooting LED Fading Problems
  • FAQ

What is PWM and How Does It Work?

Pulse Width Modulation is a technique for simulating an analogue output using a digital pin. The pin rapidly switches between HIGH (5V) and LOW (0V) at a fixed frequency — on the Arduino Uno, this is approximately 490 Hz on most PWM pins and 980 Hz on pins 5 and 6. The key variable is the duty cycle: the percentage of each cycle that the pin spends in the HIGH state.

  • Duty cycle 0% → pin always LOW → LED fully off
  • Duty cycle 50% → pin half HIGH, half LOW → LED at half brightness
  • Duty cycle 100% → pin always HIGH → LED fully on

The LED flickers at 490 Hz, but because this is much faster than the human eye can detect (the persistence of vision threshold is around 50-60 Hz), the LED appears to glow at a steady intermediate brightness. The average voltage delivered to the LED is proportional to the duty cycle.

The Arduino’s analogWrite() function abstracts all of this away. You simply pass a value from 0 (always off) to 255 (always on), and the hardware timer handles the PWM generation automatically — no interrupts or timer configuration required for basic use.

analogWrite() Basics and Syntax

The syntax is straightforward:

analogWrite(pin, value);
  • pin — a PWM-capable pin number (marked with ~ on the board)
  • value — an integer from 0 to 255

You do not need to call pinMode(pin, OUTPUT) before using analogWrite() — it sets the pin as output automatically. However, it is good practice to explicitly set it in setup() for code clarity.

A simple brightness control example:

const int LED_PIN = 9;

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

void loop() {
  analogWrite(LED_PIN, 0);    // Off
  delay(500);
  analogWrite(LED_PIN, 64);   // 25% brightness
  delay(500);
  analogWrite(LED_PIN, 128);  // 50% brightness
  delay(500);
  analogWrite(LED_PIN, 255);  // Full brightness
  delay(500);
}

Note: analogWrite() has nothing to do with analogRead(). Despite the similar names, they are completely different functions. analogRead() reads an analogue voltage on the ADC pins. analogWrite() outputs a PWM signal on digital pins.

Recommended: Arduino Uno R3 Beginners Kit — The complete starter kit includes the Arduino Uno R3 board, LEDs, resistors, and a breadboard — everything you need to follow this PWM guide and experiment with fading effects immediately.

Which Arduino Pins Support PWM?

Not all digital pins can use analogWrite(). PWM requires a hardware timer, and only certain pins are connected to those timers. Using analogWrite() on a non-PWM pin will not produce an error — it will simply behave like digitalWrite(), fully on for values ≥ 128 and fully off for values below 128.

Arduino Uno R3 PWM pins: 3, 5, 6, 9, 10, 11 (marked with ~ on the board)

Arduino Mega 2560 PWM pins: 2–13 and 44–46 (14 PWM pins total)

Arduino Nano Every PWM pins: 3, 5, 6, 9, 10

Arduino Nano 33 IoT PWM pins: 2, 3, 5, 6, 9, 10, 11, 12, A2, A3, A5

PWM frequencies on the Uno (default, using hardware timers):

  • Pins 5, 6: ~980 Hz (Timer 0)
  • Pins 9, 10: ~490 Hz (Timer 1)
  • Pins 3, 11: ~490 Hz (Timer 2)

Timer 0 is also used by millis() and delay(). Changing Timer 0’s frequency will break timing functions — avoid modifying Timer 0 unless you know what you are doing.

Recommended: Arduino Nano Every with Headers — The Nano Every is a compact and powerful board ideal for LED controller projects where space is limited. It has 5 PWM pins and an ATmega4809 processor with more SRAM than the classic Nano.

Simple Fade In and Fade Out

The classic fade example gradually increases then decreases brightness in a loop. This is the “Fading” example built into the Arduino IDE (File → Examples → 03.Analog → Fading):

const int LED_PIN = 9;

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

void loop() {
  // Fade in
  for (int brightness = 0; brightness <= 255; brightness++) {
    analogWrite(LED_PIN, brightness);
    delay(8);  // 8ms * 256 steps = ~2 seconds to full
  }
  
  // Fade out
  for (int brightness = 255; brightness >= 0; brightness--) {
    analogWrite(LED_PIN, brightness);
    delay(8);
  }
}

The delay value controls the fade speed. Lower values produce a faster fade. At delay(4), the full fade cycle takes about 2 seconds. At delay(20), it takes about 10 seconds.

Always use a current-limiting resistor with your LED. For a standard red LED with a 2V forward voltage on a 5V Arduino pin, a 150Ω to 220Ω resistor limits the current to a safe 10-15 mA. Without a resistor, the LED will draw as much current as the pin can supply (40 mA maximum on Arduino digital pins), which will likely burn out both the LED and the ATmega chip over time.

Smooth Breathing Effect with Sine Wave

The linear fade (incrementing by 1 each step) creates a perceptible pause at both the darkest and brightest points. A sine wave produces a more natural, biological breathing rhythm that accelerates through the mid-range and slows at the extremes:

#include <math.h>

const int LED_PIN = 9;
float phase = 0.0;

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

void loop() {
  // Sine wave oscillates between -1 and 1
  // Map to 0-255 for analogWrite
  float sineVal = (sin(phase) + 1.0) / 2.0;  // 0.0 to 1.0
  int brightness = (int)(sineVal * 255);
  
  analogWrite(LED_PIN, brightness);
  
  phase += 0.02;  // Smaller = slower breathing
  if (phase >= TWO_PI) phase = 0;
  
  delay(10);
}

This creates the familiar “breathing” effect seen on Apple MacBooks in sleep mode and many status indicator LEDs. The sine wave ensures the LED spends more time near minimum and maximum brightness, with a smooth transition through the midpoint.

RGB LED Colour Mixing with PWM

An RGB LED is three LEDs (red, green, blue) in a single package. By controlling each channel’s brightness with PWM, you can mix any colour. Common cathode RGB LEDs connect the negative legs together to GND and control each positive leg separately. Common anode types are the opposite — connect the common anode to 5V and use inverted PWM values (0 = full brightness, 255 = off).

const int RED_PIN   = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN  = 11;

void setup() {
  pinMode(RED_PIN,   OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN,  OUTPUT);
}

void setColor(int r, int g, int b) {
  analogWrite(RED_PIN,   r);
  analogWrite(GREEN_PIN, g);
  analogWrite(BLUE_PIN,  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, 165, 0);    // Orange
  delay(1000);
  setColor(128, 0,   128);  // Purple
  delay(1000);
  setColor(255, 255, 255);  // White
  delay(1000);
  setColor(0,   0,   0);    // Off
  delay(1000);
}

For a smooth rainbow cycle, interpolate through hue values using HSV-to-RGB conversion. There are many Arduino HSV libraries available, or you can implement a simple one yourself using the standard hue wheel algorithm.

Recommended: Multifunction Shield for Arduino Uno / Leonardo — This all-in-one shield includes LEDs, buttons, a 7-segment display, and a buzzer, giving you multiple components to experiment with PWM and other Arduino functions without needing a breadboard.

Gamma Correction for Natural-Looking Fades

The human eye does not perceive brightness linearly. A PWM value of 128 (50% duty cycle) looks much brighter than 50% of maximum brightness to human perception — it actually appears about 73% as bright. This means the first half of a linear 0-to-255 ramp looks slow, while the second half looks fast.

Gamma correction applies a power function to the brightness values to compensate. A gamma value of 2.2 is standard for most displays and LEDs:

// Generate a 256-entry gamma correction lookup table
// Run this once in setup() or store in PROGMEM
uint8_t gamma_table[256];

void buildGammaTable(float gamma) {
  for (int i = 0; i < 256; i++) {
    gamma_table[i] = (uint8_t)(pow((float)i / 255.0, gamma) * 255.0 + 0.5);
  }
}

// Use in your fade loop:
analogWrite(LED_PIN, gamma_table[brightness]);

With gamma correction, the LED appears to dim and brighten at a perceptually uniform rate throughout the full range. This is especially noticeable when dimming LED strips or indicators that must look professional and polished.

For PROGMEM storage (useful when RAM is tight on Uno/Nano), use:

const uint8_t PROGMEM gamma_table[256] = { /* pre-computed values */ };
// Read with: pgm_read_byte(&gamma_table[i])
Recommended: Arduino Nano RP2040 Connect with Header — For advanced PWM projects requiring high-frequency signals, precise timing, or multiple simultaneous fades, the RP2040’s dual cores and PIO state machines offer capabilities far beyond the standard AVR timers.

Troubleshooting LED Fading Problems

LED is full on or full off, no fading:

  • Check that you are using a PWM pin (marked ~ on the board)
  • Verify the pin number in your code matches the physical wiring
  • Confirm the variable type — if your brightness counter is an int, it should not overflow. Using byte (0-255 range) can cause issues if you decrement below 0 on an unsigned type

LED flickers noticeably:

  • A PWM frequency of 490 Hz should not be visible. If you see flicker, check for a loose connection in the LED circuit
  • Some cameras capture PWM flicker even when the human eye does not — try a different camera or phone for video recording
  • If using a MOSFET or transistor driver, ensure the gate/base resistor value is appropriate

LED is dim even at 255:

  • Check the current-limiting resistor value — it may be too large
  • Measure the LED’s forward voltage with a multimeter and recalculate: R = (Vsupply – Vf) / Idesired
  • For high-brightness LEDs, use a dedicated LED driver IC rather than direct Arduino pin control

Timing functions break after using PWM:

  • If you modified Timer 0’s prescaler or mode directly, this will break millis() and delay()
  • Only modify Timer 1 or Timer 2 for custom PWM frequencies
  • Libraries like analogWriteFrequency() from the TimerOne library can help change frequency safely

Frequently Asked Questions

Can I use analogWrite() on all Arduino digital pins?

No. Only PWM-capable pins support analogWrite(). On the Arduino Uno, these are pins 3, 5, 6, 9, 10, and 11, all marked with a tilde (~) on the silkscreen. Calling analogWrite() on a non-PWM pin will not generate an error but will produce incorrect behaviour — the pin will be fully HIGH for values above 127 and fully LOW for values of 127 or below.

What is the PWM frequency on Arduino Uno and can it be changed?

Default frequencies are approximately 490 Hz on pins 3, 9, 10, 11 and 980 Hz on pins 5 and 6. You can change the frequency by modifying the timer prescaler registers directly. The TimerOne and TimerThree libraries provide a safer abstraction. Changing Timer 0 (pins 5, 6) will break millis() and delay(), so avoid it unless absolutely necessary.

Why does my fading LED look uneven — fast at first and slow at the end?

This is a perception issue. The human eye responds to brightness logarithmically, not linearly. A PWM duty cycle of 50% appears much brighter than 50% of full brightness perceptually. Apply gamma correction (gamma ≈ 2.2) to your brightness values to create a perceptually uniform fade. The gamma correction section above includes ready-to-use code.

How many LEDs can I fade simultaneously with analogWrite()?

On the Arduino Uno, you have 6 PWM pins, so you can independently fade up to 6 LEDs. For more LEDs, use a dedicated PWM controller like the PCA9685 (16-channel, I2C) or shift registers. WS2812B addressable LED strips handle their own PWM internally and let you control hundreds of RGB LEDs with a single data pin using the FastLED or NeoPixel library.

Does analogWrite() work the same on all Arduino boards?

The function name and 0-255 range are consistent, but the underlying hardware differs. PWM pin count, frequency, and timer assignments vary between Uno, Mega, Leonardo, Nano, and the newer ARM-based boards like the Due and Zero. Always check the pinout diagram for your specific board. ARM-based boards often support higher PWM frequencies (up to 200 kHz or more) and more PWM channels than AVR-based boards.

Mastering PWM and analogWrite() is a major step up from simple digital on/off control. With these techniques, you can build professional-looking LED effects, precise motor speed controllers, audio signal generators, and much more. The same principles apply whether you are dimming a single LED or controlling a 300-LED strip.

Shop our complete range of Arduino boards and accessories at Zbotic.in — from beginner kits to advanced modules, everything you need for your next electronics project, delivered across India.

Tags: analogWrite, Arduino, beginners, Electronics, Fading LED, LED, PWM, RGB LED
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Arduino GSM SIM800L: Send SMS ...
blog arduino gsm sim800l send sms and call with at commands 594905
blog raspberry pi weather station bme680 and e ink display build 594908
Raspberry Pi Weather Station: ...

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