Classroom Public page

Lab 10.1: Fade PWM

520 words

~60 min. Smoothly fade an LED from off to fully bright and back, using analogWrite. Understand what duty cycle means by varying it deliberately.


Goal: master analogWrite for smooth analog-like LED behavior; build the intuition for what duty cycle does

Estimated time: 60 minutes

Prerequisites: lab 7.2 (LED on a pin); lab 9.1 if you want to combine with sensor input

Steps

Step 1: Wire an LED on a PWM-capable pin (5 min)

Pin 9 is a good choice (PWM-capable on the R4). Wire: pin 9 → 220 Ω → LED anode → LED cathode → GND. Same circuit as lab 7.2 if you still have it built

Step 2: Run the Arduino Fade example (10 min)

File → Examples → 01.Basics → Fade. Open the example. Modify the LED pin from 9 to whatever you used. Upload

The LED should smoothly fade from off to bright and back, ~2 seconds per cycle. Watch it. Notice the brightness change is smooth (no visible steps; the eye can't see the 5 ms between successive PWM values)

Step 3: Slow it down to see the steps (10 min)

In the loop, increase the delay between brightness changes. Try delay(50). Now you can see the brightness step up and down in noticeable increments. The PWM is still smooth; the delay between changes is what makes it visible

Set delay back to whatever looks smooth to you (typically 10-20 ms)

Step 4: Make a "breathing" pattern with sin() (20 min)

Replace the linear fade with a sinusoidal pattern:

void setup() {
  pinMode(9, OUTPUT);
}
void loop() {
  for (int t = 0; t < 360; t += 2) {
    float radians = t * PI / 180.0;
    int brightness = (sin(radians) + 1.0) * 127.5;  // map -1..1 to 0..255
    analogWrite(9, brightness);
    delay(10);
  }
}

Upload. The LED now "breathes" with a more natural-looking curve. The sin function makes the brightness change slower near the extremes and faster in the middle, mimicking how living things breathe

Step 5: Combine with the photoresistor (15 min)

Add the photoresistor circuit from lab 9.1. Modify the sketch:

void loop() {
  int reading = analogRead(A0);
  int targetBrightness = map(reading, 200, 800, 255, 0);
  targetBrightness = constrain(targetBrightness, 0, 255);
  analogWrite(9, targetBrightness);
  delay(50);
}

Now the LED brightness tracks ambient light in real time, no fading sequence. This is closed-loop control: sensor → calculation → output → measurable effect

Expected output

  • Smooth-fading LED on PWM pin
  • Optional "breathing" pattern
  • Optional ambient-light-tracking LED

Common pitfalls

  • Wrong pin: analogWrite to a non-PWM pin (like pin 2 or 4 on the R4 Minima) gives digital-only behavior. The LED is full-on for values >= 128 and off for values < 128. Use only PWM-capable pins
  • Mixing analogRead and analogWrite ranges: analogRead is 0-1023; analogWrite is 0-255. Always map between them; never assign one to the other directly
  • delay() makes the sketch unresponsive to fast button presses: PWM-fading uses delay heavily. If you want to fade AND respond to buttons, you need millis()-based timing instead. (Advanced; not required this lab.)

Stretch (optional)

  • Drive three LEDs (red, green, blue) on three PWM pins. Cycle through colors by varying each duty cycle independently (red full → green full → blue full → back to red)
  • Combine PWM with the kit's DC motor (through a transistor). Vary the motor speed with a potentiometer (analogRead on the pot → analogWrite to the transistor's base)
  • Use millis() instead of delay() for the fade. The sketch becomes responsive to button input mid-fade

Lab 10.1 v0.1. PWM closes the loop: digital pins can now do analog-like things.