Built-in project · ESP32-DevKitC V4

MicroPython meteor light on eight PWM bar segments, on an ESP32-DevKitC V4

MicroPython on an ESP32: eight segments of an LED bar on PWM pins, a bright head with a fading tail that sweeps up the bar and back. The whole build, an ESP32-DevKitC V4 and 9 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 25 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $11.20. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • PWM duty cycle as brightness
  • Controlling many outputs with a list and a loop
  • A lookup table for a fading tail
  • MicroPython on an ESP32
  • Difficulty: Intermediate
  • Time: About 25 minutes
  • Board: ESP32-DevKitC V4
  • Parts: 10

How it works

Eight GPIO pins, each through a 220 ohm resistor, drive eight segments of an LED bar. Each pin runs PWM at 10,000 Hz, so the code can set every segment to its own brightness.

A bright head moves up the bar one segment every 60 ms. Behind it, the segments get dimmer by half each step, down to a faint tail. When the head reaches the top it comes back down with the tail trailing the other way.

Each full pass prints meteor.

Parts list

10 parts, plus the jumper wires. They retail for about $11.20; on Mokxi they're free.

Kits that can build it

This starter kit has every part in the circuit. Each kit's page lists what else it can build.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Resistor, 220 Ω (8) pin 1ESP32-DevKitC V4 pin 21
Resistor, 220 Ω (7) pin 1ESP32-DevKitC V4 pin 19
Resistor, 220 Ω (6) pin 1ESP32-DevKitC V4 pin 18
Resistor, 220 Ω (5) pin 1ESP32-DevKitC V4 pin 5
Resistor, 220 Ω (4) pin 1ESP32-DevKitC V4 pin 4
Resistor, 220 Ω (3) pin 1ESP32-DevKitC V4 pin 0
Resistor, 220 Ω (2) pin 1ESP32-DevKitC V4 pin 2
Resistor, 220 Ω (1) pin 1ESP32-DevKitC V4 pin 15
LED bar graph, 10 segments pin A2LED bar graph, 10 segments pin A1
Resistor, 220 Ω (8) pin 2LED bar graph, 10 segments pin A3
Resistor, 220 Ω (7) pin 2LED bar graph, 10 segments pin A4
Resistor, 220 Ω (6) pin 2LED bar graph, 10 segments pin A5
Resistor, 220 Ω (5) pin 2LED bar graph, 10 segments pin A6
Resistor, 220 Ω (4) pin 2LED bar graph, 10 segments pin A7
Resistor, 220 Ω (3) pin 2LED bar graph, 10 segments pin A8
Resistor, 220 Ω (2) pin 2LED bar graph, 10 segments pin A9
Resistor, 220 Ω (1) pin 2LED bar graph, 10 segments pin A10
LED bar graph, 10 segments pin C10Ground
LED bar graph, 10 segments pin C9Ground
LED bar graph, 10 segments pin C8Ground
LED bar graph, 10 segments pin C7Ground
LED bar graph, 10 segments pin C6Ground
LED bar graph, 10 segments pin C5Ground
LED bar graph, 10 segments pin C4Ground
LED bar graph, 10 segments pin C3Ground
LED bar graph, 10 segments pin C1LED bar graph, 10 segments pin C2

The code

The MicroPython code exactly as the editor opens it. Change a line there and press Run: the board runs it on the official MicroPython firmware, with nothing to compile.

main.py · ESP32-DevKitC V4
# Meteor light: eight bar segments on PWM, a bright head and a tail that
# fades behind it, moving up the bar and back.
from machine import Pin, PWM
import time

pins = [15, 2, 0, 4, 5, 18, 19, 21]
leds = [PWM(Pin(n), freq=10000, duty=0) for n in pins]
tail = [1023, 512, 256, 128, 64, 32, 16, 8]

def show(head, step):
    # step is +1 going up and -1 coming back: the tail trails behind
    for i, led in enumerate(leds):
        behind = (head - i) * step
        led.duty(tail[behind] if 0 <= behind < len(tail) else 0)

while True:
    for head in range(8):
        show(head, 1)
        time.sleep_ms(60)
    for head in range(7, -1, -1):
        show(head, -1)
        time.sleep_ms(60)
    print("meteor")

Code walkthrough

The key functions of the sketch, and what each one does.

show main.py

Sets the brightness of every segment for one frame. For each LED it works out how far behind the head it sits, then looks that distance up in tail. Segments ahead of the head, or too far behind it, get a duty of zero. The step value flips the direction of the tail.

def show(head, step):
    # step is +1 going up and -1 coming back: the tail trails behind
    for i, led in enumerate(leds):
        behind = (head - i) * step
        led.duty(tail[behind] if 0 <= behind < len(tail) else 0)

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • Segments light in the wrong order This project
    The pins list must match how each GPIO is wired to its resistor and bar segment.
  • The tail looks like a flat block This project
    Check the tail values fall away from 1023, and that each pin is created with PWM, not plain Pin.
  • Segments are dim, uneven, or the chip is damaged. LED bar graph
    Every segment is its own LED and needs its own current-limiting resistor, about 220 to 330 ohms at 5 V. One shared resistor makes brightness change with how many are lit.
  • The bar lights in reverse order or a segment never lights. LED bar graph
    Check pin 1 and the orientation. Anode and cathode sides are on opposite rows. Some bars are numbered the other way around, so test with one segment at a time.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
  • A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
    Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground.
  • The board is not found, or upload fails with a connecting message. ESP32-DevKitC V4
    Use a USB cable that carries data, not charge only. Pick the ESP32 Dev Module board. If it still fails, hold BOOT while uploading starts, then release.
  • Some pins never read right, or the board will not boot with a wire attached. ESP32-DevKitC V4
    GPIO34 to 39 are input only and have no pull-ups. GPIO6 to 11 run the flash, so leave them alone. GPIO0, 2 and 12 are boot pins; avoid pulling them the wrong way at reset.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.