TinySkiff ESP32-S3 Lab · Day 8 of 30

A bright head
and a fading tail

Today the light gains a tail. You reuse the same LED bar from Day 6, then upload a sketch that gives each segment its own brightness with PWM — a bright head at the front, dimmer segments trailing behind, all sliding along the bar and back.

About 20 minutesArduino firstMicroPython optionalSame LED bar as Day 6
Agent assist code TSK-DAY08-METEOR

Hand this to an agent so it can pull the lesson packet and coach you step by step.

01 First, know the pieces

What you need

The same six things as Day 6 — you may already have them wired. Tap Define on any part you haven't met; the answer opens as a field note you can read and dismiss without losing your place.

Official manual photo of the ESP32-S3 development board.
Manual photo

ESP32-S3 board

The brain that runs your uploaded sketch.

Official manual image of the ESP32-S3 GPIO extension board.
Manual photo

GPIO extension board

Spreads the pins into rows you can reach and label.

Official manual photo of a ten-segment LED bar graph module.
Manual photo

LED bar graph

The same strip from Day 6 — ten small LEDs, each its own segment.

Official manual photo of a resistor with coloured value bands.
Manual photo

8 × 220 Ω resistors

One in series with each driven segment to keep every current gentle.

Official manual image of a jumper wire.
Manual photo

Jumper wires

Temporary, solder-free connections.

Official manual screenshot of the Arduino IDE interface.
Manual screenshot

Arduino IDE

Uploads the sketch to the board.

02 Make the physical circuit

Chart the circuit

This is the same LED bar circuit you built on Day 6 — if it's still on the breadboard, you're nearly done. The one difference is that today's sketch drives eight of the segments, because each needs its own PWM channel and the board has eight, so two segments stay dark.

Official Freenove LED-bar circuit — C Tutorial, Chapter 3, page 56 (the meteor light in Chapter 4 reuses it).
8 bar segments (via 220 Ω each) GPIO 21 47 38 39 40 41 42 2 Each pin drives one segment with its own PWM channel.
Bar common row GND Returns every segment to zero volts.

The bar can go in backwards. The LED bar's label direction is easy to reverse. If the driven segments stay dark once you upload, rotate it 180° in the breadboard and try again. Unplug USB before you move any wire.

03 One action at a time

Build it

This is the main path — you can finish the day without opening a single field note. Tap each step as you go to keep your place.

0 / 6 done
  1. Confirm the Day 6 LED bar is still wired, or rebuild it — LED bar across the centre channel, one 220 Ω resistor per segment, common row to ground.

  2. Keep USB unplugged while you check or move any wire.

  3. Note that only eight segments are wired for PWM today, since the board has eight PWM channels; two segments stay dark on purpose.

  4. Compare every wire to the chart before you plug in USB.

  5. Open Sketch_04.2_FlowingLight2.ino in Arduino IDE and upload it.

  6. Watch a bright segment with a fading tail glide along the bar and back.

The light has a tail.

Each segment is now holding its own brightness. Head to Test & debug to confirm the comet and its fading trail.

04 Read just enough code

Read the code

The sketch keeps the pins in one list, like Day 6, but adds a second list of brightness values that forms the tail. Switch to MicroPython if you'd rather see the same idea in Python — the wiring never changes.

Sketch_04.2_FlowingLight2.ino
const byte ledPins[] = {21, 47, 38, 39, 40, 41, 42, 2};
const byte chns[] = {0, 1, 2, 3, 4, 5, 6, 7};
const int dutys[] = {0,0,0,0,0,0,0,0, 1023,512,256,128,64,32,16,8, 0,0,0,0,0,0,0,0};

void setup() {
  for (int i = 0; i < 8; i++) {
    ledcAttachChannel(ledPins[i], 1000, 10, chns[i]);
  }
}

void loop() {
  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 8; j++) {
      ledcWrite(ledPins[j], dutys[i + j]);
    }
    delay(100);
  }
}
ledcAttachChannel(ledPins[i], 1000, 10, chns[i])Gives each of the eight pins its own PWM channel, so every segment can hold a brightness of its own.
const int dutys[] = {0,..., 1023,512,256,128,64,32,16,8, ...,0}A brightness gradient — bright to dim — with dark padding on each side; those falling numbers are the fading tail.
ledcWrite(ledPins[j], dutys[i + j])Reads an eight-wide window of the gradient and slides it one step each pass, which is what makes the comet move.

05 Understand, don't memorise

A gradient that moves

There's no trick here — the board sets eight brightnesses at once, then nudges the whole pattern along the bar, faster than the eye separates the steps.

Brightness

PWM per LED

Each segment gets its own channel so it can be bright or dim.

Gradient

bright to dim

The dutys list falls from full on down to a faint glow.

Slide

one step

An eight-wide window of that list moves one place each pass.

Comet

head and tail

The bright end leads and the dim end trails it down the bar.

The model eight brightnesses → a falling gradient → slide it one step → head leads, tail fades

What PWM is doing

PWM flicks each pin on and off very fast; the fraction of time it stays on sets how bright that segment looks, so a whole row can carry a smooth gradient.

06 Know it worked

Test & debug

Nothing prints to the screen today — the proof is the moving comet on the bar.

What you should see
LED bar
  • A bright segment leads with dimmer segments trailing behind it.
  • The bright head and its fading tail glide along the bar together.
  • Then the comet slides back the other way, smoothly, for as long as the board has power.

Two segments stay dark on purpose — only eight are on PWM, because the board has eight PWM channels.

If it doesn't
  • Only one segment lights, with no tail? You may be running Day 6's on/off sketch — upload 04.2 so PWM sets the brightnesses.
  • A segment in the path stays dark? Check that segment's own 220 Ω resistor and its jumper to its GPIO pin.
  • Nothing lights at all? Re-check the common row to ground, then that the sketch uploaded.
  • Upload fails? Swap in a data-capable USB cable.

07 Make the idea yours

Try this: reshape the comet

Same working circuit, small edits to the sketch. Both fit inside today's time and leave the wiring untouched.

Reshape the tail

Edit the falling numbers in dutys — add more dim values for a longer tail, or fewer for a shorter one. Predict the shape before you upload.

Change the speed

Set delay(100) to a larger or smaller number and upload. Find the speed where the comet still reads as one moving light.

Logbook

08 Learn it with a hand on the tiller

Coach me through it

Every lesson ships with a code and a machine-readable packet, so an agent can guide you with full context.

Lesson code

TSK-DAY08-METEOR

How the agent should behave: confirm the Day 6 circuit first, guide one segment at a time, wait for you to confirm, explain terms on request, and always check wiring, board, port, and USB before changing code.

Field note

Shortcut

Prompt copied