Hipster Spotify Radio Using A Raspberry Pi
Spotify is such an awesome music service. Raspberry Pi Zero is such an awesome ultra-mini computing device. Obviously, combining the two is something I must do!!! The idea here is to make something that's stylish, portable, can play Spotify, and hopefully also display visuals such as album art. If you're interested in following this project, feel free to click on the "Follow" icon just above this paragraph. Click the video below to see an overview, otherwise, scroll down to see how I made this musical masterpiece!
[slogan id="step1" h1="Step 1" h3="The Idea"]
The Pi Zero W is a phenomenal full linux computer that's basically the size of a stick of gum. And the "W" version has both bluetooth and wireless built in! That opens it up to so many amazing potential projects. One that I have been really wanting to do is a portable streaming Spotify client that displays album art or other visuals. Does it have to be a Pi Zero? Nope. You can use any other Pi or Pi alternative, but I just love the portable size and power consumption of the Pi Zero. The only issue is that the Pi Zero (at least the current iteration at the time of writing this guide) doesn't support Audio Out, unless it's through HDMI, but I'll touch on that a little later on. There are pre-built audio output "hat's" available, if you want to go that route. But anyway, here's the basic goals and obstacles I'll have to overcome for making this project work:
- Add audio output to the Raspberry Pi
- Add an amp/speaker to the Raspberry Pi
- Find a way to stream Spotify as a "headless" client
- Display album art on a small LCD screen.
[slogan id="step2" h1="Step 2" h3="Setting Up The Pi Zero"]
Before we do anything else, the first thing is to get the Pi Zero up and running. This is pretty much the standard setup for any Raspberry Pi that you get. Here's the basic items a Raspberry Pi requires to setup, if you are unfamiliar with the process:
- Pi Zero "W" board
- 4GB or Larger Micro SD Card
- HDMI Adapter
- HDMI Monitor
- USB OTG adapter
- Micro USB power supply
- Mouse & Keyboard
The first step is to load the Raspbian Operating System onto the SD card. The Raspbian OS can be downloaded from here. It downloads as a zip file that contains the Raspbian image file, and the way to transfer that image file to the SD card on Windows is by using the Win32 Disk Imager (you can use Etcher.io for other platforms).Once you launch Win 32 Disk Imager, you can choose the drive letter for your SD card, choose the Raspbian image, and then click "Write" to write the image to the SD card. Then eject the SD card and put it in the Raspberry Pi, along with the monitor, keyboard/mouse, and power.
- Download Raspbian
- Use Win32 Disk Imager to burn it to the SD Card
- Insert the SD card into the PI
- Add HDMI, Keyboard, Mouse, and power to the PI
After the Pi boots up, you can click on the wireless icon in the upper right and choosing your wireless network. Then by right clicking on that same wireless icon and choosing "Wireless & Wired Network Settings", you can set a static IP address for your Pi. Lastly, you want to click on the menu icon in the upper left and choose Preferences > Raspberry Pi Configuration. Then click on the "Interfaces" tab and make sure SSH and SPI are enabled. After that, everything should be setup on the Pi and we can begin the dirty work.
- Connect to wireless
- Go to network settings
- Set Static IP
- Enable SSH
[slogan id="step3" h1="Step 3" h3="Adding Audio"]
The first biggest hurdle to overcome is the fact that the Pi Zero (at least at the time of this post) doesn't have audio output. There are a few different ways to get around that.
- Purchase a digital audio extension: Adafruit MAX98357 or Pi Zero "hat" extension
- Make a simple circuit to extract audio from the GPIO pins
- Split out the audio from the HDMI output
If you want to go with option 3 and do the DIY route, you can follow these steps to make your own Audio Output. This method will also require either making your own Amp to use speakers, or you could purchase a simple stereo amp.
However, the method I chose to go with is quite a bit simpler. I decided to go with the Adafruit MAX98357 audio amp.
It serves several purposes: it creates an audio output, serves as a mono-amp, and can be powered through the Pi zero GPIO pins. It's pretty simple to wire up. I've decided to use the Adafruit Proto "Bonnet" for the Pi to make it easier to connect everything up to it. You can use the diagram below to connect it to your Pi.
MAX98357 | Raspberry PI |
---|---|
VIN | 5v |
GND | GND |
SD | -- |
GAIN | -- |
DIN | GPIO 21 |
BCLK | GPIO 18 |
LRCLK | GPIO 19 |
Download the Fritzing diagram here
Now that it's all wired up, we have to do a simple software tweak to get it running. Connect to your Pi through SSH and run this script:
curl -sS https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/i2samp.sh | bash
and then reboot the pi
sudo reboot
When it comes back up, you can run a test audio file to see if it all works
speaker-test -c2 --test=wav -w /usr/share/sounds/alsa/Front_Center.wav
If it doesn't work or you have any issues, you can refer to this guide over on the Adafruit website.
[slogan id="step4" h1="Step 4" h3="Adding the LCD"]
The key to make my streaming radio stand out and give it a unique touch is to have a screen that displays the album art of the current song that is playing. Obviously this is going to require an LCD. I'm going with a 1.8" TFT LCD screen.
This screen as well can be powered through the Raspberry Pi GPIO pins. So now the Pi, the amp, and the LCD screen can all be powered through a single source and can be self contained. Here's a diagram of how to wire the LCD to the Pi Zero and how it connects to the Raspberry Pi "Bonnet"
LCD | Raspberry PI |
---|---|
LITE | 3.3v (or 5v) |
MISO | -- |
SCK | GPIO 11 (SCKL) |
MOSI | GPIO 10 (MOSI) |
TFT CS | GPIO 8 (CE0) |
CARD CS | -- |
O/C | GPIO 24 |
Reset | GPIO 25 |
VCC | 3.3v (or 5v) |
GND | GND |
Download the Fritzing diagram here
To get the LCD working, you need to run a few command line scripts. So again, open up an SSH terminal and type these commands:
sudo raspi-config
(go to Interface options and enable SPI)
sudo modprobe bcm2835-v4l2 sudo modprobe fbtft_device name=adafruit18
then you can download an image and push it to the LCD screen
wget http://static.musictoday.com/store/bands/1346/product_medium/BGCDMS02.JPG sudo fbi -T 2 -d /dev/fb1 -noverbose -a BGCDMS02.jpg
If everything goes right, you should see the image you downloaded on the LCD screen. But as of right now, we would have to run those "modprobe" scripts every time we reboot the Pi. So we need to automatically start them at every boot. Here's how to do it.
First create a new file called "fbtft.conf"
sudo nano /etc/modules-load.d/fbtft.conf
Add these two lines to this new file:
spi-bcm2835 fbtft_device
Now create a new modprobe file:
sudo nano /etc/modprobe.d/fbtft.conf
And add this line to it (the "adafruit18" is for the 1.8" tft)
options fbtft_device name=adafruit18
With that done, everytime you reboot, the screen should automatically be initialized.
[slogan id="step5" h1="Step 5" h3="Installing the Spotify Software"]
Now it's time to add the magic smoke! Since the goal here is to have a radio that streams Spotify, we'll need to find some software that connects to it and plays whatever song we choose. Another requirement is that we essentially want this to run in "headless" mode, which means we want the software to run automatically and startup with no user intervention.
At first, the logical solution would be to use the Spotify web API. This would allow us to write a program that can get song information, get playlists, play songs, etc. The biggest issue is, however, that the song tracks are limited to 30 seconds, so that essentially takes it off the list as a viable candidate.
After doing more research, I stumbled across Mopidy, which is a python based music playing application for the Raspberry Pi. It can play music from several sources, including locally, Google Music, Soundcloud, and of course Spotify. The only catch, however, is that it requries a Spotify Premium account.
Setting up Mopidy with the Spotify client on the raspberry Pi is super simple. Just run the command below:
pip install Mopidy-Spotify
Now we'll need to edit some of the configuration settings to make sure it connects and plays correctly.
nano ~/.config/mopidy/mopidy.conf
Scroll down to the [spotify] section and enter in your username and password.
[spotify] enabled = true username = your_username password = your_password
Also, check the [mpd] section to make sure it's enabled and set to the correct host and port names, like below.
[mpd] enabled = true hostname = 0.0.0.0 port = 6600 password =
Then type CTRL+X to exit the nano editor, and Y to save the changes. Then reboot your Pi with
sudo reboot
After the Pi comes back up, and you can establish another SSH session, you can start Mopidy simply by typing
mopidy
It will start up the mopidy server so that you can connect to it....but how do you connect to it?
Mopidy is also a Music Player Daemon (MPD) server. And MPD has many different clients across many different platforms. So you can download an MPD client on Windows, Mac, Linux, iOS, and Andriod and use that to control your music in Mopidy. You can use whichever one works best for you.
- MPDroid Android client
- MPDroid Interface
So with the Mopidy server running on your Pi, you should be able to enter the Pi's IP address (that we set earlier) into the settings of the MPD software to connect to it. Then you can remotely control what's playing on your Pi.
To make it so that Mopidy automatically starts up when the Raspberry Pi starts up, you first need to copy over our config settings to the mopidyctl user
sudo cp /etc/mopidyctl/mopidy.conf /etc/mopidyctl/mopidy_baksudo cp ~/.config/mopidy/mopidy.conf /etc/mopidyctl/mopidy.conf
Then just run this command to auto-start it!
sudo systemctl enable mopidy
[slogan id="step6" h1="Step 6" h3="Adding Physical Knob Controls"]
What would a radio be without physical knobs that you turn to control it? But adding custom physical controls to a computer can sometimes be tricky. First, let's decide what these knobs will do. I'd like to have two, and I want one that can control the volume and one that can power the Pi on and off (although that can be tricky in itself).
My first thought was to grab a couple of potentiometers and control the Pi with them. But potentiometers are analog controls, which means we'd need some type of extra converter (ex. Arduino) to convert the analog signal to digital. Then I stumbled across a better option: rotary encoders, which are very similar, except the output is digital. There are even rotary encoders that also act as a push-button as well. So let's see how we can use these to make our controls
Power Control
As I mentioned before, adding a physical shutdown/power up switch for the Raspberry Pi can be tricky. If we simply added a switch between the Pi and a power supply, this will essentially cut all power to the Pi while it's running, which can cause damage to the software and hardware of the Pi. So a better way would be to add a button that sends the Pi the shutdown command to power it down. Then we can use that switch to kill the power once it's been safely shutdown.
With that in mind, I found this great guide on gilyes.com for adding a shutdown/reset button on the Raspberry pi. The guide and code is for use with a push-button, and luckily the rotary encoders I purchased also have a push-button function. So instead of turning the knob to turn it off/on, you have to push the knob. But hey, it works and keeps the aesthetic. Here's how to connect it up:
Rotary Encoder | Raspberry Pi |
---|---|
GND | GND |
+ | -- |
SW | GPIO 3 (SCL) |
DT | -- |
CLK | -- |
Download the Fritzing diagram here
With the encoder connected, the last thing to do is add a little script and set it to start whenever the computer starts up. Start by making a scripts directory:
mkdir scripts
Then clone the pi-shutdown script to your raspberry pi and move it to our scripts folder.
git clone https://github.com/gilyes/pi-shutdown.git cd pi-shutdown sudo mv pishutdown.py scripts/pishutdown.py
Next, create a new "systemd" service called "pishutdown.service"
sudo nano /etc/systemd/system/pishutdown.service
And put this in the new files contents:
[Service] ExecStart=/usr/bin/python /home/pi/scripts/pishutdown.py WorkingDirectory=/home/pi/scripts/ Restart=always StandardOutput=syslog StandardError=syslog SyslogIdentifier=pishutdown User=root Group=root [Install] WantedBy=multi-user.target
Now we can enable the service by typing this:
sudo systemctl enable pishutdown.service
and then starting the service will keep it running even after a reboot:
sudo systemctl start pishutdown.service sudo reboot
After the reboot, you should be able to press the encoder button quickly to restart the Pi, and then hold it down for 5 seconds or more to shut it down. If you want to start it back up, just press the button again.
Volume Control
One knob down, one more to go! Time to tackle the volume knob. Using another rotary encoder, I was able to find this guide on modmypi.com for letting it control the volume on the Pi. I changed the guide a little to fit my design more (pin 18 was already being used), so here's how I connected it up:
Rotary Encoder | Raspberry Pi |
---|---|
GND | GND |
+ | 3.3v |
SW | -- |
DT | GPIO 27 |
CLK | GPIO 17 |
Download the Fritzing diagram here
And now for the code that makes it work (adapted from the ModMyPi code). You can also view it online at my Github page. https://github.com/gigafide/raspberrypi_spotify_radio
cd~ git clone https://github.com/gigafide/raspberrypi_spotify_radio.git cd raspberrypi_spotify_radio mv volume.py scripts/volume.py
Then, like before, let's create a new service for it so that it automatically boots with Raspbian.
sudo nano /etc/systemd/system/volume_control.service
And put this in the new files contents:
[Service] ExecStart=/usr/bin/python /home/pi/scripts/volume.py WorkingDirectory=/home/pi/scripts/ Restart=always StandardOutput=syslog StandardError=syslog SyslogIdentifier=volume_control User=root Group=root [Install] WantedBy=multi-user.target
Now we can enable the service by typing this:
sudo systemctl enable volume_control.service
and then starting the service will keep it running even after a reboot:
sudo systemctl start volume_control.service sudo reboot
To test it out, launch your favorite MPD client and start some music playing. Then use the encoder knob to adjust it!
[slogan id="step6" h1="Step 7" h3="Creating The Cover Art Software"]
Now that we have the music playing, let's see if we can make something that detects the current song playing and pulls the Cover Art for that song from the web and displays it on our little LCD screen.
LastFM has a good database of artists and album art, as well as an easy to use API. So I signed up for a developers account, and it gave me an API key to use in my programs.
Now that we have a place to get album art, let's figure out how to know what song is currently playing on MPD. Searching the internet, I found python-mpd2 a simple python client that can extract information from an MPD server (such as artist, album, playtime, etc.)
pip install python-mpd2
In it's library you can use calls like
MPDClient.currentsong()['artist']
to get the artist name, and
MPDClient.currentsong()['artist']
to get the album name.
Also, we will need to install the python "urllib" so that we can retrieve images from a URL.
pip install urllib2
And with that, I was able to combine those libraries to create this script on github: https://github.com/gigafide/raspberrypi_spotify_radio/blob/master/cover-art.py
If you've already downloaded the volume control script in the previous step, then you already have a copy of my cover-art.py script on your Pi. So let's set it to start on boot.
cd~ cd raspberrypi_spotify_radio mv volume.py scripts/volume.py
Then, like before, let's create a new service for it so that it automatically boots with Raspbian.
sudo nano /etc/systemd/system/coverart.service
And put this in the new files contents:
[Service] ExecStart=/usr/bin/python /home/pi/scripts/cover-art.py WorkingDirectory=/home/pi/scripts/ Restart=always StandardOutput=syslog StandardError=syslog SyslogIdentifier=coverart User=root Group=root [Install] WantedBy=multi-user.target
Now we can enable the service by typing this:
sudo systemctl enable coverart.service
and then starting the service will keep it running even after a reboot:
sudo systemctl start coverart.service sudo reboot
Now whenever you play a song on the Pi, it should download the album art and display it on the screen!
[slogan id="step8" h1="Step 8" h3="Giving It Power"]
The great thing about the Raspberry Pi is that it uses very little power. It can easily be run by using a power bank that's normally used to charge cell phones. I found a 2500 maH power bank on Amazon. And the first thing I did was remove the casing leaving just the battery and the charging board. I then de-soldered the USB cable and added a slide switch, so that it can easily cut the power to the Pi. Finally, I extended the leads between the battery and the charging board so that it could fit better in the casing (which will get to in the last step).
[slogan id="step9" h1="Step 9" h3="Making The Radio Case"]
Finally it's time for the fun stuff (not that it hasn't been fun up to this part)! To give this project the "vintage radio" asthetic, we need to make a nice looking case. If you have an old vintage radio laying around, your welcome to shove all these components into it and resurrect it as a streaming radio, but in my case, I needed to make my own. Browsing online for inspiration, I found this cool looking Emerson AX-212.
With this as my muse, I opened up Tinkercad and designed a 3D model that mimics the design, but is scaled to fit the Raspberry Pi, LCD, Speaker, and all the other components (I took a ton of measurements). Then it was just a matter of downloading it as an STL file and 3D printing it. To give it a more Antique look, I spray painted it with a "hammered metal" textured spray paint.
Then it was just a matter of fitting in all the different components.
Then finally, it's time to flip the switch to turn it on, connect to it with your favorite MPD client, and let the music play!