Thomas' writings, builds, toys

2019-02-01

RFID Card Jukebox with Raspberry Pi

application sugestion

When a friend of mine showed the awesome little wooden Jukebox he made for his kids, I loved the idea, and knew I could make a similar contraption by recycling an old Raspberry Pi 1 I had on a shelve.

After I was finished I published build instructions on GitHub, along with the code I used, if someone wants to reproduce this. The article you are reading now is actually the story of the making of it.

First, I ordered some RFID cards and a USB connected card reader from Aliexpress, since the long delivery time would hold up the project:

cards cardreader

This kind of card reader presents itself as a keyboard to the computer that is connected to it, so when scanning a card, the number printed on the card will be 'typed' into the computer by the reader.

True to the UNIX philosphy, playing the songs should be done with simple MP3 player application like mplayer or sox. That can run as a subprocess.

It turned out that there is a significant delay on the Raspberry Pi 1 before the music actually starts playing. So I ended up running the jukebox on a Pi 2 that was already sitting in the TV cabinet.

apt-get install sox libsox-fmt-mp3 alsamixer

Next I got to work in Python, and wrote a small script that would read the number typed, finds a file that starts with the number and, if found, it will start the MP3 player application.

import subprocess
import sys, glob
player = None
while True:
    print("player ready:",)
    code = raw_input()
    for filename in glob.glob("*"):
        if not filename.startswith(code):
            #not the file we want, check next
            continue
        if player:
            #stop player if already playing
            player.terminate()
            player = None
        print("playing ", filename)
        player = subprocess.Popen(["play","-q", filename], stdin=subprocess.PIPE, stdout=sys.stdout,stderr=sys.stdout,bufsize=1)

I ended up extending the script with a 'lock' function that will disable/enable the player with a special card, and added a 'stop' card, to stop the playing song.

Next came the system integration. I didn't find an easy way to read the card reader from python, so instead, I replace the logon process on the raspberry pi with the script. Instead of getting asked a username and password to login, the pi instead waits for a card number to be typed in.

This is done by creating a systemd service file that starts the script on tty1:

[Unit]
Description=play on tty1

[Service]
Type=simple
ExecStart=/usr/bin/python /home/pi/play.py
ExecStop=/bin/kill -HUP $MAINPID
StandardInput=tty
StandardOutput=tty
#StandardOutput=journal
StandardError=journal
WorkingDirectory=/home/pi
TTYPath=/dev/tty1
Restart=always
RestartSec=2

[Install]
WantedBy=getty.target

We can install it, and enable this service file instead of the getty on tty1 like this:

sudo install -m 644 play.service /etc/systemd/system/play.service
sudo systemctl daemon-reload
sudo systemctl mask getty@tty1.service
sudo systemctl enable play.service
sudo systemctl start play.service

Crafting time

After compiling a set of song MP3's that Arthur likes, I made labels with pictures representing the songs a bit. I finished off the label with adhesive vinyl (the one used with school books).

application sugestion

I also made a piece of paper with an musical notes on it and I laminated it. (you can find that in the artwork/ folder on the GitHub project)

Installing

I installed the RFID card reader using double sided tape behind the glass front of our TV furniture.

installed in furniture

Operation

When the RFID reader outputs a card code, the player checks if a filename starting with the code (and a dash) exists. If found, it starts playing it.

There are two special cards:

  • The "key" card: to unlock/lock the player
  • The "stop" card: to stop playing the current song

To identify these special cards to the player, create empty files with the words key and stop. Next rename them to prefix them with the text generated by the RFID reader for those cards, just like is done with the MP3's.