Learning Goals 5 min
By the end of this lesson you will be able to:
- Wire the three LEDs from L01-10 and the piezo buzzer from L01-14 onto the same breadboard, all sharing GND through the − rail.
- Write a sketch that combines a chase across the three LEDs with a 5-note melody on the buzzer — using helper functions from L01-12 so the body of
loop()reads like a script. - Recognise that you've just built your first multi-component output device — and that every project from here on is the same combine-components-on-one-breadboard pattern.
Warm-Up 10 min
Eight lessons ago you wired your first LED. Fourteen lessons in, you can chase three of them, you can play music on a piezo, you know functions, for-loops and named constants. Today everything you've learned meets one breadboard.
Quick-fire puzzle
Imagine a real doorbell at a house in Petaling Jaya. When the visitor presses the button, two things happen at once:
- a chime sounds (so people in the kitchen hear it),
- a small light flashes (so people watching TV with the volume up see it).
- You can already make sound (L01-14) and make lights flash (L01-10). What is the new skill today's lesson asks you to learn?
- Both the LEDs and the buzzer return current to GND. On the breadboard, what physical part of the board lets four components share one wire back to the Arduino's
GNDpin? - Today's doorbell will ring continuously on a loop, because you don't know how to read a button yet. In which upcoming lesson do you think buttons get introduced?
Reveal the answer
- The new skill is combining what you already know onto one breadboard at the same time, with one sketch that talks to all of them. No new built-in functions; no new components beyond what you've already wired. The win is integration.
- The breadboard's − rail. You met it as a "GND bus" in L01-10. Today four wires drop into it instead of three.
- L01-16 — Push Buttons & digitalRead. Once you can read a button, you'll come back to this circuit in L01-22 (the Simple Burglar Alarm project) and add the press-to-trigger behaviour. Today: ring on a loop.
New Concept 20 min
The big idea — multiple components, one breadboard, one sketch
So far your circuits have had one or three of one kind of component. Today's circuit has two kinds on the same board:
- Three LEDs (red on
D9, yellow onD10, green onD11) — each with its own 220 Ω resistor, exactly as in L01-10. - One piezo buzzer on
D8— no resistor, exactly as in L01-14, but moved to the right end of the breadboard so it doesn't share any column tie strip with the LED modules.
All four components return their current to GND through the breadboard's − rail. The Arduino sees one shared GND wire; the rail does the gathering.
Wiring map — all four components in one table
| Component | Signal pin → row A | Resistor / body | Component legs | GND return |
|---|---|---|---|---|
| Red LED | D9 → A1 | 220 Ω, row D, D1–D6 | cathode B5, anode B6 | C5 → − rail |
| Yellow LED | D10 → A11 | 220 Ω, row D, D11–D16 | cathode B15, anode B16 | C15 → − rail |
| Green LED | D11 → A21 | 220 Ω, row D, D21–D26 | cathode B25, anode B26 | C25 → − rail |
| Piezo buzzer | D8 → A28 | (no resistor — piezo is high-impedance) | signal B28, GND B29 | C29 → − rail |
| Shared: | − rail → Arduino GND | |||
Sketch structure — four constants, two helpers, one loop()
Today's sketch reuses every code idea from Cluster B:
- Four named pin constants at the top (L01-09).
- Five named note constants for the melody (L01-14).
- Two helper functions:
flash(pin, durationMs)from L01-12 for the LEDs,beep(frequencyHz, durationMs)for the buzzer. setup()with fourpinModecalls (or aforloop, L01-11, if you want to be tidy).loop()alternates a beep and a flash, building a one-line-per-event "score" you can read top-to-bottom.
Why it matters
Every project from L01-22 (Burglar Alarm) through L01-34 (Mood Lamp + Theme Tune) follows today's pattern:
- Wire each output component independently to its own pin.
- Share GND through the − rail.
- Name every pin and every constant at the top of the sketch.
- Write a helper function for each kind of output (flashing, beeping, fading).
- Compose the project's behaviour as a sequence of helper-function calls in
loop().
Today you do this for the first time. From now on, it's muscle memory.
Worked Example 20 min
Goal: build the combined breadboard, then write a sketch that rings the doorbell — three LED flashes in sequence followed by a 3-note descending melody — every 4 seconds.
Step 1 — the wiring
Re-plug the three LEDs and their resistors exactly as in L01-10 (cols 1–6, 11–16, 21–26). Then move the buzzer from L01-14 to the right end of the breadboard, cols 28–29.
Step 2 — the same circuit as a schematic
Four branches, one merge bar, one ground. The three LED branches each carry a resistor and an LED in series; the buzzer's branch carries just the piezo.
Step 3 — the doorbell sketch
Open a new sketch and call it musical-doorbell. Type the following from the top down — globals, then helpers, then setup(), then loop().
// Pin assignments — same as L01-10 (LEDs) + L01-14 (buzzer)
const int RED_PIN = 9;
const int YELLOW_PIN = 10;
const int GREEN_PIN = 11;
const int BUZZER_PIN = 8;
// Musical notes used in the doorbell jingle
const int NOTE_G4 = 392;
const int NOTE_E4 = 330;
const int NOTE_C4 = 262;// One quick flash of an LED — same helper from L01-12.
void flash(int pin, int durationMs) {
digitalWrite(pin, HIGH);
delay(durationMs);
digitalWrite(pin, LOW);
}
// One musical note on the buzzer — same helper from L01-14.
void beep(int frequencyHz, int durationMs) {
tone(BUZZER_PIN, frequencyHz, durationMs);
delay(durationMs + 50);
}void setup() {
pinMode(RED_PIN, OUTPUT);
pinMode(YELLOW_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
flash(RED_PIN, 200);
flash(YELLOW_PIN, 200);
flash(GREEN_PIN, 200);
beep(NOTE_G4, 300);
beep(NOTE_E4, 300);
beep(NOTE_C4, 500);
delay(3000);
}Step 4 — upload and watch (and listen)
Click Upload. Every 4 seconds your circuit should:
- Flash red, then yellow, then green — about 600 ms total.
- Play a descending G–E–C melody on the buzzer — about 1.1 seconds.
- Pause for 3 seconds.
- Repeat.
If the LEDs flash but the buzzer is silent, check that the piezo is plugged at cols 28–29 (not cols 12–13 like in L01-14). If the buzzer plays but a particular LED doesn't flash, check that LED's polarity and resistor first.
Step 5 — read the loop() as a script
Look back at your loop() body. Seven lines. Each line names what happens, not how. That's the gift of helper functions: you read the sketch like a doorbell instruction sheet rather than like assembly code.
Try It Yourself — extend the project 20 min
Goal: Change the melody. Pick three different notes from the L01-14 frequency table and use them instead of G–E–C. Predict whether your new melody will sound "ascending", "descending" or "wavy" before you upload.
Questions:
- What three notes did you pick, and in what order? ____
- Did the doorbell sound friendlier, scarier or more urgent than the original? Why? (Hint: high-pitched notes often feel urgent; descending sequences often feel "complete".) ____
Goal: Make the LEDs light up with each note instead of flashing first and beeping after. Red glows during the first note, yellow during the second, green during the third — synchronised light and sound.
You'll need a new helper that turns one LED on, beeps, and turns the LED off again:
void noteWithLight(int ledPin, int frequencyHz, int durationMs) {
digitalWrite(ledPin, HIGH);
tone(BUZZER_PIN, frequencyHz, durationMs);
delay(durationMs);
digitalWrite(ledPin, LOW);
delay(50);
}Then in loop() use it three times:
void loop() {
noteWithLight(RED_PIN, NOTE_G4, 300);
noteWithLight(YELLOW_PIN, NOTE_E4, 300);
noteWithLight(GREEN_PIN, NOTE_C4, 500);
delay(3000);
}Questions:
- Notice how
noteWithLighthides the synchronisation fromloop(). Where in this code does the syncing actually happen, and why? ____ - What would happen if you removed the
delay(durationMs)line from insidenoteWithLight? Trace it on paper before testing. ____
Goal: Make the doorbell ring once when the board starts, then go silent forever. (Real doorbells don't ring every 4 seconds — they ring once per press.) For today we don't have a button, so we simulate "once per press" by moving the entire doorbell logic into setup().
void setup() {
pinMode(RED_PIN, OUTPUT);
pinMode(YELLOW_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
flash(RED_PIN, 200);
flash(YELLOW_PIN, 200);
flash(GREEN_PIN, 200);
beep(NOTE_G4, 300);
beep(NOTE_E4, 300);
beep(NOTE_C4, 500);
}
void loop() {
}Questions:
- Why does this sketch ring only once instead of forever? Trace the lifecycle from L01-03 in your head. ____
- How would you re-ring the doorbell without re-uploading? (Hint: there's a tiny black button on the Arduino UNO itself.) ____
- This is a placeholder for "ring once when something happens". What will that "something" be in L01-22? ____
Mini-Challenge — add a feature 15 min
"Long press" mode: louder, longer, brighter
Some doorbells have an angry mode for impatient visitors — louder, faster, with the lights actually flashing with the chimes instead of before them. Build it.
Your task:
- Pick three notes higher than the original G–E–C (say, C5 = 523, E5 = 659, G5 = 784). Higher notes are more attention-grabbing.
- Use the
noteWithLighthelper from the 🟡 task so every note arrives with a matching LED flash. - Play the three-note sequence three times in quick succession (six rapid LED+beep pairs) before the long pause.
- Cut the pause from 3 seconds down to 1 second — the doorbell rings more often.
It works if:
- Every beep happens with an LED on, never an LED off.
- The notes are noticeably higher than the original doorbell — feels like a smoke alarm rather than a wedding bell.
- The whole cycle (three repetitions + 1-second pause) takes under 5 seconds.
Reveal one valid sketch
// Long-press doorbell mode — higher, faster, with sync LED.
const int RED_PIN = 9;
const int YELLOW_PIN = 10;
const int GREEN_PIN = 11;
const int BUZZER_PIN = 8;
const int NOTE_C5 = 523;
const int NOTE_E5 = 659;
const int NOTE_G5 = 784;
void noteWithLight(int ledPin, int frequencyHz, int durationMs) {
digitalWrite(ledPin, HIGH);
tone(BUZZER_PIN, frequencyHz, durationMs);
delay(durationMs);
digitalWrite(ledPin, LOW);
}
void ringOnce() {
noteWithLight(RED_PIN, NOTE_C5, 150);
noteWithLight(YELLOW_PIN, NOTE_E5, 150);
noteWithLight(GREEN_PIN, NOTE_G5, 150);
}
void setup() {
pinMode(RED_PIN, OUTPUT);
pinMode(YELLOW_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
ringOnce();
ringOnce();
ringOnce();
delay(1000);
}Look at the layering: loop() only knows about ringOnce(); ringOnce() only knows about noteWithLight(); noteWithLight() only knows about digitalWrite(), tone() and delay(). Three layers, each shorter than 10 lines. This is exactly the pattern from L01-12's "functions all the way down" callout — only now it's driving a real multi-component project, not just one LED.
Recap 5 min
To combine output components on one breadboard: give each its own signal pin and (if needed) its own resistor; share a single GND return through the − rail. To control them from one sketch: name every pin, write a tiny helper for each kind of output (flashing for LEDs, beeping for buzzers), then compose the behaviour in loop() as a sequence of helper calls. Today's project is the template for every Cluster B–onwards build.
- Multi-component output device
- A single breadboard circuit that uses two or more different kinds of output (LED + buzzer here; later LED + buzzer + motor + display) to produce a coordinated effect.
- GND bus
- The breadboard's − rail acting as a shared return path for many components — so that the Arduino sees only one GND wire instead of one per component. First introduced in L01-07's Mini-Challenge; first required in L01-10; first used for four components today.
- Helper-per-kind
- The pattern of writing one helper function per kind of output (
flashfor LEDs,beepfor buzzers), soloop()stays readable as a sequence of high-level actions. - Project sketch
- A sketch whose
loop()body reads like a script of human-readable steps, because every detail has been hidden inside a helper. The opposite of a "wall of digitalWrite calls". - Layering
- The technique of building bigger helpers out of smaller ones —
ringOnce()callsnoteWithLight()which callstone()anddigitalWrite(). Three layers, each understandable on its own.
Homework 5 min
Make it yours. Pick a melody you actually like — the first phrase of your school song, the opening of Negaraku, the first four notes of a video game theme — and re-program the doorbell to play it. Light the LEDs in time with the notes.
- Write out the melody in note names on paper first (e.g. "C, C, G, G, A, A, G"). Don't start with code.
- Look up the frequency of each note (the L01-14 table covers C4–C5; for higher notes, double the frequency to jump up an octave: C5 = 523, C6 = 1046).
- Add a
const int NOTE_XXfor every note you use, at the top of your sketch. - Compose the
loop()body as a sequence ofnoteWithLight()calls — alternating between red, yellow and green LEDs so each note has a flash partner.
Also: a design reflection on paper.
- If you wanted to add a fourth LED (say a blue one on pin 12) to your doorbell, name three places in the sketch you would need to edit, in order. ____
- Today your
loop()body is around 7 lines. If you removed the helper functions and inlined everydigitalWrite,toneanddelayback intoloop(), roughly how many lines would it become? ____ (Hint: eachflashcall expands to 3 lines; eachbeepto 2 lines.)
Bring back next class:
- The saved
.inofile (call itdoorbell-your-name). - A 15–20 second phone video with sound on showing your melody.
- The two answers from the design reflection on a notebook page.
Heads up for next class: in L01-16 "Push Buttons & digitalRead" you'll finally meet the missing piece — the button. The class after that, in L01-22, this doorbell circuit returns and gets its long-promised press-to-ring behaviour. Keep your kit assembled.