Skip to content

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)