In this chapter, we will take a quick look at the Raspberry Pi hardware and some of the software that will be used both in this project and the majority of others throughout this book.
As the Pi was based on hardware that was to be included in embedded or portable electronics (such as smartphones and tablets), it has a few extra hardware features that are not found on a typical desktop or laptop PC, one of which is the General Purpose Input and Output (GPIO) header. This is a set of pins (26 on the model A and B, and 40 on the model B+) that allows you to communicate with external hardware such as GPS sensors, accelerometers, and motors through programming languages such as Python, C, and C++. When we get further in this chapter, we will take a look at a little trick that can be done to turn one of these pins into an FM radio transmitter.
In order to get the Pi up and running, the bare minimum you will need is a USB power supply, micro USB cable, an Ethernet cable to connect the Pi to your network, and an SD card that has at least 4 GB memory. Although, later on, some projects will need a larger capacity of the SD card.
While a monitor, mouse, and keyboard can also be used for a lot of the projects in this book, they are not actually required assuming that you have a network that runs a DHCP server, which you can connect with the Pi in order to set it up over SSH.
It is worth mentioning now that for a USB-powered device, the Pi is quite power-hungry (drawing around 600-700 mA), therefore, while the Pi can be powered from a USB port, which is usually rated for around 500 mA, it is recommended that you use a mains powered adapter. Without this, the Pi can become unstable when additional devices are connected that draw more power, for example, a USB Wi-Fi dongle or camera module.
There are a wide range of Linux distributions available for the Pi, some of which are very general purpose while others are built for specific purposes (a couple of which will be used in the later projects of this chapter). For now, we will use the most standard distribution, Raspbian, which as the name suggests is based on the Debian distribution.
The Raspberry Pi downloads page (http://www.raspberrypi.org/downloads) has a good selection of general purpose distributions.
Another relatively new distribution that is worth mentioning is Minibian (http://minibianpi.wordpress.com), a distribution based on Raspbian, which has the majority of its default software removed. While this may not seem that helpful, it means that the Pi boots in a useable OS in around 25 seconds and saves the SD card space. This type of OS is more suited to a project that has finished being developed and is going into a more natural usage environment. You usually would not expect a Wi-Fi router to take 3 minutes to boot, so why should your Pi-based Internet radio?
When you have all the relevant hardware, head over to http://www.raspberrypi.org/downloads and download the ZIP archive for Raspbian and extract it.
The next steps vary depending on your operating system.
Windows does not natively include a tool used to write disk images, therefore, the Win32 Disk Imager (http://sourceforge.net/projects/win32diskimager) application is used to write images to an SD card.
First, go to the download link mentioned in the preceding paragraph, download, and install Win32 Disk Imager. As writing images to drives requires administrator permissions, you will need to run Win32 Disk Imager by right-clicking on its entry in the Start menu, and selecting Run as administrator:
Ensure that the correct drive letter is selected, and the SD card does not contain any data that has not been backed up, as this operation will destroy all of the data already present in the card.
Finally, click on Write to write the image to the SD card.
First, you will need to find the path for your SD card. The easiest way to do this is to use the udev management tool,
udevadm, to monitor the udev log, which logs activity from various devices on the system, including the SD card being inserted and will allow you to see the device path that was assigned to it and the partitions already existing on it. This can be done by running the following command:
udevadm monitor --udev
Then, insert the SD card, at which point, you should see a set of log messages similar to the ones shown in the following screenshot:
We must now ensure that none of these partitions on the SD card are currently mounted, as some desktop managers (such as GNOME, the default desktop manager on Ubuntu) will try to automatically mount partitions when they are detected.
To do this, we will run the following command for every partition (that is, in my case,
PATH is the path to the partition:
If the partition was mounted, you will not see any output from the command; however, if the partition was not mounted, you will get the following message:
Once you know the path for your SD card and have ensured that no existing partitions are mounted, you can then write the Raspbian image to your SD card using the following command, where
PATH is the path to the SD card (
/dev/sdb in my case):
sudo dd if=path/to/raspbian_image.img of=PATH
Be certain that the path to the SD card is correct, and the card does not contain any data that has not been backed up as this operation will destroy all of the data already present on the card.
path/to/raspbian_image.img is the extracted image file and
sdX is the path to your SD card. Note that this step can take up to 5-8 minutes, since no output is given on the screen, the SD card reader's busy/data LED is a good indication that the image is being written.
Since the GNU Coreutils (which include commands such as
dd, and so on) do not provide much (or any) output to indicate the progress, you may want to take a look at the Coreutils Viewer tool (https://github.com/Xfennec/cv), which shows the progress of the Coreutils commands.
Once you have the image written to the card, it is time to boot the Pi and perform the initial setup. The most common way to do this is by using a keyboard, mouse, and monitor; however, if you have access to a network that provides DHCP (as most home networks do), then the setup can be done entirely over Secure Shell (SSH).
First, set up the hardware and boot the Pi by inserting the SD card, connecting the power, and the Ethernet cable. Within a few seconds, you will see that the ACT LED starts to flicker. If it flashes for very short pulses or does not light at all, then this indicates an issue with either the SD image, the connection between the card and the Pi (a common issue for the models A and B), or the card itself.
Once the Pi has booted (indicated by less frequent flashing of the ACT LED), you will need to determine its IP address. There are two main ways to do this: by accessing the DHCP allocations via your router or by scanning the local network.
The cross-platform tool, the Nmap utility (http://nmap.org) can be used to scan a network.
To do so, you will need to find the IP address of your PC (in order to find the subnet on your local network to search for the Pi in). On Windows, this can be done by opening the Command Prompt and executing this command:
This should give you the information about your network interfaces similar to the following:
On Unix, this can be done by using the following command:
This command gives output similar to the following:
Now that we know the address range in which we will be looking, we can open a terminal and run the following command:
nmap --open 192.168.0.*
Replacing the IP range with your search range will try to make contact with every host in the given IP address range and will return with a list of every host that is up, with a list of their open ports, and what services they correspond to. In our case, we are looking for any hosts that have an open SSH port:
Starting Nmap 5.21 ( http://nmap.org ) at 2014-09-21 11:58 BST Nmap scan report for 192.168.0.8 Host is up (0.0064s latency). Not shown: 999 closed ports PORT STATE SERVICE 22/tcp open ssh Nmap done: 256 IP addresses (5 hosts up) scanned in 5.84 seconds
On Unix, accessing the Pi via SSH is as simple as executing the following:
ssh pi@[Pi IP]
The authenticity of host '192.168.0.8 (192.168.0.8)' can't be established. ECDSA key fingerprint is 32:4c:46:1b:dd:7e:8b:52:a0:31:c3:f5:9f:73:d1:c6. Are you sure you want to continue connecting (yes/no)?
On Windows, PuTTY (http://www.putty.org) can be used to SSH into the Pi. Once downloaded, run PuTTY and enter the IP address of the Pi and the Host Name field, ensuring that Port is set to 22 and SSH is selected. Then, click on Open:
At this point, it would be good to learn a few Linux shell commands, which you will no doubt come across while working with the Pi:
chmod: The change mode command changes the access permission to a file, for example,
chmod 744 file(this gives read, write, and execute permissions to the owner, and read-only permission to everyone else)
This utility allows you to configure the Pi hardware and perform useful configuration tasks such as changing passwords and resizing the root partition on the SD card, both of which, we will do now.
First, select the Expand Filesystem option and press Enter. The utility will modify the partition table and report that it has completed, and that the changes made will only affect the filesystem after the next reboot. Press Enter again to return to the main menu.
Now, select Change User Password and hit Enter twice. You will be taken back to the shell and prompted to enter a new password, which has to be entered twice. Once done, a confirmation box will notify you that the password was changed successfully; press Enter to return to the menu.
As this is all that needs to be done in
raspi-config for now, press the left arrow key twice to select Finish and Enter to confirm. You will be asked whether you want to reboot now; select Yes and press Enter. Once the Pi is rebooted, SSH back into it using your new password.
The command should report the size of
rootfs much closer to the SD card capacity:
rootfs 16G 2.5G 13G 17% /
All that is left to do now is to make sure that the software on the Pi is up to date. Since we are using an image that was just downloaded, it is not likely that there will be a large number of updates; however, it is a good practice to keep an installation up to date.
Running the following commands will first update the list of available packages then update any installed packages with newer versions than what was installed:
sudo apt-get update sudo apt-get upgrade
Note that this process can take up to 10 minutes depending on the number of updates, and usually takes longer than a desktop PC or laptop as this process is writing to an SD card rather than a traditional hard drive.
wget http://omattos.com/pifm.tar.gz tar -xzvf pifm.tar.gz
This will get the gzipped archive that contains the PiFM software, the Python library, and some test files and uncompress them.
For now, a single male to male 0.1 inch pin jumper will suffice as an antenna; this should be connected to GPIO 4 (pin number 7) on the GPIO header and made to stand as upright as possible to ensure the best range (refer to the following image):
You are now ready to test the setup with an FM radio; firstly, you will need to choose a frequency that will not overlap with any licensed broadcasts in your area and is within the FM radio transmission range in your area (usually between 88 Mhz and 108 Mhz). A lot of radios that do automatic tuning also tend to prefer frequencies that are a multiple of 0.1 MHz (for example, 99.9, 101.3, and so on).
Once you have chosen your frequency, tune your radio in to it, and run the following command on the Pi, where
freq is the frequency you wish to broadcast on:
sudo ./pifm left_right.wav freq 22050 stereo
You should now hear a sample auto clip demonstrating the ability to broadcast stereo audio.
For our media player, we are going to need a selection of MP3 files on the Pi SD card. There are two main ways to do this, either by moving the card back to your PC and mounting it like a regular SD card, or by using the Secure File Transfer Protocol (SFTP).
In this case, since the Pi is already running, I have opted to use SFTP. This can be done using the FileZilla (https://filezilla-project.org) FTP client. Once installed and opened, enter the same details that you used to connect to the Pi over SSH in the fields at the top of the window (using 22 for Port), and click on Quickconnect.
You should now be able to browse the filesystems of both your computer and the Pi, as shown in the following screenshot. Files can be uploaded by right-clicking on them and selecting Upload.
In order to play the music you have just transferred to the Pi, you will need to install the
ffmpeg utility, which is a tool that is commonly used to transcode media files and can be installed using the following command:
sudo apt-get install ffmpeg
Now that you have some of your own music on the Pi, you can try playing it by piping the output of
ffmpeg to PiFM:
ffmpeg -i file.mp3 -f s16le -ar 22.05k -ac 2 - | sudo ./pifm - freq 22050 stereo
file is the MP3 file to be broadcasted and
freq is the frequency to broadcast it on. Since we are telling
ffmpeg to provide output for two audio channels (
-ac 2) and giving the stereo option to PiFM, this should give a stereo audio broadcast.
To do this, we will write a Python script that manages to search for MP3 files and calls PiFM to broadcast them.
In the PiFM download and on the PiFM website, you may have noticed that there is a Python library that can be used to control PiFM. Although, looking at the source code for it, you can see that all the library can do is call the
pifm executable with the minimum number of commands, and therefore will not allow us to play MP3 files.
However, it is a simple process to create our own function that will allow us to pass the filename of an MP3, a frequency, and that will allow Python to call
ffmpeg and PiFM in order to broadcast the audio in the file for us:
def play_file(filename, frequency): command = 'ffmpeg -i "%s" -f s16le -ar 22.05k -ac 2 - | sudo ./pifm - %f 22050 stereo' % (filename, frequency) subprocess.call(command, shell=True)
This code is an extract from the
player.py file; all we are doing here is taking the shell commands used to play an MP3 file and replacing the filename and broadcast frequency with values that are passed to the function as parameters. Then, we are using the Python subprocess module to execute the command as if it was typed into a shell.
Downloading the example code
You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
For our script to play any MP3 files, it needs to be able to find them first. Finding an MP3 file involves taking a look at each file in a starting directory to check whether a file is an MP3 file, and then repeating this process for every directory within the start directory. Thankfully, Python makes this very easy:
mp3_files = list() for root, dirs, files in os.walk(directory): for filename in files: if filename.endswith(".mp3"): mp3_files.append(os.path.join(root, filename))
directory is the directory we want to search for files media in. The
os.walk function returns a tuple; the first element (
root) is a string that contains the absolute path to the search directory,
dirs is a list of directories within the search directory and its subdirectories, and
files is a list of all the files within the search directory and its subdirectories.
if statement is a simple way to check whether a file is an MP3 file based solely on its file extension. If it has the
.mp3 extension, it is added to the
mp3_files list, which is then passed to the playlist code.
In order to set various settings for our player script, for example, the directory in which you can search for files, we need a way to get input from the user via a command line, and in this case, from the arguments passed to the script when it is started. To do this, we will use the
argparse Python module:
parser = argparse.ArgumentParser(description='Broadcast a set of MP3s over FM') parser.add_argument( '-f', '--frequency', default=101.1, type=float, help='Frequency on which to broadcast') params = parser.parse_args()
argparse Python module allows you to define a set of arguments that can be passed to a Python program, it allows you to parse the arguments when the script is run, and it automatically allows you to generate a help page (accessed by passing
-h to the script).
In this case, we will add an argument for the broadcast frequency, which is set using either
type is used to validate input from the user,
default is what is read by the program if the user does not set a value, and
help is what is shown for this argument on the help page.
file_number = -1 while True: if params.random: file_number = random.randint(0, len(filenames) - 1) else: file_number += 1 if file_number >= len(filenames): return play_file(filenames[file_number], params.frequency)
Here, if the
--random parameter has been passed to our script, whenever we are about to play a file, the file to be played will be selected at random using the
randint function in the
random Python module. This number is then used to get a certain file from the list of filenames that were previously discovered.
python player.py -d music -f 99.9 --random
This will search for all MP3 files under the music directory and broadcast them at 99.9 MHz in a random order. A full list of commands will be available to you if you run:
python player.py -h
Since the radio is not much of use when you have to SSH into it to start playing the music, we will add a cron job that will start the
player.py script when the Pi boots up.
To do this, we will use a shell script to start the Python script (
#!/bin/bash sleep 20 cd /home/pi python player.py -d music --random -f 99.9 &
This will ensure that the player script is executed in the correct folder, in this case,
/home/pi, as this is where our PiFM executables and music directories are.
Next, we will add an entry in the crontab, which is where cron jobs are defined. This can be edited with the following command:
sudo crontab -e
This command will open the default command-line text edit on the Pi,
nano, which will allow you to add entries to the crontab. To start our media player script, we will need to add the following line to the end of the crontab that is opened:
Press Ctrl + X followed by Y and Enter to save the changes to the crontab, then use the following command to reboot the Pi, and if all goes as planned, start your personalized radio station:
In this chapter, we covered the basic setup of the Pi hardware and Raspbian OS. You learned how to discover the IP address of the Pi in order to allow remote access to it over SSH; this process will be used in the majority of the projects later in this book.
We also took a quick look at the GPIO expansion header, and how it is typically used to interface with external hardware. We also used this as a crude FM transmitter through which we wrote a single Python script to broadcast music.
In the next chapter, we will go into further details regarding how to set up various software packages in order to run them on the Pi, as well as you will learn the various ways to configure networking when we make a portable speaker system that runs the Logitech Media Server.