How to Use a Piezo Speaker With the Raspberry Pi to Play Sounds

Make music with the Raspberry PI!

Raspberry Pi Piezo Speaker Feature Image

Have you ever wondered how those tiny teddy bear toys make sound? Chances are, you were listening to a piezoelectric speaker. You can make your own to play sounds and music by using a piezo speaker with the Raspberry Pi!

What Is a Piezo Speaker?

Piezo speakers contain a special material called a “piezo element” that is capable of exhibiting the piezoelectric effect, a process generates an electric charge when you hit something solid.

Squeezed Vs Unsqueezed Crystal In A Piezo Element 1

Many solid things, like rocks or salt, are solid because their atoms are packed tightly together. This arrangement is called “crystal structure.”

In some materials, a crystal structures can bend or get squeezed when enough force is applied to it. This makes some atoms stay beside other atoms that they normally wouldn’t sit next to.

In piezoelectric materials or piezo elements, these atoms have opposite charges: one positive and the other negative. The moment these atoms of opposite charges get close together, they make electricity happen.

Piezo Speakers Above And Below
There are piezo elements inside these piezo speakers.

You can also do the opposite – apply an electric field on piezo elements to make crystal structures bend, changing the material’s overall shape. When using a piezo speaker, you’re making the piezo element inside contract and expand so fast that it vibrates and makes a sound.

What You Need for the Project

Using piezo speakers with the Raspberry Pi to generate sounds is as simple as making LEDs blink. You just need a few things and a different code. You won’t need a resistor.

  • Piezo speakers
  • 2 male-to-female jumper wires
  • Raspberry Pi

How to Use a Piezo Speaker With Raspberry Pi

  1. Open your favorite code editor and paste the following code:
# The frequencies in this code was based on the note frequencies found at:
# https://pages.mtu.edu/~suits/notefreqs.html
# Tuned at A4 = 440Hz.
 
import RPi.GPIO as GPIO
from time import sleep
 
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT)
pin7 = GPIO.PWM(7, 100)
pin7.start(50)
 
while True:
  GPIO.output(7, GPIO.HIGH)
  pin7.ChangeFrequency(16.35) # C0
  sleep(1)
  pin7.ChangeFrequency(261.63) # C4
  sleep(1)
  pin7.ChangeFrequency(293.66) # D4
  sleep(1)
  pin7.ChangeFrequency(329.63) # E4
  sleep(1)
  pin7.ChangeFrequency(349.23) # F4
  sleep(1)
  pin7.ChangeFrequency(392.00) # G4
  sleep(1)
  pin7.ChangeFrequency(440.00) # A4
  sleep(1)
  pin7.ChangeFrequency(493.88) # B4
  sleep(1)
  pin7.ChangeFrequency(523.25) # A5
  sleep(1.5)
  pin7.ChangeFrequency(16.35) # C0
  sleep(1)
  GPIO.output(7, GPIO.LOW)
  sleep(1)
  1. Save as “rpi-piezo.py” or any filename you want, as long as it ends with the “.py” file extension, then shut down the Raspberry Pi.
  1. Now it’s time to build the circuit. Connect the positive pin or wire to pin 7 and the other pin to GND. Some piezo elements have a “+” sign showing which pin is positive. Others have wires sticking out – as always, a red wire means positive.
Piezo On Breadboard Arrow On Cross Red And Black Wire
Arrow: Cross sign indicating 5V on the piezo speaker.

If you’re having trouble looking for pin 7, hold your Raspberry Pi in a way that the GPIO pins are sticking to the right, then look at the GPIO pins. The top-left pin should be pin 1 and to its right is pin 2. Below pin 1 is pin 3, and to its right is pin 4 and so on.

Raspberry Pi Pinout
  1. Power up your Raspberry Pi and open the terminal.
  1. Go to the folder where you saved “rpi-piezo.py” through the terminal using cd. Here’s an example: cd MTE/experiments/rpi-piezo. The folder “rpi-piezo” contains our “rpi-piezo.py” script.
  1. Now it’s time to run the Python script. Enter python3 rpi-piezo.py and listen to the sounds of the C major scale!

Code Explanation

The code can look like a large mess at first glance, so let’s separate it into three parts:

  1. Import commands
  2. Setup commands
  3. Looped commands

This isn’t a standardized grouping – it was created because it’s always a good practice to divide your code into easily identifiable parts. It makes things easier when you’re trying to change any part of the code.

Import Commands

This is where you define which modules you’re “importing” into your code. The import commands consist of two lines of code.

import RPi.GPIO as GPIO
from time import sleep

import RPi.GPIO as GPIO tells Python that you’re using the RPi.GPIO module to control the Raspberry Pi’s GPIO pins. as GPIO tells it that whenever you call the variable GPIO, you’re calling the RPi.GPIO module.

from time import sleep is another way of calling modules. But instead of taking the whole module, you’re just importing the sleep() function from the time module. This can help a lot when it comes to performance, as Python won’t have to load the whole module; it just uses that one function.

Setup Commands

The code in the setup commands is where you “set up” or define all the important parts in your program, such as variables, settings, and pin designations. These only have to be defined once.

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.OUT)
pin7 = GPIO.PWM(7, 100)
pin7.start(50)

GPIO.setwarnings(False) prevents warnings from showing up when you run the code. Warnings still show up when your code runs successfully, but adding this piece of code keeps warning messages from flooding the terminal every time you enter python3 rpi-piezo.py. But this is more of a personal preference – you can just remove this bit if you want to see the warnings. It still works the same.

GPIO.setmode(GPIO.BOARD) tells Python how you want your Raspberry Pi’s general purpose input/output (GPIO) pins to be named. There are two ways: BOARD and BCM.

  • BOARD is a naming format where you name the pins based on their pin numbers. Here, pin 1 is at the top left, pin 2 beside it, pin 3 below pin 1 and so on.
  • BCM stands for “Broadcom.” Instead of physical pin numbers, BCM chooses their Broadcom SOC Channel. This naming format differs from board to board, so it can be a bit harder to follow if you’re using BCM on a guide.

GPIO.setup(7, GPIO.OUT) tells Python that you’re using pin 7 as an output.

pin7 = GPIO.PWM(7, 100) makes a variable, pin7, that contains the string GPIO.PWM(7, 100). This shortens your code so that you can just use pin7 instead of calling GPIO.PWM(7, 100) all the time.

Lastly, pin7.start(50) sets pin 7 to PWM (Pulse Width Modulation) mode. This means that whenever pin 7 is set to HIGH, it emits 3.3V half of the time. The rest of the time, it doesn’t emit anything (or is at 0V).

Looped Commands

Looped commands run on a loop – they repeat as long as you keep the script running. To do so, you have to keep them indented after while True:.

while True:
  GPIO.output(7, GPIO.HIGH)
  pin7.ChangeFrequency(16.35) # C0
  sleep(1)
  pin7.ChangeFrequency(261.63) # C4
  sleep(1)
  pin7.ChangeFrequency(293.66) # D4
  sleep(1)
  pin7.ChangeFrequency(329.63) # E4
  sleep(1)
  pin7.ChangeFrequency(349.23) # F4
  sleep(1)
  pin7.ChangeFrequency(392.00) # G4
  sleep(1)
  pin7.ChangeFrequency(440.00) # A4
  sleep(1)
  pin7.ChangeFrequency(493.88) # B4
  sleep(1)
  pin7.ChangeFrequency(523.25) # A5
  sleep(1.5)
  pin7.ChangeFrequency(16.35) # C0
  sleep(1)
  GPIO.output(7, GPIO.LOW)
  sleep(1)

GPIO.output(7, GPIO.HIGH) turns pin 7 on HIGH. That pin is working and giving out a PWM signal. The function GPIO.output() takes in two parameters: the pin number and whether you want to set it HIGH or LOW. If you skip to the bottom part, you find GPIO.output(7, GPIO.LOW), which does the opposite – it turns pin 7 on LOW.

The lines of code in between are just a series of pin7.ChangeFrequency() and sleep(1). Adjusting their parameters lets you play different kinds of notes.

pin7.ChangeFrequency() is actually a shortcut form of GPIO.PWM(7, 100).ChangeFrequency(). Using the shortcut form makes it easier to change the pin you’re using. If you didn’t define pin7 = GPIO.PWM(7, 100) earlier, you would have to change the pin number on every frequency change you make.

What’s inside .ChangeFrequency() is the frequency of the PWM signal and, hence, the piezo element. Remember that a piezo element is just a solid crystal that slightly contracts when you pass electricity through it and relaxes when you stop. The rapid contracting and relaxing make sounds of varying pitches, and you can control the pitch by changing the number inside .ChangeFrequency(). To make things easier for you, there’s a comment after each pin7.ChangeFrequency() indicating what note they are.

Lastly, sleep(1) pauses the code for one second. If you pause the code after you change the frequency, you’d basically have a single note – it’s gonna play that note for as long as you keep the code sleeping.

How Is the Sound Generated

How does it all go from a vibrating piezo element to sound, then turn into something that could resemble music? It’s all about the frequency and pitch.

What we perceive as sounds with our ears are actually vibrations in the air. The more the air vibrates, the higher the sound’s pitch. We plot this out on paper as waves of varying patterns and give it an SI unit, i.e., a unit of measurement: Hz (which stands for Hertz). Sound waves with more Hz vibrate faster than those with less. We humans can hear sound waves vibrating somewhere between 20Hz and 20,000Hz.

When you used ChangeDutyCycle(), you changed the number of times that the piezo element would vibrate over time, i.e., the frequency. Hz is a measure of the frequency of vibrations in the air.

To change the sound in a way that at least resembles music, you have to change the frequency in a particular way. In other words, you have to modify the pitch. Unlike frequency, pitch is a measure of how high or low a sound sounds to our ears. By changing the pitch, you’re making something already close to music.

Guitar Unsplash
A guitar’s strings always play sounds at a definite frequency.
Image source: Unsplash

Of course, there is more to making music than just changing pitches. You also need pitch duration to make a note. That’s where sleep() goes – you make the Raspberry Pi stay at a given pitch for a certain amount of time to give you a proper note!

Frequently Asked Questions

What is the difference between a piezo speaker and a magnetic speaker?

Piezo speakers use a vibrating piezo element to produce sound. They are usually made of ceramic and are typically used in buzzers. Meanwhile, magnetic speakers use electromagnets that vibrate plastic membranes. They are used in smartphones and headsets.

Do piezo elements have polarity?

Technically, yes. The piezo element inside piezo speakers bends one way if you apply voltage from one side and the other way if you reverse it.

Besides speakers, what else are piezo elements used for?

Just about anything that has something to do with pressure and vibration has piezo elements. This includes accelerometers, microphones, guitar pickups, and speakers. But there’s also one unusual thing that has them: lighters use them to make the spark that lights a flame.

Photos and screenshots by Terenz Jomar Dela Cruz

Subscribe to our newsletter!

Our latest tutorials delivered straight to your inbox