At the start of the month I announced my plan to try and build my own whole home audio system using a handful of Raspberry Pis to act as the player and audio
receivers. I’ve received
all the stuff I need now, and I’m ready to get to building!
The first thing I’m doing is preparing the Pis and setting
up networking. Next I’m going to install audio playing software with a
web-interface on Pi number one, and thirdly I’ll adjust the setup so that this
player sends it’s audio to the other two Pis (the receivers) instead of
outputting it directly to its own speakers. You can follow the whole journey by
following the #RPiWHA
Project hashtag right here.
Raspbian is the Raspberry Pi’s recommended operating system.
There’s plenty of guidance online on how
to install it, so I won’t reiterate the whole process here. When I ran
through Raspbian’s initial setup options on first boot I set my location,
timezone and keyboard layout (in Internationalisation Options), set the memory
split to 16mb for graphics (in Advanced Options – we can set this low because
we won’t even be connecting a display) and finally expanded the filesystem
(right from the main menu).
Minimizing SD Card Access
The Pi has no power button. If it’s plugged in then it’s on,
and you turn it off by pulling the plug. I’ve read online that if the power is
pulled while the system is in the process of writing to the Pi’s SD card (which
is the only storage the system has) this can cause problems and possible
Linux systems do a lot of logging, most commonly to the
folder /var/log. They also write stuff about running process to the folder
/var/run. To minimize writes to the SD card, we’re going to mount these two
folders in memory instead of on the card. Another cause of frequent writes is
that linux systems store the time that a file was last accessed, so even if we’re
just reading a file the system is actually writing back to the disk to update
the time that the file was accessed. We’re going to change that behaviour too.
To make these changes, we’re going to edit the file
/etc/fstab so that it looks like this:
proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults,noatime 0 2 /dev/mmcblk0p2 / ext4 defaults,noatime 0 1 none /var/run tmpfs size=1M,noatime 0 0 none /var/log tmpfs size=1M,noatime 0 0
The first two lines haven’t changed, but on the third line
we’ve added the flag “noatime” to indicate that we don’t want to store the
timestamp that the file was last accessed. The fourth and fifth lines are
entirely new, and these create 1mb partitions in RAM to house the /var/run and /var/log folders respectively.
Setting Up Networking on Pi #1
The next step was to connect one of the Pis (and only one)
to my existing home WiFi network. To do this I plugged in one of my USB WiFi
adapters and modified the /etc/network/interfaces file to include the
auto wlan0 allow-hotplug wlan0 iface wlan0 inet static wpa-ssid MyHomeWiFiName wpa-key-mgmt WPA-PSK wpa-group CCMP TKIP wpa-pairwise CCMP TKIP wpa-psk MyHomeWiFiPassword address 192.168.1.71 netmask 255.255.255.0 gateway 192.168.1.254 dns-nameservers 192.168.1.53 192.168.1.254
Your setup will probably be slightly different, but
essentially this connects to my home network, gives the pi a static IP address
(192.168.1.71 in my case) and defines my two DNS servers.
You may be wondering why I’m only doing this on one of the
Pis, given that they all need to be connected together. The reason is that this
first pi (the player) is ultimately going to be sending audio out over the
network as multicast packets. In other words, this data goes to every device on
the network whether they want it or not.
The problem is that this is a lot of data flowing around, and
a typical home WiFi network struggles under the load of it all. My solution is
to have two WiFi networks. The one we’ve set up above will connect us to the
internet (for streaming audio services) and other stuff on my network (like the
fileserver where my music collection lives), but we’ll use a second, separate
WiFi network to send the multicast audio to other Pis.
Let’s plug in a second USB WiFi adapter to the first Pi, and
make some more additions to the /etc/network/interfaces file:
auto wlan1 allow-hotplug wlan1 iface wlan1 inet static address 192.168.5.1 netmask 255.255.255.0
This section is pretty minimal as you can see, but it’s
setting a static IP address on the second wireless interface. The important
part is that this uses a different subnet to the other WiFi network (in my
case, 192.168.1.x is my existing network, 192.168.5.x is the dedicated network
for the Pis).
This section of the /etc/network/interfaces file is so short
because this Pi is going to act as a wireless access point that the others will
connect to. To set this up we need an additional bit of software, called
hostapd. Because I’m using WiFi adapters based on a Realtek 8188 chipset, I had to download and compile this myself – the version found in the debian software repositories wouldn’t work for me:
wget https://github.com/jenssegers/RTL8188-hostapd/archive/v1.1.tar.gz tar -zxvf v1.1.tar.gz cd RTL8188-hostapd-1.1/hostapd make sudo make install
Then edit the file /etc/hostapd/hostapd.conf to change the following three lines:
interface=wlan1 ssid=PiWHA wpa_passphrase=mySecurePassword
Finally, start the service and add it to the boot autostart services for future:
sudo /etc/init.d/hostapd start sudo update-rc.d hostapd enable
Setting Up Networking on the Other Pis
We want the other Pis to connect to the wireless network
hosted by Pi #1. To do so, plug one USB WiFi adapter into each and modify the
/etc/network/interfaces file on each to reflect the following:
auto wlan0 allow-hotplug wlan0 iface wlan0 inet static wpa-ssid PiWHA wpa-key-mgmt WPA-PSK wpa-group CCMP TKIP wpa-pairwise CCMP TKIP wpa-psk mySecurePassword address 192.168.5.2 netmask 255.255.255.0
The important point here is that the IP address for each
must be unique, and must be on the same subnet (192.168.5.x) that we set on the
Setting Up Time Synchronization
The Raspberry Pi has no real-time clock, and instead it gets
the time from internet time servers at boot. Having the time synchronized on
each of our Pis is going to be important to make sure that they play music in
sync. Only the first Pi has a connection to the wider internet though, so we
need to take some additional steps. On Pi #1, edit the file /etc/ntp.conf and
uncomment (or add) the following line:
This tells the pi to broadcast a time signal out onto the
network using a special multicast IP address that the other Pis will listen
On the other Pis edit the same file, but uncomment (or add)
the following lines:
disable auth broadcastclient
We don’t need to tell the other Pis which multicast IP
address to listen for – they already know as part of the NTP protocol.
And We’re Done! Or Are We?
That was a lot of setup work, but we should now have our Pis
setup and networked together, with our player device having an additional
connection to the wider internet.
The thing is… I don’t. The setup is all correct, but the
cheap USB WiFi adapters I bought from China don’t properly support access point
mode. Sometimes things work, sometimes they don’t.
I’ve read that I can download driver source-code from the
adapter’s manufacturer and compile the driver myself, so I’m going to try this
before I go further.