Source: https://mokxi.com/learn/arduino-tone-melody

Learn

# An Arduino melody with tone(): a song on a piezo

Beginner

Written by the Mokxi team

Start building free Open the editor

Or see every lesson.

- 455 parts on the bench
- 43 boards running now
- 1.00x real time, on every board

Click to open it in the editor

Ode to Joy on a piezo on pin 8, with a lamp on pin 13 for every note, on a simulated ATmega328P.

A passive piezo and two lines of code are enough to play a tune on an Arduino. tone() makes a note, noTone() stops it, and a list of notes and lengths turns that into a song. This page builds one from scratch: where the numbers for the notes come from, how to keep time, and why each note needs a short silence after it.

The circuit above is an Uno playing the opening of Beethoven’s “Ode to Joy” on a piezo on pin 8, with a lamp on pin 13 that lights for every note. It runs in your browser on the sketch below. The serial monitor prints each pitch as it plays, and the simulated piezo measures the frequency it is really given, so you can check every note.

## What you need

- An Arduino Uno
- A passive piezo buzzer (not an active one)
- One LED and a 220 ohm resistor
- A breadboard and jumper wires

## Wiring

Part and pin | Goes to | Note

Piezo, one leg | Pin 8 | Either leg; a piezo has no polarity

Piezo, other leg | GND |

LED anode, through 220 ohm | Pin 13 | The lamp that lights on each note

LED cathode | GND |

## A note is a frequency

Every musical note is a vibration at a set number of times a second. The A above middle C is 440 hertz, and each step up the piano is about 6 percent higher, so an octave up doubles it. Middle C is 262 Hz, the E above it is 330 and the G is 392. tone(8, 330) makes pin 8 switch on and off 330 times a second, and the piezo turns that into an E.

tone() starts the note and returns at once. The note keeps playing in the background, from one of the Uno’s hardware timers, until you call noTone() or start another note. So the sketch decides how long a note lasts with its own delay().

The timer can only divide the Uno’s 16 MHz clock in whole steps, so most notes come out a hair off. Run the circuit and the piezo measures 330.7 Hz for the 330 Hz E. Nobody can hear that difference.

## The sketch, step by step

The tune is two lists of the same length. NOTES holds the pitch of each note in hertz, and BEATS holds how long each one lasts. The lengths are counted in half beats, so 2 is one beat, 3 is a beat and a half and 4 is two beats. That keeps them whole numbers.

loop() walks both lists together. For each note it prints the pitch, lights the lamp, starts the tone, waits for the note’s length minus 30 milliseconds, then stops the tone and waits out those 30 milliseconds in silence. After the last note it says "again in two seconds" and starts over.

TEMPO_MS is the length of half a beat, 200 milliseconds here, so one beat is 400 ms: 150 beats a minute. Make it smaller and the whole tune speeds up, with no other change.

The melody sketch, trimmed

## Why each note needs a gap

The tune starts with two E’s in a row. Play them back to back with no gap and you hear one long E, because the pin never stops switching. The 30 milliseconds of silence after every note is what makes two notes of the same pitch sound like two. It is also why the lamp blinks off between them.

Arduino’s own toneMelody example does the same thing another way: it calls tone(pin, note, duration) and then waits about 30 percent longer than the note. Either way works. What matters is that the silence is there.

## Write your own song

You do not have to look up frequencies. #include "pitches.h" gives you names for every note from NOTE_B0 (31 Hz) to NOTE_DS8 (4978 Hz), the same numbers the Arduino IDE’s example uses, so NOTE_A4 is 440. Mokxi has the file built in, so the include works without adding a tab.

Then write the tune as two lists: the notes, and the lengths. Use 0 for a rest, and play a rest with noTone() and a delay instead of a tone. Copy a melody from sheet music one note at a time, check the count of both lists is the same, and press Run.

In the editor, try changing TEMPO_MS to 150 for a faster tune, or GAP_MS to 0 to hear the two E’s run together. Add 12 notes to each list and the loop plays them, because COUNT is worked out from the list.

## Common mistakes

Using an active buzzer. It has its own oscillator and plays one pitch whatever you send it. A tune needs a passive piezo or a small speaker.

No gap between notes, so repeated notes blur into one.

Lists of different lengths. If BEATS is shorter than NOTES, the loop reads past its end and plays nonsense lengths. Count them, or let the compiler count one of them as this sketch does.

PWM stopping on pins 3 and 11. On an Uno, tone() uses timer 2, the same timer that drives PWM on those two pins, so analogWrite() on them stops working while a note plays. Use pins 5, 6, 9 or 10 for anything you fade.

Trying to play two notes at once. tone() works on one pin at a time. Start a note on a second pin and the first one stops.

A loose ground. With the piezo’s second leg pulled out, the piezo here goes silent, as a real one does.

## Questions

How do I play a song on an Arduino buzzer?

Use a passive piezo, put the song’s notes in one array and their lengths in another, and loop through them calling tone(pin, note), delay(length), then noTone(pin) and a short delay. The sketch on this page does exactly that.

What is the difference between tone(pin, freq) and tone(pin, freq, duration)?

Both return at once. With a duration, the note stops by itself after that many milliseconds, but the sketch does not wait for it, so you still need a delay before the next note.

Where do I get pitches.h?

In the Arduino IDE it is a tab in the toneMelody example (File, Examples, 02.Digital). In Mokxi it is built in: #include "pitches.h" works on its own.

Can tone() make a sound on any pin?

Yes, any digital pin on an Uno. It uses timer 2 whichever pin you pick, which is why PWM on pins 3 and 11 pauses while it plays.

Related

## Keep going

Arduino Buzzer and Piezo: Beeps, Notes, Metronome Arduino Blink Without Delay: Two LEDs, Two Rates PWM: Faking an Analog Voltage on a Digital Pin Arduino Christmas Lights to Build in Your Browser Arduino MPR121: 12-Key Capacitive Touch Piano The buzzer and piezo, pin by pin How the passive piezo is modeled A buzzer on an Arduino Uno The project page, with the full sketch Beginner

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building free Open the editor
