Fork me on GitHub

Podcast In a Box Step by Step

15 Apr 2015 by Libby Miller

Cross-posted from Libby's blog

Introduction

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.

IMG_3914

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).

Things you'll need

Ingredients

  • Raspberry Pi (B or B+, because you need 2 USB ports, I used a B+ and these instructions assume that)
  • Mini speaker with USB power / charging and 3.5mm jack (example)
  • Explore NFC Raspberry Pi shield
  • 8G or 4G (micro) SD card suitable for the Pi (example)
  • WiPi or similar wifi card (RT5370 chipset)
  • Power supply for the Pi (example)
  • Microswitch (example) + 2 screws to attach it
  • 6 M/M jumper wires (example), two attached to crocodile clips
  • 2 M/F jumper wires (example)
  • 1 RGB LED common cathode (example)
  • Small breadboard ideally with a sticky back (example)
  • 3 x 1K resistors
  • Oyster card or similar MIFARE card
  • Small box with a lid (example)
  • Thin balsa wood (~ 0.3mm width) or thick card
  • A bit of thicker balsa wood (I used 1cm square) or something similar, to trigger the lid button
  • Glue (for the balsa wood lid trigger)
  • Optionally: keyboard, mouse and screen, HDMI cable (for the Pi)

rdan_ingredients

Tools

  • Electric drill
  • Screwdriver
  • Soldering iron and solder
  • Laptop
  • Hacksaw

Putting it all together requires basic linux commands and editing, but no programming.

Method

1. Put the operating system on the SD card

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 -

  • using a separate card reader rather than the built-in Mac one (if that's what you have)
  • you can try $ 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.

2. Assemble the basic elements

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:

IMG_3912

3. Get the wifi working and test

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.

rdan_wifi1rdan_wifi2rdan_wifi3

Make sure you rejoin your usual wifi network.

4. Test the vanilla Radiodan

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:

rdan_default

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.

5. Log into the Radiodan

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)

6. Overclock and enable SPI interface

$ sudo raspi-config

Reboot: $ sudo reboot

Overclock to Medium

Enable the SPI interface (sudo raspi-config -> advanced -> enable SPI)

7. Disable Radiodan updates

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

8. Download the podcast software

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.

9. Install dependencies

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).

10. Install the podcast app

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

11. Check everything's running

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

13. Test the podcast app

$ 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

14. Solder some wires on to the NFC shield

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:

rdan_wire1

and also tin the places where you’ll be adding the wires:

rdan_nfc1

(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.

rdan_wire_nfc

15. Assemble the LED components

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

rdan_led1

and then add the ground:

rdan_led2

16. Add the button

This uses WiringPi pin 3 and another ground pin, via the breadboard again:

rdan_button1

The “COM” terminal of the switch goes to ground and the pin 3 wire goes to “NO” (normally open)

rdan_button2

17. Try it all out - Programme a card

rdan_ui rdan_write1

rdan_write2 rdan_write3

  • Save

rdan_write4

After a few seconds it should start playing the audio from your feed and the light should go green.

18. Test behaviour

  • Click the switch shut - while you hold it, it should stop the audio and the light should go blue
  • Release the switch and it should restart the audio and the light should go green
  • Remove the Oyster card and it should stop the audio again, and the light should go green
  • Add the Oyster card again and it should restart from approximately the same point

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.

19. Drill holes in the box

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.

rdan_microusbrdan_power

You may also want to add holes for ventilation - it can get warm (but not very hot).

rdan_vent

20. Add the switch

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.

rdan_switch

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.

rdan_lidrdan_shelf

21. Put everything in the box

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.

rdan_inbox

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.

rdan_box_shelf

22. Test again

rdan_box_test

rdan_card_shelf

DONE

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).

rdan_cards2

rdan_cards1