PWM LED Fade Effect
Take your Blink tutorial a step further: instead of a hard on/off, smoothly fade an LED in and out using Pulse Width Modulation (PWM).
What Is PWM?
A digital pin can only be fully HIGH or fully LOW — there's no "half on." PWM fakes an in-between brightness by switching the pin on and off very rapidly. The duty cycle (the percentage of time the signal spends HIGH within each cycle) controls the apparent brightness: 0 is off, 255 is fully on, and everything in between looks dimmer or brighter to your eye.
The Hardware Setup
This reuses the exact same wiring as the Blink tutorial — no new parts needed. We're driving the same LED on GPIO 2, just with a different signal.
The Arduino Source Code
The ESP32 Arduino core (3.0 and newer) supports analogWrite() directly, so you don't need to manually configure the LEDC peripheral for a simple fade. Make sure your board package is up to date in the Boards Manager.
// ESP32-S3 PWM LED Fade Tutorial - CircuitHub.pro
#include <Arduino.h>
const int LED_PIN = 2;
void setup() {
// No pinMode() needed before analogWrite() on modern ESP32 cores,
// but it doesn't hurt to be explicit:
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// Fade in: 0 (off) to 255 (full brightness)
for (int duty = 0; duty <= 255; duty++) {
analogWrite(LED_PIN, duty);
delay(8);
}
// Fade out: 255 back down to 0
for (int duty = 255; duty >= 0; duty--) {
analogWrite(LED_PIN, duty);
delay(8);
}
}
Using an older ESP32 board package? Swap the setup and loop calls for ledcAttach(LED_PIN, 5000, 8) once, then ledcWrite(LED_PIN, duty) in place of analogWrite().
Required Components
Same parts list as the Blink tutorial — if you've already built that circuit, you're ready to go:
🚀 Take It Further: Breathing Light
Right now the fade is linear, which can look a little mechanical. Try replacing the duty cycle with a sine wave calculation ((sin(millis() / 1000.0) + 1) * 127.5) for a smoother, more organic "breathing" effect.