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.
Installing Raspbian
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
corruption.
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
following:
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
first Pi.
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:
broadcast 224.0.0.1
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
for.
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.