Episode #5 · LED + BUZZER

Give Your Robot a Personality

The two cheapest parts on the whole channel — an LED and a piezo buzzer, under a dollar combined — and the first ones that let your robot talk back to you.

Episode video — paste your YouTube ID to embed

What they are

The LED is a two-legged diode that lights up when current flows one direction only — long leg (anode) positive, short leg or flat rim (cathode) negative. The piezo buzzer is a ceramic disc glued to a thin brass diaphragm: zap it with voltage and it flexes, and that flex makes sound — a speaker with no coil and no magnet.

The bare minimum to use them

  • LED needs a resistor, always. Skip it and the LED burns out in under a second — not optional, ever.
  • Resistor math: (supply V − LED forward V) ÷ desired current. 220Ω is a safe default on 3.3V.
  • Or skip the math entirely: pre-wired LEDs have the resistor built into the lead. That's what this build uses.
  • Buzzer needs no resistor — a small piezo pulls only a few mA, straight off a GPIO pin.
  • Passive vs. active: only a passive buzzer plays real notes with tone(). Active buzzers know one beep.
The mistake everyone makes once: wiring an LED with no current-limiting resistor. It's instant and it's final — the resistor costs less than the LED does.

Wiring

GPIO 20 ──▶ 220Ω resistor ──▶ LED anode (long leg)
LED cathode (short leg / flat side) ──▶ GND

GPIO 21 ──▶ Buzzer +
Buzzer − ──▶ GND

Two of the last free GPIO pins on the SuperMini — everything else is already claimed by the servo, driver, motor, and I2C episodes.

The code — a heartbeat

Blinks the LED and beeps the buzzer together, once a second. Full sketch in the sidebar.

// minirobo EP5 — LED + buzzer heartbeat (ESP32)
const int LED_PIN = 20;
const int BUZZER_PIN = 21;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_PIN, HIGH);
  tone(BUZZER_PIN, 880, 120);   // a short "boop"
  delay(500);
  digitalWrite(LED_PIN, LOW);
  delay(500);
}

digitalWrite() is on/off; analogWrite(pin, 0–255) PWMs the LED for a fade instead of a snap. tone(pin, frequency, duration) plays an actual note on a passive buzzer — string a few together and you've got a melody.

Why your buzzer sounds broken

Wire up a bare disc, run tone(), and you'll hear almost nothing. The part isn't a dud — it's physics. The disc is a dipole: the front face pushes air out at the same instant the back face pulls the same air in, and at the rim the two meet and cancel.

The fix is a housing that seals the back away from the front. Touch the disc to a table and it gets louder; drop it in a cup and it gets much louder; give it a printed body and horn and it's a real speaker. Same disc, same pin, same voltage — the loudness is free, it's just shape.

Bonus: the trapped air plus the cap's port hole form a Helmholtz resonator you can tune onto the disc's own peak (~5.2kHz on ours). That's what the port caps in the sidebar are for — print the set, pick by ear.

What I wish I knew

  • Backwards LED = just dark, not damaged. Safe to flip and retry.
  • Skip the resistor, lose the LED. Every time, no exceptions.
  • "tone() does nothing" means you bought an active buzzer by accident — check before you order.
  • One resistor per LED. Sharing one across two LEDs means one hogs the current and cooks.
  • A silent bare disc is normal. It's cancelling itself, not broken — house it.
  • Piezo buzzers are loud up close. Don't bench-test a housed one next to your ear.

⏱ Your 60-second challenge

Give your robot a heartbeat.

Blink the LED and beep the buzzer together, once a second, like a pulse. Post a clip of your robot's heartbeat in the YouTube comments.