FUN WITH LINUX

How to build a music-box for children

2 January 2021

The Tonibox is a music player for children. They can simply place figures on the box and depending on the figure, a corresponding audio book is then played. I like this concept and since my child loves audio books, I am going to build such a box.

Note: I never had an original Tonibox in my hands. So I don’t know about it’s exact features and also don’t know how it really works. This article simply describes how I would build such a device.

Overview

In this article I am going to build a “Tonibox-like” device with the following components:

  • wooden box (160x160mm)
  • PN532 NFC-Reader
  • 3 Watt audio speakers
  • PAM8403 amplifier
  • Raspberry PI 4
  • Spotify(premium account)
  • Local Audio Files
  • Pink LEDs + resistors

Near-field communication

Picture of a pn532 nfc-reader module

Let’s think how the original Tonibox might work. I believe that the figures might have built-in NFC-tags. As soon as they are placed on the reader, it reads the ID of the tag and plays the audio book. That’s why I bought the PN532-reader(see Figure 1). It’s very cheap and works perfect for my purposes. This chip can be controlled via SPI, UART or I2C. After some research, it seam that I2C needs just view cables, but might be not very stable. UART has a quite slow bitrate. I2C is faster but more unstable. So I decided to use SPI. According to https://www.schnatterente.net/technik/nfc-raspberry-pi-pn532-breakout-board/5 SPI works rather fast and stable with the PN532 chip. In order to use SPI, a jumper must be set. The following diagram shows how to connect the chip to the Raspberry PI and how to set the jumpers for SPI.

Wiring schema of the PN532 with the Raspberry PI

After connecting the nfc-reader it’s time for the software. The easiest way to access the reader is by using the libnfc(link). It can easily installed via apt:

apt install libnfc-bin libnfc-dev libnfc-examples libnfc-pn53x-examples libnfc5:armhf

I use the following configuration to use the PN532 chip via SPI:

allow_autoscan = true
allow_intrusive_scan = false

log_level = 1

device.name = "_PN532_SPI"
device.connstring = "pn532_spi:/dev/spidev0.0:500000"

Now let’ try to access it. The libnfc comes with a tool “nfc-poll”. We will use it to read the ID of the nfc-tag with the following command:

sudo nfc-poll

I modified the source code of nfc-poll and made a nfc-daemon(https://github.com/whotwagner/nfc-daemon) that executes events when a nfc-tag is detected and when it is removed. Installation is rather simple:

git clone https://github.com/whotwagner/nfc-daemon
cd nfc-daemon
make
sudo make install
sudo cp docs/nfc-daemon.service /etc/systemd/system/nfc-daemon.service
sudo systemctl enable nfc-daemon.service
sudo systemctl start nfc-daemon.service

We can test the nfc-daemon by editing “/usr/local/share/nfc-daemon/run_script”:

#!/bin/bash
echo -n "hello world: "
echo $@

We also need a stop_script “/usr/local/share/nfc-daemon/end_script”:

#!/bin/bash
echo "Goodbye World"

Music-Daemon: Mopidy

By using the nfc-daemon, we can now execute scripts. Finally it’s time to play music. I decided to use the music-daemon mopidy to do the playback. Mopidy plays music from local disk, Spotify, SoundCloud, TuneIn, and more. You can edit the playlist from any phone, tablet, or computer using a variety of MPD and web clients. The installation is straight forward. I followed the guide in the mopidy-documentation and installed the mopidy-server via pip3. In addition I also installed the following modules:

  • Mopidy-Mopify
  • Mopidy-MPD
  • Mopidy-MPRIS
  • Mopidy-Spotify
  • Mopidy-Spotify-Web

For Spotify we also have to create credentials. We need a spotify premium account for that. I just followed the guide at https://mopidy.com/ext/spotify/. The client_id and client_secret must be used in the configuration. I experienced some strange problems, therefor I also added the spotify-username and spotify-password to the config. I actually don’t know if it also works somehow without the spotify credentials. I also believe that Mopidy-Spotify-Web is not necessary to install.

/etc/mopidy/mopidy.conf:

[audio]
output = alsasink

[spotify]
enabled = true
username = SPOTIFY_USER
password = SPOTIFY_PASS
client_id = CLIENT_ID
client_secret = CLIENT_SECRET

[spotify_web]
client_id = CLIENT_ID
client_secret = CLIENT_SECRET


[mopify]
enabled = true
debug = false

[http]
enabled = true
hostname = 0.0.0.0
port = 6680
zeroconf = Mopidy HTTP server on $hostname
allowed_origins = 
csrf_protection = true
default_app = mopidy

If you want to test the sound-server, you can do that by using mpc (command-line-client) or by using the ncurses based client “ncmpcpp”.

WIFI

I do not want any cables but the loading cable on the Tonibox. So I configured wifi. I configured the raspberry pi to connect to two networks. One is my home-wifi, and one is a non-existent network. The latter one I create with my mobile phone when we are not at home.

/etc/wpa_supplicant/wpa_supplicant.conf:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=AT

network={
	ssid="home-net"
	psk="home-net-password"
	key_mgmt=WPA-PSK
	id_str="home"
	priority=1
}

network={
	ssid="mobile-hotspot"
	psk="mobile-hotspot-password"
	key_mgmt=WPA-PSK
	id_str="mobile"
	priority=2
}

Bootsound

In order to play a sound if the box is booted, I also want to have a nice sound that indicates that it is up and running. I downloaded a nice wav-file from soundbible.com and configured a boot-script “/usr/local/bin/bootsound.sh”:

sleep 15s # dirty hack to be sure that it is booted
mpc clear
mpc add file:///home/pi/SoundEffects/boot.wav
mpc play

A systemd-service will execute this script. So let’s create the systemd-service “/etc/systemd/system/bootsound.service”:

[Unit]
Description=Boot Sound
After=avahi-daemon.service
After=dbus.service
After=network.target
After=nss-lookup.target
After=pulseaudio.service
After=remote-fs.target
After=sound.target
After=mopidy.service
After=mopidy.service

[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/usr/local/bin/bootsound.sh

[Install]
WantedBy=default.target

Now we just have to set the permissions and enable the systemd-service:

chown root.root /usr/local/bin/bootsound.sh
chmod 755 /usr/local/bin/bootsound.sh
systemctl enable bootsound.service

Audio Hardware

Image of the PAM8403 Module

I want to keep things simple. In order to avoid a special power adapter, I simply use an amplifier that works with low power and connect it to the 5V Raspberry PI power-pins. I found the PAM8403 amplifier module. It works with 5Volt and allows to connect two 3 Watt audio speakers. By soldering a cable to the amplifier, it is possible to connect it to the sound output of the Raspberry PI

Finally I also need 3 Watt speakers and I will use the Visaton 2242. They are not very special, work with 2 Watt and 8 Ohm and might be enough for a “toy”.

Image of a Visaton 2242 audio speaker Image of the wiring: raspberry pi connected to the amplifier that has the two speakers connected

Joni – Connecting NFC and Mopidy

The final component is the script that identifies the UID of the nfc-card and looks it up in a database in order to play it using the Mopidy server. I want to make this script as simple as possible. That’s why I didn’t use any database at all and use a simple yaml-file instead. Since I don’t expect too many entries, it might be okay. The outcome is a script called “joni”.

Installation:

git clone https://github.com/whotwagner/joni.git
cd joni
sudo pip3 install .
sudo cp bin/jon.py /usr/local/bin/jon.py
sudo chmod +x /usr/local/bin/jon.py
sudo mkdir /etc/joni
sudo touch /var/log/joni.log
sudo chown pi.pi /var/log/joni.log

Now create the config-file /etc/joni/config.yml:

volume: 45
timeout: 10

tracks:
    - id: 029i2939392a
      description: "Petronella Apfelmus - Zaubertricks und Maulwurfshuegel"
      play: 
        - spotify:album:3HJSMsKWgmP5OCss1UD2p5

    - id: 0298383219f
      volume: 20 # you can set a volume per playlist
      description: "Das Beste ueberhaupt"
      play: 
        - file:///home/pi/Kindercds/Geschichten/Track01.wav
        - file:///home/pi/Kindercds/Geschichten/Track02.wav
        - file:///home/pi/Kindercds/Geschichten/Track03.wav
        - file:///home/pi/Kindercds/Geschichten/Track04.wav
        - file:///home/pi/Kindercds/Geschichten/Track05.wav

In order to run joni we have to edit the run- and end-script.

/usr/local/share/nfc-daemon/run_script:

#!/bin/bash
# concats the id:
VAR=`echo $@ | awk '{ gsub (" ", "", $0); print}'`

/usr/local/bin/jon.py -d -L /var/log/joni.log --start $VAR

/usr/local/share/nfc-daemon/end_script:

#!/bin/bash

/usr/local/bin/jon.py -c /etc/joni/config.yml --stop

The Wooden Box

It’s rather difficult to make a toy for a child. It has to be “unbreakable”, but must not be too heavy. Choose the wood wisely and make the “walls” rather thick! I made the mistake that I used beech wood. It’s much to heavy and very hard. On the other hand, it’s a very beautiful wood.

Since I am not very good at working with wood, my uncle helped me out and made the box(160x160x160mm) with walls that are about 30mm thick.

Empty wooden box empty wooden box without any electronics Wooden box with built-in raspberry pi Music-Box with speakers and transparent plastic on top

Pink LED Indicator

My box is a massive box made of wood. I want to place the nfc-reader on the top of it and want to have a small distance between card and reader. That’s why I bought a simple pocket-mirror and used just one half of it. Since it is made of transparent plastic, it would be beautiful to place LED’s there. They light up when a card is placed. I use 4 LED’s. That’s too much current for one GPIO-pin. As far as I know the Raspberry PI 4 GPIO-pins support up to 16mA. So I connect the LED’s with 4 GPIO-pins. One LED with a resistor per pin. I picked a 330Ohm resistory so that I have 10mA per GPIO-pin. In order to initialize the GPIO-pins, I placed the code in /usr/local/bin/bootsound.sh:

#!/bin/bash

sleep 10s
echo "26" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio26/direction
echo "0" > /sys/class/gpio/gpio26/value

echo "19" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio19/direction
echo "0" > /sys/class/gpio/gpio19/value

echo "13" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio13/direction
echo "0" > /sys/class/gpio/gpio13/value

echo "6" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio6/direction
echo "0" > /sys/class/gpio/gpio6/value

echo "5" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio5/direction
echo "0" > /sys/class/gpio/gpio5/value

mpc clear
mpc add file:///home/pi/SoundEffects/boot.wav
mpc play

/usr/local/share/nfc-daemon/run_script:

#!/bin/bash
VAR=`echo $@ | awk '{ gsub (" ", "", $0); print}'`

echo "1" > /sys/class/gpio/gpio26/value
echo "1" > /sys/class/gpio/gpio19/value
echo "1" > /sys/class/gpio/gpio13/value
echo "1" > /sys/class/gpio/gpio6/value
echo "1" > /sys/class/gpio/gpio5/value

/usr/local/bin/jon.py -d -L /var/log/joni.log --start $VAR

/usr/local/share/nfc-daemon/end_script:

#!/bin/bash

/usr/local/bin/jon.py -c /etc/joni/config.yml --stop

echo "0" > /sys/class/gpio/gpio26/value
echo "0" > /sys/class/gpio/gpio19/value
echo "0" > /sys/class/gpio/gpio13/value
echo "0" > /sys/class/gpio/gpio6/value
echo "0" > /sys/class/gpio/gpio5/value

Image shows the nfc-reader module that is placed on top of the wooden box

Special Thanks

This box wouldn’t be as perfect as it is now if there weren’t some friends who helped me. I want to thank “Jumpy” and his friends who made most of the wooden box. I also want to thank “Brother Patrick” with his super-cool soldering station, who showed me how to solder properly and who helped me making the electronics just perfect. And last but not least to my neighbor who printed all the labels for the NFC-cards.

Final words

It was very easy to create a Spotify-powered homemade Tonibox and it was a lot of fun for me. My child was more than delighted and listens to the audio books every day.

[ Programming  C  HackADay  Raspberry  Music  Hardware  ]
Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 Unported License.

Copyright 2015-present Hoti