ESP32 UNO - Fade LED

Make an LED glow up and down like a slow breath with the ESP32 Uno fade LED circuit. One LED, one resistor and a PWM pin on the ESP32 Uno form board are all you need to dim an LED smoothly from Arduino code. You get three ready sketches: a looping fade, a timed fade-in and a timed fade-out.

By the end, you can:

  1. Connect an LED and a 220 ohm resistor to a PWM pin
  2. Change LED brightness with analogWrite() values from 0 to 255
  3. Fade an LED in and out in a loop with delay()
  4. Fade in or fade out an LED over 3 seconds with millis(), so the rest of the sketch keeps running
ESP32 Uno fade LED

Components You Need

1×ESP32 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×LED Kit
1×LED (red)
1×LED Module
1×Alternatively, Button and LED Kit
1×220Ω Resistor
1×Breadboard
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Buy Note: Use the LED Module for easier wiring. It includes an integrated resistor.

LED Facts for Dimming

After this part, you know which LED leg goes where and how a digital pin can make "half bright".

Pinout

LED Leg How to Spot It Connect To
Cathode (-) Short leg, flat edge on the rim GND (0V)
Anode (+) Long leg The control pin, through the resistor
LED Pinout

How It Works

Tie the cathode to GND first. Then the signal on the anode sets the light level:

Signal on the Anode LED Result
GND (0V) Dark
Steady supply voltage Full brightness
PWM signal Any level in between

PWM flips the pin between on and off thousands of times per second. Your eye cannot follow the flicker, so it sees the average. In Arduino code, the PWM value runs from 0 to 255:

  • 0 keeps the pin low all the time, so the LED is dark.
  • 255 keeps the pin high all the time, so the LED is at full power.
  • 128 keeps the pin high about half of each cycle, so the LED looks roughly half bright.
How LED Works

※ NOTE THAT:

Put a resistor in series with the LED to cap the current. The exact value depends on the LED type. For a standard 5 mm LED on a 3.3V pin, 220 ohm keeps the current low and safe.

Dimming an LED with the ESP32 Uno

To fade, the LED must sit on a pin that can output PWM. Nearly every Uno header pin on the ESP32 Uno can do this, so you pick D9 here, as on the original diagram. Run the anode through the resistor to that pin, take the cathode to GND, and let the code change the PWM value over time.

Good to know: ESP32 Uno pins give 3.3V when high, not 5V, so the top brightness is a little lower than on a 5V board.

ESP32 Uno Pinout

Your sketch talks to GPIO numbers, while the board labels show Uno names like D9. Use this diagram to find the GPIO behind each header pin before you place the jumper wires.

ESP32 Uno pinout diagram

How to Connect

After this step, the LED sits on D9 and is ready for PWM.

The wiring diagram between ESP32 Uno LED

This image is created using Fritzing. Click to enlarge image

LED Pin ESP32 Uno Pin
Anode (+) via 220 ohm resistor D9 (GPIO13)
Cathode (-) GND

Good to know: D9 is GPIO13, a normal I/O pin with PWM and no boot role, so you can leave the LED plugged in during uploads.

Two Functions That Control Brightness

After this part, you know the two calls behind every fade sketch.

Step 1 — Set the pin as an output

Call pinMode() one time in setup(). D9 is GPIO13, so the code uses 13:

pinMode(13, OUTPUT);

Step 2 — Write a brightness level

Call analogWrite() each time you want a new level:

analogWrite(13, brightness);

brightness takes any whole number from 0 (dark) to 255 (brightest).

ESP32 Uno Code - Classic Fade Sketch

This is the well-known Fade example from the Arduino IDE, with the pin set to GPIO13. Every 30 ms it moves the brightness by 5 and turns back at 0 and 255, so the LED rises and falls forever.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-fade-led */ #define LED_PIN 13 // D9 (GPIO13) feeds the LED anode through the resistor int brightness = 0; // current PWM level sent to the LED int fade_step = 5; // amount the level changes on each pass // setup() runs one time after power-on or a reset void setup() { // make D9 (GPIO13) an output pin pinMode(LED_PIN, OUTPUT); } // loop() repeats without end void loop() { // write the current level to D9 (GPIO13) analogWrite(LED_PIN, brightness); // move the level up or down for the next pass brightness = brightness + fade_step; // flip the direction when the level hits either end if (brightness <= 0 || brightness >= 255) { fade_step = -fade_step; } // short pause so the eye can follow the change delay(30); }

Upload and Test

  1. First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
  2. Build the circuit by following the wiring table above.
  3. Plug in the USB Type-C cable between the ESP32 Uno and your computer.
  4. Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
  5. Paste the sketch into a new Arduino IDE window.
  6. Press Upload and wait for "Done uploading" at the bottom.
Arduino IDE Upload Code
  1. Check the LED: one full dark-to-bright-to-dark cycle takes about 3 seconds (51 steps up and 51 down, 30 ms each).
  2. Pro tip: set fade_step to 1 and delay(30) to delay(6). The cycle time stays almost the same, but the 255 small steps look much smoother at low brightness.

Video Tutorial

See the ESP32 Uno build in action in the video below.

Code Explanation

After this part, you can change the speed and range of the fade with confidence.

Code Part What It Does
#define LED_PIN 13 Names GPIO13 (header D9) once for the whole sketch
int brightness = 0 Keeps the PWM level that goes out next
int fade_step = 5 Sets how much the level changes per pass
analogWrite(LED_PIN, brightness) Sends the level to the LED as PWM
fade_step = -fade_step Turns the fade around at 0 and 255
delay(30) Holds each level for 30 ms

The result is a steady triangle wave of light that never stops.

※ NOTE THAT:

delay() freezes the board for those 30 ms on every pass. A button press or sensor read in the same loop would be late or missed. The two sketches below fix this: they look at millis() to know how far the fade has gone, so loop() never waits.

Timed Fade-Out Without delay()

After this part, the LED dims from full to dark in 3 seconds and then starts over.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-fade-led */ #define LED_PIN 13 // D9 (GPIO13) feeds the LED anode through the resistor #define FADE_PEDIOD 3000 // one full fade lasts 3000 ms unsigned long fade_start_ms; // setup() runs one time after power-on or a reset void setup() { pinMode(LED_PIN, OUTPUT); // make D9 (GPIO13) an output pin fade_start_ms = millis(); } // dim from full to off, then begin again void loop() { unsigned long progress = millis() - fade_start_ms; if (progress <= FADE_PEDIOD) { long brightness = 255 - map(progress, 0, FADE_PEDIOD, 0, 255); analogWrite(LED_PIN, brightness); } else { fade_start_ms = millis(); // start a new fade cycle } }
Code Part What It Does
millis() - fade_start_ms Time passed since this fade began
map(progress, 0, FADE_PEDIOD, 0, 255) Turns 0 to 3000 ms into 0 to 255
255 - map(...) Flips the value so the light goes down
fade_start_ms = millis() Starts the next 3-second cycle

Halfway through, at 1500 ms, the LED gets a level of about 128.

Timed Fade-In Without delay()

After this part, the LED rises from dark to full in 3 seconds and repeats.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-fade-led */ #define LED_PIN 13 // D9 (GPIO13) feeds the LED anode through the resistor #define FADE_PEDIOD 3000 // one full fade lasts 3000 ms unsigned long fade_start_ms; // setup() runs one time after power-on or a reset void setup() { pinMode(LED_PIN, OUTPUT); // make D9 (GPIO13) an output pin fade_start_ms = millis(); } // brighten from off to full, then begin again void loop() { unsigned long progress = millis() - fade_start_ms; if (progress <= FADE_PEDIOD) { long brightness = map(progress, 0, FADE_PEDIOD, 0, 255); analogWrite(LED_PIN, brightness); } else { fade_start_ms = millis(); // start a new fade cycle } }

The only change from the fade-out sketch is that the map() value goes straight to analogWrite(). Edit FADE_PEDIOD to set a longer or shorter fade, for example 8000 for a slow sunrise effect.

ESP32 Uno vs UNO R4 for This Project

This table lists what really changes when you move this fade project from the UNO R4 to the ESP32 Uno.

Item Arduino UNO R4 ESP32 Uno
Logic voltage 5V 3.3V
LED pin D9 (pin 9 in code) D9 (GPIO13, 13 in code)
PWM range in analogWrite() 0 to 255 0 to 255 (default)
Brightness at 255 A bit brighter (5V) A bit lower (3.3V)
Arduino IDE board Arduino UNO R4 WiFi or Minima ESP32 Dev Module
Wireless WiFi only on the WiFi model WiFi and Bluetooth built in

The same wiring works as-is. Only the pin number in the code changes from 9 to 13.

Go Wireless: Set the Glow from Your Phone

After this part, you have an idea for setting the LED brightness without touching the board.

The ESP32 Uno has WiFi and Bluetooth on the chip. Replace the automatic fade with a slider on your phone: each slider value from 0 to 255 goes straight into analogWrite(13, value). You can also add an on/off switch on the same page for the LED.

Function References

Open these pages for the full details of each function in the sketches:

Troubleshooting

Problem Possible Cause Solution
Arduino IDE lists no COM port CH340 driver missing or a charge-only cable Install the CH340 driver and swap to a USB data cable
Upload ends with "Failed to connect" or "Waiting for download" Board did not go into download mode Hold the BOOT button when the upload starts and let go once writing begins
LED stays dark the whole time LED legs swapped or loose breadboard wire Turn the LED so the long leg faces the resistor and D9, and press all wires in firmly
LED blinks hard on and off instead of fading Code still uses pin 9 Set LED_PIN to 13, the GPIO behind header D9
"analogWrite was not declared" when compiling esp32 core older than 2.0.11 Update esp32 by Espressif Systems in the Boards Manager
Fade looks steppy near dark Step of 5 is coarse at low levels Use a step of 1 or 2 with a shorter delay
LED is weak even at 255 Resistor too big for a 3.3V pin Use 100 to 220 ohm, never no resistor
Board resets when the LED is plugged in Short between 3.3V or 5V and GND on the breadboard Check the resistor and cathode rows for a bridge

FAQ

Can the ESP32 Uno use analogWrite() like a normal Arduino board?

Yes, with the esp32 by Espressif Systems core 2.0.11 or newer (including 3.x). It takes the usual 0 to 255 value. Older cores only had the ledc functions, so update the core if the compiler complains.

What PWM frequency does analogWrite() use on the ESP32 Uno?

The default is about 1 kHz with 8-bit resolution. That is far too fast to see, so the LED looks steady at every level. You can change it with analogWriteFrequency() and analogWriteResolution() if you ever need to.

Why does the code use 13 when the LED is wired to D9?

The ESP32 Uno code uses the chip GPIO number, not the Uno label. Header D9 is wired to GPIO13. If you type 9, the sketch drives GPIO9, which is a flash pin, and the LED will not fade.

Do I need the resistor if the pin is only 3.3V?

Yes. Without it, the LED pulls too much current from the pin. That can damage the LED and the ESP32 Uno pin. A 220 ohm resistor gives a safe current of a few milliamps.

Can I fade the LED on pins A2 to A5?

No. On the ESP32 Uno, A2 to A5 are GPIO35, 34, 36 and 39, and these pins are input only. They cannot output PWM. Use a digital header pin such as D3, D5, D6, D7 or D9 instead.

Is D8 a good choice for a fading LED?

Avoid it if you can. D8 is GPIO12, a boot strapping pin that must be LOW at startup. A circuit that pulls it high can stop the board from starting. D9 (GPIO13), used here, has no such role.

How can I fade two LEDs at different speeds?

Use the millis() style from the timed sketches. Give each LED its own start time, period and pin, and update both in the same loop(). With delay(), one LED would hold up the other.

Will a fade sketch written for another Uno board run here?

Almost always. For a sketch from the UNO R4, change the pin number to the GPIO from the pinout (9 becomes 13), pick ESP32 Dev Module and upload. The analogWrite(), map() and millis() calls stay the same.

What if my fade project needs more pins than the Uno headers give?

The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they also work while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Fit them with soldered pin headers, then put the bare GPIO number in the sketch. For more fading LEDs, GPIO32 and GPIO33 are the best picks. Two warnings: GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, so a wrong connection can stop the board from booting or uploading code; use GPIO32/33 first. Never use the six holes under the digital header (SD0 to SD3, CMD, CLK = GPIO6 to GPIO11); they are wired to the flash chip and using them crashes the board.

Can I control the LED brightness from a phone?

Yes. The ESP32 Uno has WiFi and Bluetooth, so a phone slider can send the brightness value to analogWrite(). See the Go Wireless section above for the web and Bluetooth slider guides.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!