Learning Goals 5 min
By the end of this lesson you will be able to:
- Explain what a piezo buzzer is physically doing when it makes a sound — vibrating at a specific number of times per second, measured in hertz (Hz) — and that the toggling of the Arduino pin is what drives that vibration.
- Use
tone(pin, freq),tone(pin, freq, duration)andnoTone(pin)to play any frequency from about 31 Hz up to the limit of human hearing, and stop it again on command. - Read the standard musical-note frequency table (middle C = 262 Hz, A4 = 440 Hz, …) and use it to play recognisable single notes and short scales — and understand that every octave up doubles the frequency.
Warm-Up 10 min
L01-14 gave you tone() as a magic incantation: "pick a number, get a beep." L01-31 just showed that analogWrite is really fast on/off switching. Today the same reveal happens for sound — tone() is just fast on/off switching too, only at audio speeds, driving a tiny disc that pushes air at your ear.
Quick-fire puzzle
Pluck a guitar string and watch it closely. It blurs into a fuzzy shape because it's vibrating back and forth so fast your eye can't follow. The thicker, lower string blurs less — its motion is slower and bigger. The thin top string blurs more — its motion is faster and smaller.
- If a low-pitched string moves slowly back and forth, and a high-pitched string moves quickly, what number describes a sound's pitch?
- A piezo buzzer has no string — it's a tiny stiff disc inside a plastic case. What would make it vibrate, given that an Arduino can only output HIGH or LOW on a digital pin?
- To make the disc vibrate 440 times per second (the pitch of an orchestra's tuning A), how many times per second do you think your sketch needs to toggle the pin?
Reveal the answer
- The pitch of a sound is the number of vibrations per second. This number has a name: hertz, written Hz. A low note like a bass guitar's open E is around 82 Hz; a high violin note can be over 2,000 Hz. Higher number = higher pitch.
- The piezo disc has two faces and a wire to each. Apply HIGH to one wire and the disc flexes one way; switch to LOW and it relaxes (or flexes the other way). Toggle the wire fast enough and the disc oscillates — and oscillating discs push air, which is what your ear interprets as sound.
- 880 times per second — twice the frequency. Each "vibration" needs one trip out and one trip back, which means two pin toggles. That's it. The
tone()function in Arduino does exactly this for you, perfectly timed, while your sketch is free to do other things.
New Concept — frequency, hertz, and the note table 15 min
The big idea — sound is fast wiggling
Every sound you have ever heard is something pushing on the air, fast. A drum skin pushes air. A guitar string pushes air. Your vocal cords push air. A loudspeaker cone pushes air. A piezo disc, when you toggle its wire, pushes air. The number of pushes per second is the sound's frequency; the unit for that number is the hertz (Hz), named after Heinrich Hertz, the German physicist who proved radio waves exist.
Humans typically hear from about 20 Hz at the very deep bass end to about 20,000 Hz at the squeaky-high end. Below 20 Hz you feel it as a rumble more than a sound; above 20,000 Hz only dogs and bats hear it. The Arduino's tone() function works comfortably from about 31 Hz up to several kilohertz — covering essentially all human hearing.
From PWM to tone() — almost the same trick
L01-31 taught you that analogWrite toggles a pin about 490 times a second to fake brightness. tone() is the same idea, but at audio frequencies — anything from tens to thousands of toggles per second — driving the buzzer at whatever frequency you asked for. The differences:
- You pick the frequency directly, not a duty cycle.
tone(pin, 440)means "toggle this pin 880 times per second, giving 440 complete cycles". - It works on any digital pin, not just the six ~ pins.
tonedoesn't use the PWM hardware; it uses one of the chip's general timers. - It runs in the background. After you call
tone, the chip keeps toggling on its own while yourloop()runs. Nodelayneeded during the note — only after, if you want the note to actually last.
The three calls — same as L01-14, with one new wrinkle
tone(BUZZER_PIN, 440); // start 440 Hz; keeps playing until noTone or another tone
tone(BUZZER_PIN, 440, 500); // 440 Hz for 500 ms, then auto-stop
noTone(BUZZER_PIN); // silence — immediately stop whatever's playingThe two-argument and three-argument forms are exactly the same except for the auto-stop. Use the three-argument form for known-duration notes (most music); use the two-argument form for sirens or alarms that should keep going until you tell them to stop.
The musical-note frequencies — what counts as "a note"
Out of all the millions of possible frequencies, Western music picks out a set of specific ones and gives them letter names. The middle row of a piano — called the 4th octave, hence the digit "4" in the names — looks like this:
| Note | Frequency (Hz) | What it sounds like |
|---|---|---|
| C4 (middle C) | 262 | The note at the centre of the piano |
| D4 | 294 | Slightly higher |
| E4 | 330 | Higher again |
| F4 | 349 | Half-step up from E |
| G4 | 392 | Higher |
| A4 | 440 | The world-standard tuning pitch (every orchestra tunes to this) |
| B4 | 494 | One step below high C |
| C5 (high C) | 523 | One octave above middle C — exactly double its frequency |
The octave rule — frequency doubles
Notice C4 = 262 and C5 = 523 — very close to twice 262. That's not a coincidence: going up one octave doubles the frequency. A6 is 880 (double A4's 440); A3 is 220 (half A4); A2 is 110. This doubling-per-octave rule is fundamental to how music works on every instrument ever built. So if you only memorise one note frequency, memorise A4 = 440 Hz — you can derive any other A by repeated doubling or halving.
Approximate, not exact
The numbers in the table are rounded to the nearest integer hertz. The actual "perfect" pitches are slightly more precise (A4 is exactly 440.000…, the rest involve irrational numbers from the twelfth root of 2). Your ear can't tell the difference between 262 Hz and 261.626 Hz. Use the rounded numbers — they're more than good enough for a buzzer.
Why it matters
The same "frequency = pitch" rule governs every speaker, microphone, telephone, radio transmitter, sonar pulse, ultrasound scanner and Bluetooth headphone on earth. Picking a frequency to play, generating it, and stopping it are the three primitives of every audio system. Today you do them on the cheapest possible speaker; the next forty years of audio engineering builds out from this exact foundation.
Worked Example — play a note, then a scale 20 min
Same wiring as L01-14: one piezo buzzer on D8, with both leads landing in adjacent columns on the breadboard and one lead jumpered to GND. No new parts. The only thing that changes today is what you ask the chip to play.
Step 1 — Play a single A4
The simplest possible audio sketch: one note, played for one second, then a pause, then repeated.
// Single A4 — concert-pitch tuning note
const int BUZZER_PIN = 8;
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
tone(BUZZER_PIN, 440, 1000); // A4 for 1 second
delay(1500); // 1 s note + 0.5 s silence
}Upload. You hear the standard orchestra tuning note — a clear, steady tone, like the first note before a concert. Note the delay(1500): the tone call returns immediately because the chip handles the note in the background, so without the delay your loop() would call tone a million times per second, restarting the note instantly each time. The delay is what lets the note play.
Step 2 — A scale, one note at a time
Now play the whole C-major scale, one note after another, with a short pause between. Eight notes, eight calls. Each note plays for 300 ms with a 50 ms gap (which gives a slight "separated" feel; pros call this staccato).
// C-major scale — C4 to C5
const int BUZZER_PIN = 8;
void playNote(int freq) {
tone(BUZZER_PIN, freq, 300);
delay(350);
}
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
playNote(262); // C4
playNote(294); // D4
playNote(330); // E4
playNote(349); // F4
playNote(392); // G4
playNote(440); // A4
playNote(494); // B4
playNote(523); // C5
delay(1000); // pause before repeating
}Upload. You should recognise this immediately — it's the "do re mi fa sol la ti do" scale every music class teaches. The playNote helper hides the duration-plus-gap pattern so each line of loop() reads as just one note's frequency. Each call's delay(350) covers the 300 ms tone plus the 50 ms gap — the tone is already auto-stopping at 300 ms, the extra 50 ms is the silent gap before the next note.
Step 3 — Hear the octave-doubling rule for yourself
Replace the body of loop() with this — four "A" notes, each an octave higher than the last:
void loop() {
playNote(110); // A2 — low A
playNote(220); // A3 — twice the frequency
playNote(440); // A4 — twice again (concert pitch)
playNote(880); // A5 — twice again (high A)
delay(1500);
}Upload. You hear four notes that all sound like "the same note" — they have the same character — but each is higher than the last. That's the perceptual magic of the octave: any two notes whose frequencies are in a 2:1 ratio sound to your brain like "the same letter". Singers and instruments rely on this constantly: a man and a woman singing "Happy Birthday" together are usually an octave apart, and it sounds like one melody, not two.
You may also notice that A2 (110 Hz) is much quieter on the piezo than A5 (880 Hz). That's the piezo's resonance: it's a tiny stiff disc that physically prefers to vibrate fast. Low notes are softer; high notes ring out. This is the buzzer's nature, not a bug.
Trace one note on paper
For a single call tone(BUZZER_PIN, 262, 500), fill in what happens at each moment:
| Time | What the chip is doing | What your loop() is doing |
|---|---|---|
| t = 0 ms | start toggling pin at 524 Hz (twice 262) | returns from tone(); free to do other work |
| t = 1 ms | still toggling — pin has flipped ~__ times so far | ____ (whatever you wrote next) |
| t = 250 ms | still toggling — about ____ full cycles done | ____ |
| t = 500 ms | auto-stops toggling — pin goes idle | ____ |
The point of the table: the tone runs independently. Your code does not have to babysit it. That's why the delay after a tone call usually matches the tone's duration — to keep your sketch quiet while the chip is playing in the background.
Try It Yourself — three audio sketches 20 min
Goal: A police siren. Alternate between 800 Hz and 1200 Hz, with each note lasting 200 ms, forever. No serial.
Plan: two tone(BUZZER_PIN, freq, 200) calls in loop() separated by delay(200). Use the L01-14 wiring.
const int BUZZER_PIN = 8;
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
tone(BUZZER_PIN, 800, 200);
delay(200);
tone(BUZZER_PIN, 1200, 200);
delay(200);
}Questions:
- What's the ratio between the two frequencies? Is it close to an octave, a half-octave, or something else? ____ (Hint: an octave is exactly 2:1.)
- If you replace both
200ms with50ms, what does the siren turn into — and why does it sound more annoying? ____ - Change 1200 to
880. Now the two notes are A4 and an A-flavoured higher note. Is the result more like a siren or more like a doorbell? ____
Goal: A frequency sweep. Slowly climb from 100 Hz up to 2000 Hz and back down, like a science-fiction sound effect. Use a for loop walking frequency in 20-Hz steps with a 10 ms delay between each.
const int BUZZER_PIN = 8;
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
for (int f = 100; f <= 2000; f = f + 20) {
tone(BUZZER_PIN, f);
delay(10);
}
for (int f = 2000; f >= 100; f = f - 20) {
tone(BUZZER_PIN, f);
delay(10);
}
noTone(BUZZER_PIN);
delay(500);
}Questions:
- Notice the tone calls have no duration argument. Why does that work here but didn't in the A4 sketch? ____ (Hint: each call instantly replaces the previous one before it had a chance to end.)
- Why is
noTone(BUZZER_PIN)needed at the end ofloop()but not in the middle? ____ - The buzzer probably sounds louder during the middle of the sweep (around 2 kHz) than at the very low or very high ends. Why? ____
Goal: A digit-driven scale player. Type a digit 1–8 into the Serial Monitor; the buzzer plays the matching note of the C-major scale (1 → C4, 2 → D4, …, 8 → C5).
Plan: standard input pattern (L01-26) + switch/case (L01-28). Each digit-case calls tone with the right frequency from today's table.
const int BUZZER_PIN = 8;
void setup() {
Serial.begin(9600);
pinMode(BUZZER_PIN, OUTPUT);
Serial.println("Type 1-8 to play a scale note.");
}
void loop() {
if (Serial.available() > 0) {
char c = Serial.read();
switch (c) {
case '1': tone(BUZZER_PIN, 262, 300); break;
case '2': tone(BUZZER_PIN, 294, 300); break;
case '3': tone(BUZZER_PIN, 330, 300); break;
case '4': tone(BUZZER_PIN, 349, 300); break;
case '5': tone(BUZZER_PIN, 392, 300); break;
case '6': tone(BUZZER_PIN, 440, 300); break;
case '7': tone(BUZZER_PIN, 494, 300); break;
case '8': tone(BUZZER_PIN, 523, 300); break;
}
}
}Questions:
- Type
1234567812345678as one Send. Does the Arduino play all 16 notes, or do later ones get cut short? Explain in terms oftone's "replace immediately" behaviour. ____ - Eight near-identical case branches are a lot of typing. What syllabus topic from a later lesson do you think might cleanly compress this? ____ (Hint: L01-33 is called "Note Arrays".)
- The Mini-Challenge below uses note letters instead of digits. Why might that be a slightly worse idea here? ____ (Hint: which letters are easy to mistype on a keyboard?)
Mini-Challenge — Twinkle Twinkle 10 min
"Play the first line of the song everyone knows"
Build a sketch that plays the opening of Twinkle Twinkle Little Star when the Arduino is powered on, then waits forever. The first line uses six different pitches in this pattern (each "x x" pair is the same note repeated):
| Lyric | Note | Frequency (Hz) |
|---|---|---|
| "Twin-" | C4 | 262 |
| "-kle," | C4 | 262 |
| "Twin-" | G4 | 392 |
| "-kle," | G4 | 392 |
| "lit-" | A4 | 440 |
| "-tle" | A4 | 440 |
| "star" | G4 (held) | 392 — twice as long |
Your task:
- Reuse the
playNote(freq)helper from the worked example, but extend it toplayNote(freq, duration)so the last note can hold twice as long. - Each regular note: 400 ms duration, 50 ms gap (i.e.
delay(450)in the helper). The held final note: 800 ms duration, 50 ms gap. - Put the seven calls in
setup(), notloop()— the tune should play once at power-on, then the sketch sits quiet.
It works if:
- You can sing along: "Twin-kle twin-kle lit-tle staaaar". (Mouth the words; the timing should match.)
- The tune plays exactly once and then stops (no repeating, no infinite loop).
- The final "star" is clearly twice as long as each of the earlier notes.
Reveal one valid sketch
// Twinkle Twinkle Little Star — first line, one-shot
const int BUZZER_PIN = 8;
void playNote(int freq, int duration) {
tone(BUZZER_PIN, freq, duration);
delay(duration + 50);
}
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
playNote(262, 400); // Twin-
playNote(262, 400); // -kle,
playNote(392, 400); // Twin-
playNote(392, 400); // -kle,
playNote(440, 400); // lit-
playNote(440, 400); // -tle
playNote(392, 800); // staaaar (held)
}
void loop() { }The playNote helper now takes a duration, and the delay inside is always duration + 50 — so a 400 ms note really takes 450 ms total (with 50 ms silence after), and the 800 ms held note takes 850 ms. One line of setup() = one note of music, which is exactly the shape L01-33's note arrays will collapse even further. Notice we never wrote anything in loop() — once setup() returned, the sketch is done. The piezo sits silent, the Arduino draws minimal power, the sketch just waits at the empty loop() forever.
Recap 5 min
Sound is fast wiggling — and the wiggle count per second has a name (hertz) and a unit (Hz). tone(pin, freq, duration) tells the chip to toggle a pin at freq Hz for duration ms, then auto-stop. The piezo disc tracks those toggles and pushes the air, your ear hears a pitch, and your brain calls it a note. Musical notes are specific frequencies — middle C is 262 Hz, A4 is 440 Hz — and each octave up doubles the frequency. Combine that with the for-loop and switch ideas from earlier and you can already play scales, sirens, sweeps and simple tunes.
- Frequency
- The number of complete back-and-forth cycles per second of any oscillating thing — string, speaker, piezo disc, radio wave. For sound, the frequency is the perceived pitch.
- Hertz (Hz)
- The unit of frequency: one cycle per second. Named after Heinrich Hertz. Human hearing spans roughly 20 Hz to 20,000 Hz.
tone(pin, freq)- Tells the chip to toggle
pinatfreqHz in the background, indefinitely. The sketch'sloop()is free to do other work while the tone plays. tone(pin, freq, duration)- Same as the two-argument form but auto-stops after
durationms. The form you want for music. noTone(pin)- Immediately silences whatever tone is playing on that pin. Pair with the no-duration form of
tonefor sirens and alarms. - Octave
- A musical interval where one note's frequency is exactly double another's. Two notes an octave apart share a letter name (A2, A3, A4, A5) and sound to the brain like "the same note", higher or lower.
- Concert pitch (A4 = 440 Hz)
- The world-standard tuning reference. Every orchestra in the world tunes to a 440 Hz A before performing. Worth memorising as your "anchor" frequency.
Homework 5 min
The "Happy Birthday" intro. Use today's playNote(freq, duration) helper to play the first phrase of Happy Birthday to You — the bit that ends with "to you". The notes are:
| Lyric | Note | Freq (Hz) | Duration |
|---|---|---|---|
| "Hap-" | C4 | 262 | short (300 ms) |
| "-py" | C4 | 262 | short (200 ms) |
| "birth-" | D4 | 294 | medium (500 ms) |
| "-day" | C4 | 262 | medium (500 ms) |
| "to" | F4 | 349 | medium (500 ms) |
| "you" | E4 | 330 | long (1000 ms) |
Six calls. Put them in setup() so the tune plays once at power-on, just like Twinkle Twinkle. Then the sketch waits silently.
Also: a design reflection on paper.
- If you wanted to play any song with this approach, what's the most painful thing about the current style of code? ____ (Hint: every note is two pieces of data — freq and duration — yet they're typed out one by one in code. L01-33 has a much better answer.)
- You memorised one frequency this lesson — A4 = 440 Hz. Using the octave-doubling rule, work out A0, A1, A2, A3, A4, A5, A6, A7 on paper. Which of these can your buzzer actually play, given the 31 Hz minimum? ____
- Look at any piano keyboard photo online. The middle C key is in the centre of the keyboard, slightly to the left of the brand name. Count keys (including the black ones) from middle C up to C5 — what number do you get? ____ (Hint: 12 — that's how many "semitones" are in an octave.)
- The lesson said the piezo prefers high frequencies. If you wanted to build a portable music box that plays bass-heavy songs, what kind of speaker would you use instead, and why? ____
Bring back next class:
- The saved
.inofile (call ithappy-birthday-intro). - A 10-second phone video of the tune playing on power-on (or after pressing the reset button).
- Your four written reflection answers, in your notebook.
Heads up for next class: L01-33 "Note Arrays" answers the pain point at the bottom of today's reflection. Instead of typing each note as its own line, you'll store the whole melody as a list of frequencies and a parallel list of durations, then play it back with a single for loop. Today's seven-line tune becomes one-line data.