Cross-posted from Libby's blog
Podcast-player-in-a-box is a way to associate a physical object (a plastic card) with a possibly-changing list of audio files. When you put the card in the box it plays the audio.
It’s inspired by this lovely project to make an audiobook reader and also by Jasmine Cox’s enchanted objects.
I’m particularly interested in using it with Huffduffer, an excellent site that enables you to build your own podcast of audio files.
Podcast-player-in-a-box matches contactless cards of a particular type (MIFARE) with podcast feeds. MIFARE cards are very common - Oyster cards for example, and many ID cards, so there are plenty of them around (I had 6 in my house, or you can buy them easily), and there’s a cheap and easily available shield for them for the Raspberry Pi.
The box enables you to “programme” a card for a particular podcast. It doesn’t actually write to the card, just reads the id and maintains matches between card ids and urls. A card has to be present to play, and when the box is shut it stops playing. If it finds a new item in the podcast, it plays that, otherwise it remembers roughly where you last were in the podcast.
I made it because I want to listen to audio podcasts on a device, rather than a mobile or a laptop, because that’s how I listen to the radio. I also want to be able to switch between different podcasts very quickly, easily and intuitively.
It’s also a test for me of Radiodan, the radio prototyping platform we’ve been working on. Radiodan allows you to add new radio apps and flip between them. I wanted to see how quickly I could prototype something using the platform (answer - I got quite far in a day, but it’s taken me a couple of weeks to iron out the bugs).
You can see the podcast-in-a-box in action in this video.
Here are step-by-step instructions. It’ll take about 2 hours once you have the SD card written - so maybe 3-4 hours in total (but you can do something else while the SD card is writing. Much of the 2 hours is also waiting for stuff to install).
Putting it all together requires basic linux commands and editing, but no programming.
I recommend using an 8GB SD card tested with the PI - Radiodan does a lot of writes to the disk and not all cards are up to it. The Radiodan image is Ubuntu Wheezy with some extra Open Source code for playing audio streams, and managing wifi. If you like, you can use a 4GB card instead of 8GB - there’s a separate image for that in this directory.
Get the Radiodan 8GB SD card image:
curl -O http://dev.notu.be/2014/12/radiodan/2014-12-23-radiodan.img.gz
Plug the SD card into the laptop using a card reader. List disks:
$ diskutil list
Find the disk number (e.g. “2”). Unmount that disk.
$ diskutil unmountDisk /dev/diskX
Unzip and write the image in 1 step:
$ gzip -dc /path/to/2014-12-23-radiodan.img.gz | sudo dd of=/dev/diskX bs=1m
This part can take a long time (74 minutes last time I tried). You can speed it up by -
$ gzip -dc /path/to/2014-12-23-radiodan.img.gz | sudo dd of=/dev/rdiskXXX bs=1m
("rdisk" rather than "disk") - but I find this can corrupt the disk.Put the SD card in the Pi, and the wifi card in one of the USB ports. Plug in the speaker into another USB port and into the 3.5mm audio socket. Plug the Pi into the power supply and plug it into the mains. It should look like this:
Wait a minute or two for it to boot up, and you should see a wifi network appear (“radiodan-configuration”).
Connect to this new wifi network with your laptop. A web page should pop up, if it doesn’t, go to any web page. You should see a page load with a list of all the wifi networks available. Pick your usual one, and enter the details, and reboot the Pi when instructed.
Make sure you rejoin your usual wifi network.
Once the Pi has rebooted, you have the default Radiodan. It currently acts like an internet radio. You can test this by going to http://radiodan.local in a web page on your laptop.
You should see something like this:
Click on the power button and you should hear some radio playing. It can take a little while for it to be visible (you might get 404 Not Found
for a bit).
We’re going to change its behaviour by installing another app.
If you like you can do this using a keyboard and mouse and screen, but I usually just shell in from my laptop, since the Radiodan is on the wifi. This can be a bit slow depending on congestion in your wifi network.
$ ssh pi@radiodan.local
The password is the default pi password: “raspberry
” (without quotes)
$ sudo raspi-config
Reboot: $ sudo reboot
Overclock to Medium
Enable the SPI interface (sudo raspi-config -> advanced -> enable SPI)
Radiodan uses Monit to manage its processes. You can see what it’s doing by typing this:
$ sudo monit status
We want to disable Radiodan updates (updater_status) in case it overwrites the changes we’ve made; we also want to remove radiodan-cease (a utility to turn off the radio with the power button being held down, because we use the power button differently); and we’re going to replace radiodan-magic which is the default app with our own, so we’re going to stop Monit monitoring all those:
$ sudo monit stop updater_status
$ sudo monit stop radiodan-cease
$ sudo monit stop radiodan-magic
then you’ll see things like this:
$ sudo monit status
File 'updater_status'
status Not monitored
monitoring status Not monitored
data collected Fri, 02 Jan 2015 15:02:16
Radiodan keeps its apps in /opt/radiodan/apps
, so we’ll put it there.
$ cd /opt/radiodan/apps
$ sudo git clone https://github.com/libbymiller/radiodan-client-podcast.git
$ cd radiodan-client-podcast/
$ sudo chown -R pi:pi .
There are two pieces - a script in python that only talks to the NFC reader, and some node code (mostly in main.js) that controls the audio and runs a small web server.
Install the dependences for node
$ npm install
and for the python nxppy code (for interacting with the NFC reader)
$ cd
$ sudo apt-get update
$ sudo apt-get -y install build-essential python2.7-dev python-setuptools cmake
$ curl -O https://bootstrap.pypa.io/get-pip.py
$ sudo python get-pip.py
$ sudo pip install requests
Install nxppy:
$ git clone https://github.com/svvitale/nxppy.git
$ cd nxppy
$ sudo python setup.py build install
(nxppy didn’t seem happy being installed with pip, I didn’t investigate why).
Monit works using init.d scripts, so we need to add those, so that our app runs when the Pi is booted up.
$ sudo cp /opt/radiodan/apps/radiodan-client-podcast/init.d/radiodan-huffduffer /etc/init.d/
$ sudo cp /opt/radiodan/apps/radiodan-client-podcast/init.d/radiodan-nfc /etc/init.d/
and add these to Monit
$ sudo cp /opt/radiodan/apps/radiodan-client-podcast/init.d/radiodan-type-huffduffer /etc/monit/monitrc.d/
Change the config file for the physical UI:
$ sudo pico /etc/init.d/radiodan-buttons
change
DAEMON_OPTS="/opt/radiodan/apps/magic/current/config/physical-ui-config.json"
to
DAEMON_OPTS="/opt/radiodan/apps/radiodan-client-podcast/config/physical-ui-config.json"
Make a small edit to the buttons interface:
$ sudo pico /opt/radiodan/apps/buttons/current/lib/bootstrap.js
// Reverse the polarity of the neutron flow
// rgbOpts.reverse = true;
^^^ comment out this line, like this
Switch to the new app type
$ sudo radiodan-device-type radiodan-type-huffduffer
Reboot to make sure it all comes up.
$ sudo reboot
ssh in again
$ ssh pi@radiodan.local
$ ps ax | grep node
2126 ? Sl 0:11 /usr/lib/erlang/erts-6.1/bin/beam -W w -K true -A30 -P 1048576 -- -root /usr/lib/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /usr/lib/rabbitmq/lib/rabbitmq_server-3.3.5/sbin/../ebin -noshell -noinput -s rabbit boot -sname rabbit@radiodan -boot start_sasl -kernel inet_default_connect_options [{nodelay,true}] -sasl errlog_type error -sasl sasl_error_logger false -rabbit error_logger {file,"/var/log/rabbitmq/rabbit@radiodan.log"} -rabbit sasl_error_logger {file,"/var/log/rabbitmq/rabbit@radiodan-sasl.log"} -rabbit enabled_plugins_file "/etc/rabbitmq/enabled_plugins" -rabbit plugins_dir "/usr/lib/rabbitmq/lib/rabbitmq_server-3.3.5/sbin/../plugins" -rabbit plugins_expand_dir "/var/lib/rabbitmq/mnesia/rabbit@radiodan-plugins-expand" -os_mon start_cpu_sup false -os_mon start_disksup false -os_mon start_memsup false -mnesia dir "/var/lib/rabbitmq/mnesia/rabbit@radiodan" -kernel inet_dist_listen_min 25672 -kernel inet_dist_listen_max 25672 2554 ? Sl 0:11 node /opt/radiodan/apps/buttons/current/bin/server /opt/radiodan/apps/radiodan-client-podcast/config/physical-ui-config.json 2564 ? Sl 0:11 /usr/local/bin/node /opt/radiodan/apps/radiodan-client-podcast/main.js 2575 ? Sl 0:07 node /opt/radiodan/apps/server/current/bin/server /opt/radiodan/apps/magic/current/config/radiodan-config.json 2942 pts/0 S+ 0:00 grep --color=auto node
$ ps ax | grep python
2541 ? D 0:28 /usr/bin/python /opt/radiodan/apps/radiodan-client-podcast/accessCardReader.py 2951 pts/0 S+ 0:00 grep --color=auto python
Check for errors
$ tail /var/log/radiodan-huffduffer.log
$ tail /var/log/radiodan-nfc.log
$ curl -X POST http://localhost:5000/rssFromNFC -d "feedUrl=http://downloads.bbc.co.uk/podcasts/fivelive/kermode/rss.xml"
You should hear the podcast. Stop it like this:
curl -X POST http://localhost:5000/stopFromNFC
Now shut down the PI, as we’re going to attach the NFC reader.
sudo halt
One of the downsides of using a shield is that it uses most of the pins, even on the B+. We need to have some sort of a signal about what’s going on (an LED), and also a button for the closing-box-switching-off feature. The shield doesn’t actually use all the pins but it sits on all of them, so we need to solder the wires we need for the RGB led and the button onto some of the unused pins on the shield.
Because it’s a B+ there are a couple of spare ground pins available, so I just soldered the 4 pins I needed. Here’s a list of the pins the NFC shield uses, but it’s a bit vague, and I found the spare ones through trial and error.
The soldering is a bit tricky - what seems to work best is to make the pins short, tin them:
and also tin the places where you’ll be adding the wires:
(we’ll be using WiringPi wires 3,4,5,6 in this diagram - I’ve put a “*” next to them):
$ gpio readall
+-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | | | 3.3v | | | 1 || 2 | | | 5v | | | | 2 | 8 | SDA.1 | IN | 0 | 3 || 4 | | | 5V | | | | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | | | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT0 | TxD | 15 | 14 | | | | 0v | | | 9 || 10 | 1 | ALT0 | RxD | 16 | 15 | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 | | 27 | 2 | GPIO. 2 | OUT | 0 | 13 || 14 | | | 0v | | | | 22 | 3 | GPIO. 3*| IN | 1 | 15 || 16 | 0 | OUT | GPIO. 4*| 4 | 23 | | | | 3.3v | | | 17 || 18 | 0 | OUT | GPIO. 5*| 5 | 24 | | 10 | 12 | MOSI | ALT0 | 0 | 19 || 20 | | | 0v | | | | 9 | 13 | MISO | ALT0 | 0 | 21 || 22 | 1 | OUT | GPIO. 6*| 6 | 25 | | 11 | 14 | SCLK | ALT0 | 0 | 23 || 24 | 1 | ALT0 | CE0 | 10 | 8 | | | | 0v | | | 25 || 26 | 1 | OUT | CE1 | 11 | 7 | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | | 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | | | 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 | | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v* | | | | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 | | 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 | | | | 0v*| | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+
We’re soldering on the top of the NFC shield.
I happened to have some common cathode RGB leds - common anode ones are also available, but need different configuations. The cathode RGB LED’s longest leg goes to ground and then it’s
blue green [cathode] red
We connect them to WiringPi pins 6, 5 and 4 respectively, using the mini breadboard and the resistors
and then add the ground:
This uses WiringPi pin 3 and another ground pin, via the breadboard again:
The “COM” terminal of the switch goes to ground and the pin 3 wire goes to “NO” (normally open)
After a few seconds it should start playing the audio from your feed and the light should go green.
The basics are now done - we just need to put it in the box. Turn it off by unplugging it or doing sudo halt
if you are sshd in to the Pi.
The basic part is the hole for the power cable. Make a note of the maximum width and height of the small end of the power cable - that’s the hole size you need.
You may also want to add holes for ventilation - it can get warm (but not very hot).
Screw the switch on to the side of the box. Glue a bit of balsa wood or similar in the opposite corner of the lid, and test that when the box is shut you can hear the switch click.
While you are sawing, cut a couple of pieces of balsa wood, one to fit exactly across the lid and another across the width of the box to form a shelf.
Put everything in the box threading the power cable through the hole you drilled earlier. The arrangement will vary a bit depending on your box size and shape, but the important things are that the aerial of the NFC reader is accessible (the card doesn’t have to be flat on it though) and the LED is visible. Reconnect the croc clips to the switch.
I’ve added a little shelf in to make it easier to place the card. The range of the NFC is about 3-5 cm, but the closer the shelf is to it the better.
You can programme more cards and stick pictures on them to show what they will play. A Pogo printer is a great for this (but a normal printer and a pritt stick work perfectly well too).