Twinkling Stars — MicroPython LED Dimming on XIAO-RP2040¶
Date: 2026-02-24
Hardware: Seeed XIAO-RP2040
Language: MicroPython
Topic: Randomly dimming/twinkling 3 LEDs using PWM on analog pins A0, A1, A2
Overview¶
The XIAO-RP2040 does not have true analog output (DAC), but PWM (Pulse Width Modulation) can simulate it — which works perfectly for dimming LEDs. Each LED is faded smoothly to a random brightness target, creating an organic twinkling effect.
Pin Mapping:
| Label | GPIO |
|---|---|
| A0 | GP26 |
| A1 | GP27 |
| A2 | GP28 |
Code¶
import machine
import random
import time
# Set up PWM on A0 (GP26), A1 (GP27), A2 (GP28)
led_pins = [26, 27, 28]
pwm_leds = [machine.PWM(machine.Pin(p)) for p in led_pins]
# Set PWM frequency (1000 Hz works well for LEDs)
for pwm in pwm_leds:
pwm.freq(1000)
def set_brightness(pwm, brightness):
"""Set brightness 0-100% -> duty cycle 0-65535"""
duty = int((brightness / 100) * 65535)
pwm.duty_u16(duty)
def twinkle():
# Pick a random target brightness for each LED
targets = [random.randint(0, 100) for _ in pwm_leds]
# Get current brightness levels
current = [int(pwm.duty_u16() / 65535 * 100) for pwm in pwm_leds]
# Smoothly transition to target brightness
steps = 20
for step in range(steps + 1):
for i, pwm in enumerate(pwm_leds):
brightness = current[i] + (targets[i] - current[i]) * step // steps
set_brightness(pwm, brightness)
time.sleep_ms(30) # Controls fade speed (~600ms total per twinkle)
# Main loop
while True:
twinkle()
time.sleep_ms(random.randint(0, 200)) # Random pause between twinkles
How It Works¶
- PWM at 1000 Hz simulates analog output. The LED can't perceive the flicker, only the average brightness.
- Each
twinkle()call picks a random brightness target (0–100%) for each LED and smoothly fades toward it over 20 steps. - A random pause between twinkles adds organic variation so the LEDs don't sync up.
Tuning Parameters¶
| Parameter | Default | Effect |
|---|---|---|
steps |
20 |
More steps = smoother fade |
time.sleep_ms(30) |
30 ms |
Lower = faster fade, higher = slower |
Random pause (0, 200) |
0–200 ms |
Controls how often twinkles retrigger |
Brightness target (0, 100) |
0–100% |
Raise lower bound (e.g. 10) to prevent LEDs fully turning off |
Wiring¶
Connect each LED (with a ~100Ω resistor in series) between A0/A1/A2 and GND.
The XIAO-RP2040 GPIO pins source 3.3V.
GP26 (A0) ---[100Ω]---[LED]--- GND
GP27 (A1) ---[100Ω]---[LED]--- GND
GP28 (A2) ---[100Ω]---[LED]--- GND
Generated with Claude (claude.ai)