ESP32-S3 Lab · Day 8 of 30

A bright head
and a fading tail

Today the light gains a tail — and you'll see exactly why it moves. You reuse the same LED bar from Day 6, then upload a sketch that draws one still frame at a time — eight brightnesses set at once, a short pause, then the whole pattern nudged one step along the bar. Run those frames fast enough and they blend into a single gliding comet with a trailing tail. It's the same trick your eye plays at the cinema.

About 25 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, and adds a second list of brightness values. That second list is the whole animation — a bright head with values that fall off behind it — and each frame the loop shows a moving slice of it. 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 — the per-LED control each frame needs.
const int dutys[] = {0,..., 1023,512,256,128,64,32,16,8, ...,0}A brightness for every position — bright head down to a faint glow, with dark padding on each side. Those falling numbers are the tail, baked into the data rather than redrawn each frame.
ledcWrite(ledPins[j], dutys[i + j])Shows one eight-wide slice of the list — a single frame; the i offset moves that slice one step further each pass, so successive frames make the comet travel.

05 Understand, don't memorise

Motion is frames on a timer

There's no special "animation" feature on the chip. Everything that moves — film, a game, this bar — is still frames shown one after another, fast. The loop is your projector — each pass sets a fresh picture and pauses, and a small change between frames becomes motion.

Frame

one pass, one still

Each time through the loop the board sets all eight brightnesses at once and pauses. That fixed picture is one frame.

Array

brightness per LED

A list holds a brightness for every position — a bright head with values that fall off behind it. That falling shape is the tail.

Advance

move a step

Before the next frame the pattern shifts one LED along the bar. A small move plus a short pause reads as the head creeping forward.

Fuse

faster than the eye

At about ten frames a second the pauses disappear and the separate steps blend into one comet gliding down the bar.

The loop set eight brightnesses → pause → shift one step → repeat = a moving picture

How each LED holds a brightness

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

Why the steps look smooth

Each frame lingers on your eye for an instant, and the next arrives before it fades. Around ten frames a second, they merge into continuous motion — the same trick a film reel uses.

One long list, a moving window

The brightness list is longer than the bar and padded with dark at both ends. Each frame shows a different eight-LED slice of it, so the comet can slide in from a dark bar and back out again.

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 one sketch — each one changes the animation and shows you a different part of how it works. All three fit inside today's time and leave the wiring untouched.

See the frames land

Change delay(100) to delay(500) and upload. The comet now steps forward once every half-second, so you can watch each individual frame arrive — the motion you saw was these same stills, shown too fast to separate.

Reshape the tail

Edit the falling numbers in dutys — add more dim values for a longer tail, fewer for a stubbier one. That list is the animation, so predict the new shape before you upload, then check it.

Swap which end leads

Reverse the order of the bright block in dutys so it climbs from dim up to bright. The head and tail trade ends, and the comet appears to run the other way — proof that head and tail are only the shape of the list.

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, then teach the animation idea plainly — one loop pass draws a still frame, the dutys list is the whole animation, and shifting it one step each frame is what moves the comet. Guide edits one at a time, wait for the learner to confirm, explain terms on request, and always check wiring, board, port, and USB before changing code.

Keep your place

Finished Day 8?

Mark it complete — it shows on your course map, and your place is saved on this device.

Field note

Shortcut

Prompt copied