Analog I/O

Lesson 71: Using analogWrite() for PWM Output

Learn how analogWrite() controls PWM duty cycle for LED brightness and other variable-output tasks.

Progress indicator

Lesson 71 of 71

Learning Objectives

  • Understand how analogWrite() generates PWM-style output.
  • Learn duty cycle meaning and how brightness maps from 0-255.
  • Know common PWM pin requirements and board differences.
  • Build smooth fade logic with controlled step changes.
  • Avoid common PWM mistakes in beginner Arduino projects.

Concept Explanation

What is analogWrite()

analogWrite() sets PWM output level on supported pins.

PWM rapidly switches pin HIGH/LOW so devices feel an average output value.

analogWrite() Syntax

analogWrite(pin, value);

How analogWrite() Works

  1. Set PWM value for one output pin.
  2. Timer hardware generates high-frequency pulse waveform.
  3. Duty cycle changes according to PWM value.
  4. Device receives average energy based on duty cycle.

PWM Concept Explained

PWM is not true analog voltage output. It is fast digital pulsing where ON-time ratio controls perceived level.

Duty Cycle Basics

  • 0% duty cycle: always LOW.
  • 50% duty cycle: half cycle HIGH, half LOW.
  • 100% duty cycle: always HIGH.
analogWrite valueApprox duty cycleLED feel
00%OFF
128~50%Medium brightness
255~100%Full brightness

analogWrite() Value Range

Beginner-friendly range is usually 0-255. Lower values mean less ON-time.

PWM Pins on Arduino

PWM support depends on board and pin. Always check board pinout/docs for supported PWM pins.

When to Use analogWrite()

  • LED dimming and visual indicators.
  • Motor speed control via proper driver circuits.
  • Output level modulation where full ON/OFF is too abrupt.

Example Code

This sketch fades LED brightness up and down using analogWrite() and step control.

const int LED_PIN = 2;
int brightness = 0;
int stepValue = 25;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  analogWrite(LED_PIN, brightness);

  Serial.print("brightness=");
  Serial.println(brightness);

  brightness = brightness + stepValue;

  if (brightness >= 255 || brightness <= 0) {
    stepValue = -stepValue;
  }

  delay(120);
}

Example Code Explanation

  1. brightness stores current PWM value.
  2. analogWrite(LED_PIN, brightness) applies that PWM level.
  3. brightness += stepValue moves level up/down each cycle.
  4. When brightness hits edges, stepValue sign is inverted.
  5. This makes smooth fade-in/fade-out loop.
  6. Serial logs help debug PWM transitions.

What Happens Inside

  1. CPU writes PWM compare value to output subsystem.
  2. Timer cycle runs continuously in background.
  3. Pin stays HIGH for duty portion, LOW for remainder.
  4. Human eye integrates pulses as brightness level.
  5. Loop updates compare value for animation effect.

Common Mistakes with analogWrite()

  • Using pins that do not support PWM on target board.
  • Passing invalid range values and expecting stable behavior.
  • Using too large step changes causing flicker/jumps.
  • Driving motors directly from MCU pin without proper driver.

Best Practices for analogWrite()

  • Confirm PWM-capable pin before writing code.
  • Use small step increments for smoother fades.
  • Clamp values in valid range for predictable output.
  • Print PWM values while tuning animations.

Try it now

Open the simulator workspace and observe PWM brightness values during fade cycles.

Run in Simulator