How Sound Works on Arduino
Your Arduino can produce sound by toggling a pin on and off very quickly. Do that thousands of times per second, and a passive buzzer connected to that pin vibrates the air at that frequency. That vibration is sound.
tone() handles all of that toggling for you. You tell it which pin, what frequency, and optionally how long. It runs in the background using a hardware timer, so your code keeps executing while the sound plays.
The Two Functions
tone()
tone(pin, frequency); // plays until you call noTone()
tone(pin, frequency, duration); // plays for duration milliseconds, then stops
| Parameter | Type | What it means | |-----------|------|---------------| | pin | int | Any digital pin connected to your buzzer | | frequency | unsigned int | Pitch in Hertz (cycles per second) | | duration | unsigned long | (Optional) How many milliseconds to play |
When you call tone() without a duration, the sound plays forever until you call noTone(). When you include a duration, it stops automatically, but tone() returns immediately. It does not wait for the sound to finish. So if you call tone(pin, 440, 500) and immediately call tone(pin, 880, 500), the second call overwrites the first and you never hear the 440 Hz tone.
noTone()
noTone(pin);
Stops the tone on that pin. Always call this when you are done making sound, otherwise the buzzer keeps going.
Frequency Ranges
| Range | Hz | Notes | |-------|----|-------| | Human hearing | 20 to 20,000 | Full range | | Small piezo sweet spot | 500 to 5,000 | Where your kit's buzzer sounds best | | Good for melodies | 200 to 2,000 | Musical notes that are easy to tell apart | | Below 100 Hz | < 100 | Clicking, not a real tone |
Note Frequency Table
| Note | Hz | Note | Hz | |------|----|------|----| | C4 | 262 | G4 | 392 | | C#4 | 277 | G#4 | 415 | | D4 | 294 | A4 | 440 | | D#4 | 311 | A#4 | 466 | | E4 | 330 | B4 | 494 | | F4 | 349 | C5 | 523 | | F#4 | 370 | | |
A4 at 440 Hz is the universal tuning reference. Use 0 for rests (silence).
Playing a Melody
Store notes in one array and durations in another, then loop through them:
int melody[] = {262, 330, 392, 523};
int durations[] = {400, 400, 400, 800};
int numNotes = 4;
for (int i = 0; i < numNotes; i++) {
tone(buzzerPin, melody[i], durations[i]);
delay(durations[i] + 50); // note + gap between notes
}
noTone(buzzerPin);
That 50ms gap between notes is important. Without it, consecutive notes at the same pitch blend into one long tone.
tone() and PWM: The Timer2 Conflict
On the HERO board, tone() uses Timer2 internally. Timer2 also powers analogWrite() on pins 3 and 11. That means: while tone() is active, analogWrite() on pins 3 and 11 will not work correctly. Your LED will not dim smoothly and there will be no error message to tell you why.
The fix: use different PWM pins for anything that needs analogWrite() while tone() is running.
| PWM Pin | Timer | Affected by tone()? | |---------|-------|---------------------| | 3 | Timer2 | Yes | | 5 | Timer0 | No | | 6 | Timer0 | No | | 9 | Timer1 | No | | 10 | Timer1 | No | | 11 | Timer2 | Yes |
Common Mistakes
| Mistake | What Happens | Fix | |---------|-------------|-----| | Calling tone() in loop() with no delay | Restarts the tone every iteration, sounds glitchy | Call tone() once, or use a flag | | Playing two tones at once | Only the second one plays, first is silently killed | HERO only supports one tone at a time | | Forgetting noTone() | Buzzer keeps going forever | Always clean up | | Using an active buzzer | Weird warbling sound | Active buzzers have their own oscillator; use passive buzzers with tone() | | Using analogWrite on pin 3 or 11 while tone is playing | LED brightness control breaks silently | Use pins 5, 6, 9, or 10 instead |