GPIO Music Box - Raspberry Pi Projects PDF
GPIO Music Box - Raspberry Pi Projects PDF
Step 1 Introduction
In this project, you will build a button-controlled “music box” that plays
di erent sounds when di erent buttons are pressed. You can nd a
shortened version of this project on YouTube (https://www.youtube.co
m/watch?v=2izvSzQWYak&feature=youtu.be)
A Raspberry Pi computer
A breadboard
Four (4) tactile switches (to make buttons)
Five (5) male-to-female jumper leads
Four (4) male-to-male jumper leads
Speakers or headphones
Software
You will need some sample sounds for this project. There are lots of
sound les on Raspbian, but it can be a bit di cult to play them using
Python. However, you can convert the sound les to a di erent le
format that you can use in Python more easily.
Open a File Manager window by clicking on the icon in the top left
corner of the screen
In the window, right-click and select Create New… and then Folder
from the context menu
In the dialogue box, type the name of your new directory and then
click OK
Open a new Terminal window by clicking on the icon in the top left
corner of the screen
mkdir my-new-directory
cd my-new-directory
Type the following lines to copy all the les from one directory to
the other:
cp /usr/share/sonic-pi/samples/* ~/gpio-
music-box/samples/.
When you have done that, you should be able to see all the .flac
sound les in the samples directory.
Convert the sound les
To play the sound les using Python, you need to convert the les from
.flac les to .wav les.
cd ~/gpio-music-box/samples
If you want to learn more about converting media les and running
commands on multiple les, look at the two sections below.
You can easily convert media les on the Raspberry Pi using a piece
of software called mpeg. This is preinstalled on the latest versions
of
Raspbian (https://www.raspberrypi.org/downloads/raspbian/).
mv original_file_name.txt new_file_name.txt
for f in *
Next you need to tell bash what to do with each le name. In this
case you want to echo the le name to standard output.
do
echo $f
Here the $ sign is used to state that you’re talking about the
variable f. Lastly you need to tell bash that you’re done.
done
You can hit enter after each command if you like, and bash won’t
run the whole loop until you type done, so the command would
look like this in your terminal window:
for f in *.txt
> do
> echo $f
> done
Alternately, instead of hitting Enter after each line, you could use a
; to seperate the commands.
Manipulating strings.
That last command was a little pointless, but you can do much more
with batch operations. For instance, what if you wanted to change
the name of each of the les, so instead of being called 0.txt for
instance, they get called 0.md.
If you ls the contents of the directory, you’ll see all the les have
been renamed. So how did this work?
The rst part for f in *.txt tells bash to run the operation on
every le ($f) with a .txt. extension.
words="Hello World"
echo ${words%World}
You could now end something else onto the end of the string.
echo ${words%World)Moon
You should now be able to see all the new .wav les in the samples
directory.
Next, you will start to write your Python code. You can use any text
editor or IDE to do this — Mu is always a good choice.
To start to create the instruments of your music box, you need to test
whether Python can play some of the samples that you have copied.
First you will need to import the pygame module and initialise it.
import pygame
pygame.init()
Playing a sound
Next you can create a Sound object and provide it with the path
to your le.
my_sound =
pygame.mixer.Sound('path/to/my/soundfile.wav')
my_sound.play()
First, import and initialise the pygame module for playing sound
les.
import pygame
pygame.init()
Save this le in your gpio-music-box directory.
Choose four sound les that you want to use for your project, for
example:
drum_tom_mid_hard.wav
drum_cymbal_hard.wav
drum_snare_hard.wav
drum_cowbell.wav
drum = pygame.mixer.Sound("/home/pi/gpio-
music-box/samples/drum_tom_mid_hard.wav")
import pygame
pygame.init()
drum = pygame.mixer.Sound("/home/pi/gpio-
music-box/samples/drum_tom_mid_hard.wav")
cymbal =
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_cymbal_hard.wav")
snare = pygame.mixer.Sound("/home/pi/gpio-
music-box/samples/drum_snare_hard.wav")
bell = pygame.mixer.Sound("/home/pi/gpio-
music-box/samples/drum_cowbell.wav")
Save and run your code. Then, in the shell at the bottom of the
Mu editor, use .play() commands to play the sounds.
drum.play()
If you don’t hear any sound, check that your speakers or headphones are
working and that the volume is turned up.
You will need four buttons, each wired to separate GPIO pins on the
Raspberry Pi.
If you look at a Raspberry Pi with the USB ports facing towards you,
the layout of the GPIO pins is as follows.
3V3 5V
GPIO2 5V
GPIO3 GND
GPIO4 GPIO14
GND GPIO15
GPIO17 GPIO18
GPIO27 GND
GPIO22 GPIO23
3V3 GPIO24
GPIO10 GND
GPIO9 GPIO25
GPIO11 GPIO8
GND GPIO7
DNC DNC
GPIO5 GND
GPIO6 GPIO12
GPIO13 GND
GPIO19 GPIO16
GPIO26 GPIO20
GND GPIO21
Each pin has a number, and there are additional pins that provide 3.3
Volts, 5 Volts, and Ground connections.
Here’s another diagram showing the layout of the pins. It shows some
of the optional special pins as well.
Full
Abbreviation Function
name
3.3 Anything connected to these pins will
3V3
volts always get 3.3V of power
Anything connected to these pins will
5V 5 volts
always get 5V of power
GND ground Zero volts, used to complete a circuit
These pins are for general-purpose use
GPIO
GP2 and can be con gured as input or output
pin 2
pins
ID_SC/ID_SD/DNC Special purpose pins
There are various types of buttons - they can for example have two or
four legs. The two-leg versions are mostly used with ying wire to
connect to the control device. Buttons with four legs are generally
mounted on a PCB or a breadboard.
Here’s a video that shows how you can wire the buttons.
To see how a function can be called using a button press, have a look at
the section below.
In the diagram below, a single button has been wired to pin 17.
You can use the button to call functions that take no arguments:
First you need to set up the button using Python 3 and the
gpiozero module.
from gpiozero import Button
btn = Button(17)
def hello():
print('Hello')
btn.when_pressed = hello
Now each time the button is pressed, you should see Hello being
printed to the Python shell.
Your function can be as complex as you like - you can even call
functions that are parts of modules. In this example, pressing the
button switches on an LED on pin 4.
btn = Button(17)
led = LED(4)
btn.when_pressed = led.on
When the button is pressed, the program should call a function such as
drum.play().
This is because the program must only call the function when the
button is pressed, rather than straight away. So, in this case, you just
use drum.play.
First, set up one of your buttons. Remember to use the numbers
for the GPIO pins that you have used, rather than the numbers
in the example.
1 import pygame
2 from gpiozero import Button
3
4 pygame.init()
5
6 drum =
7 pygame.mixer.Sound("/home/pi/gpio-
8 music-
9 box/samples/drum_tom_mid_hard.wav")
10 cymbal =
11 pygame.mixer.Sound("/home/pi/gpio-
music-
box/samples/drum_cymbal_hard.wav")
snare =
pygame.mixer.Sound("/home/pi/gpio-
music-box/samples/drum_snare_hard.wav")
bell =
pygame.mixer.Sound("/home/pi/gpio-
music-box/samples/drum_cowbell.wav")
btn_drum = Button(4)
To play the sound when the button is pressed, just add this line
of code to the bottom of your le:
btn_drum.when_pressed = drum.play
Run the program and press the button. If you don’t hear the
sound playing, then check the wiring of your button.
Now, add code to make the remaining three buttons play their
sounds.
btn_cymbal = Button(17)
btn_cymbal.when_pressed = cymbal.play
import pygame
from gpiozero import Button
pygame.init()
drum = pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_tom_mid_hard.wav")
cymbal = pygame.mixer.Sound("/home/pi/gpio-
music-box/samples/drum_cymbal_hard.wav")
snare = pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_snare_hard.wav")
bell = pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_cowbell.wav")
btn_drum = Button(4)
btn_cymbal = Button(17)
btn_snare= Button(27)
btn_bell = Button(10)
btn_drum.when_pressed = drum.play
btn_cymbal.when_pressed = cymbal.play
btn_snare.when_pressed = snare.play
btn_bell.when_pressed = bell.play
Step 6 Improve your script
The code that you have written should work without any problems.
However, it’s generally a good idea to make your code a bit cleaner once
you have a prototype that works.
The next steps are completely optional. If you’re happy with your script,
then just leave it as it is. If you want to make your script a bit cleaner,
then follow the steps on this page.
You can store your button objects and sounds in a dictionary, instead of
having to create eight di erent objects.
Have a look at the steps below to learn about creating basic dictionaries
and then looping over them.
Dictionaries in Python
The dictionary has a name, in this case band, and the data in it is
surrounded by curly brackets ({}). Within the dictionary are the key () :
value () pairs. In this case the keys are the names of the band
members. The values are the names of the instruments they play.
Keys and values have colons between them (:), and each pair is
separated by a comma (,). You can also write dictionaries so that
each key () : value () pair is written on a new line.
band = {
'john' : 'rhythm guitar',
'paul' : 'bass guitar',
'george' : 'lead guitar',
'ringo' : 'bass guitar'
}
Open IDLE, create a new le, and have a go at creating your own
dictionary. You can use the one above or your own if you like.
When you’re done, save and run the code. Then switch over to the
shell to have a look at the result by typing the name of your
dictionary.
You’ll probably notice that the key () : value () pairs are no longer in
the order that you typed them. This is because Python dictionaries
are unordered, so you can’t rely on any particular entry being in
any speci c position.
To look up a particular value () in a dictionary you can use its key ().
So for instance, if you wanted to nd out what instrument ringo
plays, you could type:
band['ringo']
Dictionaries can store all types of data. So you can use them to
store numbers, strings, variables, lists or even other dictionaries.
Like any data structure in Python, you can iterate over dictionaries.
If you simply iterate over a dictionary with a for loop, you will only
be iterating over the keys.
band = {
'john' : 'rhythm guitar',
'paul' : 'base guitar',
'george' : 'lead guitar',
'ringo' : 'bass guitar'
}
>>> ringo
john
george
paul
If you want to get the keys and values, you’ll need to specify this in
your for loop
First, create a dictionary that uses the Buttons as keys and the
Sounds as values.
button_sounds = {Button(4):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_tom_mid_hard.wav"),
Button(17):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_cymbal_hard.wav"),
Button(27):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_snare_hard.wav"),
Button(10):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_cowbell.wav")}
You can now loop over the dictionary to tell the program to play
the sound when the button is pressed:
import pygame
from gpiozero import Button
pygame.init()
button_sounds = {Button(4):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_tom_mid_hard.wav"),
Button(17):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_cymbal_hard.wav"),
Button(27):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_snare_hard.wav"),
Button(10):
pygame.mixer.Sound("/home/pi/gpio-music-
box/samples/drum_cowbell.wav")}
Challenge!