Active and passive buzzers: making the robot beep and play notes
The difference between active and passive buzzers, how to tell which one you have, how to play notes with tone() on Arduino and PWM on the ESP32, minding the pin current, and what tone() does to pins 3 and 11 on the Nano.

The buzzer is the robot's voice. It looks like the simplest part in the kit, but there are two types that look alike on the outside and work differently, and mixing one up with the other is the number one reason for "the buzzer won't sound".
Active and passive
An active buzzer has an oscillator inside. Just apply power and it beeps, always at the same pitch, usually somewhere between 2 kHz and 3 kHz. To the program, it's like an LED: pin high, it beeps; pin low, it goes quiet.
A passive buzzer is just the vibrating element. On DC voltage, it clicks once and stays silent. To make a sound, it needs a square wave, and the frequency of that wave is the note. In exchange for the extra work, it plays melodies.
How to tell which one you have
- The definitive test: connect the buzzer to 5 V (or 3.3 V) for a moment. A continuous beep: active. Just a click: passive.
- Visual clue: many active buzzers have a sealed bottom with a sticker on top; many passive ones show the circuit board underneath. It's not a rule, just a clue.
- Polarity: the active one is polarized; the longer leg or the "+" marking goes to the pin.
In the block coding IDE, the buzzer card asks for the type. For an active buzzer, it switches the pin on and off; for a passive one, it generates the frequency.
Playing notes
Some reference frequencies (tuned to A = 440 Hz):
| Note | Frequency |
|---|---|
| C5 | 523 Hz |
| D5 | 587 Hz |
| E5 | 659 Hz |
| G5 | 784 Hz |
| A5 | 880 Hz |
For an alert, short high-pitched sounds work best: 2,000 Hz for 100 ms gets attention without being annoying. Two rising notes sound like "it worked"; two falling ones, like "error".
On the Arduino Nano
The tone(pin, frequency, duration) function generates the square wave on any pin, and noTone(pin) silences it. Two things to keep in mind:
- Only one tone at a time. While a tone() is playing on one pin, calling tone() on another pin has no effect.
- tone() uses timer 2, so it interferes with PWM (analogWrite) on pins 3 and 11 while it plays. Servos driven by the Servo library are not affected, because that library uses a different timer.
On the ESP32 with MicroPython
The ESP32's PWM does the job of tone: the frequency is the note, and a 50% duty cycle gives the square wave.
from machine import Pin, PWM
import time
buzzer = PWM(Pin(23), freq=2000, duty_u16=32768)
time.sleep_ms(100)
buzzer.duty_u16(0) # silence
Pin current
The small buzzers that come in kits draw a few tens of milliamps, close to the recommended limit for a microcontroller pin (about 20 mA on the Nano's ATmega328P). For a louder buzzer, use a transistor as a switch: the pin drives the transistor, and the transistor switches the buzzer.
On the robot arm
The arm's buzzer confirms what the operator did: a short beep when a position is recorded, two beeps at the end of the playback, a continuous tone while an object is close to the sensor. In the block coding IDE, the "Beep the buzzer" card asks for the pin, the type and the duration, and the "Play a note" card takes the note by name.