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.
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.
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
- 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)
- 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.
- 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.
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.
- Power up your Raspberry Pi and open the terminal.
- 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.
- Now it’s time to run the Python script. Enter
python3 rpi-piezo.pyand listen to the sounds of the C major scale!
The code can look like a large mess at first glance, so let’s separate it into three parts:
- Import commands
- Setup commands
- 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.
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.
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.
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 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: 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
LOW. If you skip to the bottom part, you find
GPIO.output(7, GPIO.LOW), which does the opposite – it turns pin 7 on
The lines of code in between are just a series of
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.
.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.
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.
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
Our latest tutorials delivered straight to your inbox