Learn
Playing Tones on a Passive Buzzer with a Raspberry Pi 4B (PWM)
Wire a passive buzzer to a Raspberry Pi 4B GPIO pin and play a real, changing musical pitch with GPIO.PWM() — unlike an Active Buzzer, this one only sounds while your script is actively driving it.
Try this directly in the free Raspberry Pi 4B simulator — no hardware or signup required. New to the GPIO header? Start with the interactive pinout guide.
What you’ll need
- Raspberry Pi 4B
- Passive Buzzer
Step by step
- Drag Raspberry Pi 4B onto the Canvas.
- Drag the Passive Buzzer onto the Canvas — connects via drawn wires, not breadboard legs.
- Hover over its 2 pins to confirm the labels: Positive (+) and Negative (−).
- Wire it up: Positive → a GPIO pin (e.g. pin 37). Negative → a Pi GND pin.
- Go to the Code tab and write a script that plays a short rising scale:
import RPi.GPIO as GPIOimport asyncio buzzerPin = 37 GPIO.setmode(GPIO.BOARD)GPIO.setup(buzzerPin, GPIO.OUT) pwm = GPIO.PWM(buzzerPin, 262) # start at middle C (262Hz)pwm.start(50) # 50% duty cycle — a passive buzzer needs this to make any sound at all notes = [262, 294, 330, 349, 392] # C, D, E, F, G for note in notes: print(f"Playing {note}Hz") pwm.ChangeFrequency(note) await asyncio.sleep(0.4) pwm.stop()GPIO.cleanup()- Click Start.
What “working correctly” looks like
- You should hear 5 distinct, rising tones, one every 0.4 seconds, matching the printed frequency in the Console each time.
- The buzzer's own note indicator stays animated continuously through the whole sequence — unlike the Active Buzzer, which only ever plays one fixed pitch, this one's pitch genuinely changes with ChangeFrequency().
If something’s wrong
- Nothing happens, not even the note indicator → a Passive Buzzer needs BOTH pwm.start(...) AND at least one ChangeFrequency() call — a bare GPIO.output(buzzerPin, GPIO.HIGH) (the Active Buzzer's own approach) produces no sound here at all, since this component has no built-in oscillator of its own.
- You hear a tone but it never changes pitch → confirm you're calling pwm.ChangeFrequency(...) inside the loop, not just once before it starts.