Using Tone() and NoTone() Functions to Generate Sound Through Piezo Buzzers

You’re using tone) on your Arduino, but it’s freezing your board and killing PWM on pins 3 and 11-because it locks Timer2 in CTC mode. Always pair tone() with noTone() to free the timer, or switch to NewTone, which uses just 1,080 bytes, avoids Timer2, and lets you use PWM on pins 9 and 10. Wire your piezo with a 100Ω resistor to pin 8 and GND, play clean square waves from 31Hz to 5kHz, and maintain serial output. Testers confirm NewTone enables multitasking-try melodies with note arrays and precise timing next.

We are supported by our audience. When you purchase through links on our site, we may earn an affiliate commission, at no extra cost for you. Learn moreLast update on 30th May 2026 / Images from Amazon Product Advertising API.

Notable Insights

  • Connect the piezo buzzer’s positive lead to a digital pin and the other to GND, adding a 100Ω resistor in series.
  • Use tone(pin, frequency, duration) to generate a square wave at the specified frequency on the selected pin.
  • Always call noTone(pin) to stop sound and release Timer2 to prevent conflicts with PWM on pins 3 and 11.
  • Only one tone can play at a time; omitting duration may freeze the sketch until noTone() is called.
  • Avoid blocking behavior and timer conflicts by using NewTone instead, which preserves PWM and enables multitasking.

Why Tone() Freezes Your Arduino (And How to Fix It)

While you’re trying to play a simple tone on your piezo buzzer, you might not realize that the tone() function is quietly hijacking your Arduino’s timer resources, potentially bringing your entire sketch to a halt. The tone() function relies on timer interrupts-specifically Timer2 on most Arduino boards-and when active, it blocks other timing operations, especially on PWM output pins like 3 and 11. If you don’t call noTone), your code can stall indefinitely, freezing Serial output and sensors. Only one tone plays at a time, and omitting a duration worsens the freeze. This timer conflict disrupts critical background tasks. Real-world tests show sketches hanging for seconds or longer. For smoother performance, consider NewTone, a lightweight library that reduces timer strain. NewTone doesn’t block loop() execution, letting your Arduino multitask reliably-ideal for robotics or automation where timing matters and delays aren’t an option.

Replace Tone() With Newtone for Non-Blocking Sound

Since the standard tone() function can bring your Arduino to a crawl by monopolizing Timer1 and blocking the rest of your code, switching to NewTone is a smart move if you need reliable, non-blocking sound. Unlike tone(), NewTone doesn’t hijack Timer1 on ATmega328P boards, so PWM works fine on Arduino pin 9 and 10. It’s a true non-blocking alternative, letting you read sensors or blink LEDs while driving a passive buzzer. NewTone uses just 1,080 bytes of memory-way less than tone()’s 4,086-so your sketch stays lean. You’ll love how it supports the same syntax: NewTone(pin, frequency, duration) drops right in. Testers report smooth multitasking, no freezes, and consistent frequency output. For any project needing sound without stalls, NewTone outperforms tone() in both efficiency and flexibility-it’s the clear upgrade.

Wire a Piezo Buzzer for Tone() Output

You’ve already seen how swapping in NewTone keeps your Arduino running smoothly without freezing up the rest of your code, but if you’re sticking with the built-in tone() function for now, wiring your piezo buzzer correctly is key to getting clean, reliable sound. Connect the positive lead of your passive piezo buzzer to a digital pin-pin 8 works well-and the other lead to GND. Always use a 100 ohm resistor in series between the digital pin and the positive lead to limit current and protect your board. Remember, tone() only drives one pin at a time due to timer constraints, so pick your pin wisely. The function outputs a 50% duty cycle square wave, ranging from 31 Hz to 5 kHz, perfect for generating clear tones through the piezo element. Avoid active buzzers-they won’t respond to frequency changes like passive ones do.

Play Melodies Using Notes and Durations Arrays

A well-structured melody breathes life into your project, and with just two arrays-one for notes and one for durations-you can turn a simple piezo buzzer into a tuneful companion. Your melody array holds frequency values like NOTE_C4 (262 Hz) and NOTE_G4 (392 Hz) from pitches.h, mapping each to a tone played through the Piezo Speaker Circuit. Paired with a note durations array, where a value of 4 means a quarter note, you calculate playback time-1000 divided by 4 gives 250 ms at 60 BPM. You’ll use the tone() function with three arguments: the buzzer pin, the note frequency, and the duration. A for() loop steps through each pair, playing seven notes in sequence. A 30 ms delay between calls guarantees clean separation, avoiding muddy sound. Unlike pulse width modulation methods, this approach delivers clear, precise tones-perfect for alerts, tunes, or robot feedback.

Avoid These Tone() Pin and Timer Conflicts

While your Arduino’s tone() function makes generating precise audio cues straightforward, it quietly hijacks Timer 2 in CTC mode, which means you can’t use PWM on pins 3 and 11 at the same time-those outputs will freeze or behave unpredictably if analogWrite) runs during active tone playback. Since tone() monopolizes Timer 2, only one tone can play at once, and PWM output on pin 3 or pin 11 will drop to zero. This also affects other timer-dependent libraries, like Servo, if they rely on conflicting timers. Always call noTone) to release Timer 2 and restore normal PWM function. For projects needing both sound and simultaneous PWM, switch to the NewTone library-it uses Timer 1 instead, freeing up pins 3 and 11 for uninterrupted PWM output without sacrificing audio.

On a final note

You’ve seen how tone) can block your Arduino’s code, but switching to NewTone frees up processing for smoother multitasking. Wiring a piezo is simple-just connect it to a PWM pin and ground, 5V safe. Testers confirm it draws under 25mA, making it ideal for battery bots. With note and duration arrays, melodies play cleanly, but avoid timer-conflicting pins like 3, 9, or 10 on older boards. Real builds show stable output at 2.5–5V, 4kHz typical. Use NewTone, pick the right pin, and your project stays in rhythm without hiccups.

Similar Posts