Files
piplayer/documentation/qudio/index.html
T
2019-01-20 08:08:07 +01:00

565 lines
31 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Qudio - a QR-enabled Audio Player for Children</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta property="og:url" content="http://tilman.de/projekte/qudio/" />
<meta property="og:title" content="Qudio - a QR-enabled Audio Player for Children" />
<meta property="og:description" content="After building the first version of this music player for my oldest son in 2016, I recently had to update my project for his younger brother. As before, music can be played by simply placing a card with a QR code on the player. The new version has a improved case and is cheaper and easier to build. Internally it uses the volumio player which allows to not only play all MP3s from the local network, but also to connect streaming services like Spotify. Oh, an there is a rocket again, too. But this time it is optional." />
<meta property="og:image" content="http://tilman.de/projekte/qudio/images/qudio-01-space.jpg" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.6/dist/jquery.fancybox.min.css" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,800' rel='stylesheet' type='text/css' />
<!-- <link href='https://fonts.googleapis.com/css?family=Lora:400,400italic,700,700italic' rel='stylesheet' type='text/css' /> -->
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab:400,700" rel="stylesheet" type='text/css'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<style type="text/css" media="all">
<!--
body {
background-color: #FFFFFF;
color: black;
font-family: 'Roboto Slab', serif;
font-size: 160%;
}
p {
margin-top: 1.5em;
}
h1 {
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 800;
text-align: center;
color: #303030;
}
h2, h3, h4 {
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 800;
color: #303030;
margin-top: 1em;
}
#subtitle {
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 800;
font-weight: 800;
text-align: center;
color: #303030;
font-size: 120%;
margin-bottom: 2em;
}
.gallery {
text-align: center;
margin-top: 2em;
margin-bottom: 2em;
}
.timestamp {
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
text-align: right;
color: #888;
margin-top: 2em;
}
a > img {
margin: 2em;
}
.fancybox-title {
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.fancybox-caption {
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
-->
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.6/dist/jquery.fancybox.min.js"></script>
<div id="content" class="container">
<p class="timestamp">2019-01-20</p>
<h1>Qudio Player</h1>
<p id="subtitle">An easy-to-use music player for children based on the Raspberry Pi Zero and the JBL On Stage IIIp (again)</p>
<p class="well" style="text-align: center;">In spring 2016 I finalized the <a href="http://tilman.de/projekte/musikrakete/">&quot;Musikrakete&quot;</a>, an MP3 player that our boys could operate without assistance. Later on, there was a <a href="http://www.tilman.de/projekte/audiosphere/">second version</a>. This is the third version, with all of the improvements I came up with during the last three years. It is easier and cheaper to build, the case is way smaller and much more robust and by switching to volumio the player now supports remote control from the phone and streaming services like Spotify. This is all combined with the existing features like playing MP3s from the local network and, most importantly, being easy to use even for small children. So if your children love music and audio books just like mine, this might be a project for you.</p>
<h2 id="history">The Idea</h2>
<a data-fancybox style="float:right;" href="images/qudio-01-space.jpg" data-caption="The Qudio player (with the additional rocket). The QR cards are placed on the window on top of the case, where they are detected by a photo sensor that triggers the recognition process. After the code has been read by the webcam, the stream or MP3s it point to start playing."><img src="images/qudio-01-space.jpg"
width="480" alt="The Qudio player (with the additional rocket). The QR cards are placed on the window on top of the case, where they are detected by a photo sensor that triggers the recognition process. After the code has been read by the webcam, the stream or MP3s it point to start playing." /></a>
</p>
<p>
This project started in 2016, when Anica asked me if buying a <a href="https://de-de.hoerbert.com/">hörbert</a> MP3 player would be a good idea. At the time our boys wasted two to three CDs every week, trying to get some music out of the small player in their room. And the player in the living room also seemed to reach its end of life pretty soon due to their enthusiasm. Still I wasn't too sure about this hörbert thing. In order to get new files on the SD card of the player, the case had to be opened, the navigation with 11 buttons seemed a little confusing and a single speaker operated with four batteries also did not seem promising to me.
</p>
<p>
I had seen a <a href="http://www.die-schembergs.de/index.php?page=qr-music">project description of an MP3 player for small children</a> shortly before: A Raspberry Pi mini computer, connected to a webcam and speakers, reads QR codes and plays the respective track or playlist. So this was what I suggested and to my surprise it was considered a better solution right away. And I had a project.
</p>
<p>
As good as the project description seemed to be, I wanted to make some improvements on the original design: The player should detect the QR automatically, it should have buttons for play/pause and skipping and all components should be put together in a single case. Most importantly, the MP3 files should be delivered directly from our home server. No SD card replacement needed.
</p>
<p>
Since we had an old <a href="https://www.manualslib.com/manual/684236/Jbl-On-Stage-Iiip.html">JBL <em>On Stage IIIp</em></a> speaker lying around that wasn't used anymore due to its outdated iPhone dock connector, I decided to use this as a base. After playing around with <a href="https://www.onshape.com/">Onshape</a>, soldering and programming for three months, I had the <a href="http://tilman.de/projekte/musikrakete/">Musikrakete</a> ready by end of March 2016. It was a huge success with the boys and has been in heavy use ever since.
</p>
<p>
Over the last years I came up with some improvements on the original design and created a <a href="http://www.tilman.de/projekte/audiosphere/">second version</a>. But I always had some things in the back of my mind that I wanted to make better about both the hard- and the software and when the little brother moved into a room of his own, I knew it was time to bring all that to life. So this is the smaller, better and cheaper third version. The rocket on top is optional, by the way. But little brother would never have accepted a player that did not somehow include a rocket, since the original, rocket-shaped design is still used by the older one.
</p>
<div style="margin: 2em; text-align: center;">
<video controls><source src="Video to follow" type="video/mp4" /></video>
</div>
<h2 id="piplayer3">PiPlayer 3.0: Qudio</h2>
<p>
This third version now relies on <a href="https://volumio.org/">volumio</a> which can play music from streaming services like Spotify Premium or LastFM, has a nice web interface and does most of the configuration for us. The case is much smaller than before, which makes it sturdier and easier to print. The electronic parts are all easily obtainable standard compontents and even cheaper than before. Again, it is built on top of the JBL On Stage IIIp speaker, that can still be found on ebay for little money and provides a perfect base for a player like this.
</p>
<p>
The main component is now a Raspberry Pi Zero W, that can be run off the dock connector without an additional power source. I replaced the Pimoroni PHAT DAC with a dirt cheap audio module based on the same chip. The IR sensor that detects the QR cards is now a ready-made module which makes assembly easier. The buttons have been replaced by the ubiqitous standard components that come with every Arduino starter kit.
</p>
<h2 id="parts">Parts list</h2>
<ul>
<li>JBL On Stage IIIP</li>
<li>The <a href="https://github.com/tliero/qudio/tree/master/case">case, which consists of four parts</a>. I printed mine in standard PLA.</li>
<li>Raspberry Pi Zero W with a micro SD card</li>
<li><a href="https://blog.sengotta.net/connecting-a-pcm5102a-breakout-board-to-a-raspberry-pi/">CJMCU-5102 plus a 10 k&#8486; resistor</a>, some other PCM5102A based module or any other I2S DAC that is supported by volumio. Search for 'pHAT DAC'. A usb sound card will not work, since the USB port is used by the webcam.</li>
<li>TCRT5000 reflective sensor module</li>
<li>The ultra-cheap <a href="http://www.penguin.cz/~utx/hardware/USB_Camera_AX2311/">USB webcam</a> that can be found on ebay, aliexpress and the like (just sort for price). Some versions come with a small cable reel. This fits perfectly in the holder at the bottom of the case.</li>
<li><a data-fancybox href="images/usb-a-to-micro-usb-adapter.jpg">USB A to micro USB adapter</a> that connects the webcam to the Raspberry Pi's micro USB port</li>
<li><a data-fancybox href="images/30-pin-apple-dock-to-micro-usb-and-audio-adapter.jpg">30-pin Apple dock adapter to micro USB and 3.5 mm audio</a></li>
<li>White LED (preferably diffused) for illumination of the QR cards with a proper resistor</li>
<li>3 push buttons with 12 mm caps</li>
<li>Jumper cables: 6x M-F 10 cm for the buttons, 5x F-F 10 cm for the audio module, 4x F-F 20 cm for the sensor and the LED</li>
<li>A small sheet of acrylic glass / plexiglass (around 2 mm)</li>
<li>8 M3&times;8 screws with nuts</li>
<li>4 M3 <a href="https://www.3dhubs.com/knowledge-base/how-assemble-3d-printed-parts-threaded-fasteners#inserts">threaded heat-set inserts</a></li>
<li>Soldering iron, drill, screwdriver, glue gun, box cutter</li>
</ul>
<pre style="background-color:#ffff66">
deactivate microphone?
12 mm caps?
acrylic glass --> size?
</pre>
<h2 id="components">Assembling the Components</h2>
<h3 id="mount">Mounting the Base</h3>
<p>
</p>
<h3 id="wiring">Wiring</h3>
<h4 id="audio-module">Audio Module</h3>
<p>
Test 1, 2, 3
</p>
<h4 id="buttons">Buttons</h3>
<p>
</p>
<h4 id="sensor">Sensor</h3>
<p>
</p>
<h4 id="led">LED</h3>
<p>
</p>
<h2 id="software">Installing the Software</h2>
<p>
</p>
First step was the design of the new case. Like the first <a href="https://cad.onshape.com/documents/56f3cf83e4b02f6312a93771/w/785ccf8684baed006305bb0d/e/c68592f13fbf9a2c69b8dd05">rocket case</a> it's public, you can find it <a href="https://cad.onshape.com/documents/584e7d080f617710a60fc5d3/w/28f44a0afe402320fa3f3faa/e/765c3d5ab7a1032836866ac8">here on Onshape</a>. (You will need to create an account to open the document.) Or you can download the <a href="https://github.com/tliero/audiosphere/tree/master/case">STL files</a> for printing if you are using the very same components. Please note that you will need to rotate the top of the sphere 180° for printing. Also be careful about the Raspberry holder: The Raspberry Pi together with the PHAT DAC should have a <a href="images/phat_dac_measure.jpg" class="fancybox">height of 7.2 mm</a> (or less) which depends on the GPIO header that is used to solder the PHAT DAC to the RasPi. If the height exeeds that, the distance needs to be adjusted before printing.
</p>
<p class="gallery">
<a href="images/piplayer-04-04.png" class="fancybox" rel="collection01"><img src="images/piplayer-04-04.png"
width="320" alt="The base with the three main electronic components: The Raspberry Pi Zero with the PHAT DAC (blue), the USB hub with the ethernet port (green) and the camera with a representation of its viewport (black)." /></a>
<a href="images/piplayer-02-500.gif" class="fancybox" rel="collection01"><img src="images/piplayer-02-500.gif" width="320"
alt="Animation of the assembly" /></a>
<a href="images/piplayer-02-07.png" class="fancybox"
rel="collection01"><img src="images/piplayer-02-07.png" width="320"
alt="The assembled case" /></a>
</p>
<h2 id="system">Software</h2>
<h3 id="wi-fi">Configure Wi-Fi</h3>
<p>
</p>
<pre class="pre-scrollable">
# Scan networks and add Wi-Fi network to configuration (<a href="https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md">https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md</a>)
# (Close nano after editing with Ctrl-X)
sudo iwlist wlan0 scan
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
# network={
# ssid="The_ESSID_from_earlier"
# psk="Your_wifi_password"
# }
# Restart Wi-Fi
sudo ifdown wlan0
sudo ifup wlan0
# Check if Wi-Fi is connected
ifconfig wlan0
# Turn off
sudo shutdown -h now
</pre>
<h3>Remotely Finish the Setup</h3>
<p>
From here on you can connect via SSH over Wi-Fi. Unplug monitor, keyboard and the ethernet cable. It might also be helpful to configure a static IP for the Wi-Fi adapter in your router before continuing. Then restart the RasPi, <a href="https://www.raspberrypi.org/documentation/remote-access/ssh/">connect via SSH</a> from a different computer and go on with the setup procedure.
</p>
<pre>
# Now that remote connection is available, disable HDMI (<a href="http://www.jeffgeerling.com/blogs/jeff-geerling/raspberry-pi-zero-conserve-energy">http://www.jeffgeerling.com/blogs/jeff-geerling/raspberry-pi-zero-conserve-energy</a>)
# (This line has to go *before* "exit 0" at the end of the file)
sudo nano /etc/rc.local
# # disable HDMI
# /usr/bin/tvservice -o
# Add this to config.txt to disable the ACT LED
sudo nano /boot/config.txt
# dtparam=act_led_trigger=none
# dtparam=act_led_activelow=off
# Configure NTP
sudo apt install ntp
sudo nano /etc/ntp.conf
# add time server to /etc/ntp.conf (line 16)
# server de.pool.ntp.org
sudo /etc/init.d/ntp restart
date
# Turn off
sudo shutdown -h now
</pre>
<p>
Now that the RasPi is ready, the next step is setting up all the other hardware components: The speaker, the case and the electronics.
</p>
<h2 id="jblpreparation">Preparing the JBL IIIp Speaker</h2>
<p>
In order to drill the holes for the screws, the speaker has to be disassembled. The procedure is described <a href="https://de.ifixit.com/Guide/JBL+On+Stage+II+Speakers+Replacement/22462">here at ifixit.com for the predecessor</a> which works basically the same way: Remove the rubber pads, then remove all screws from the case. (Don't forget the center screw in the battery case.) Once the speaker case is opened, the circuit board is unscrewed and removed.
</p>
<p>
I drilled the holes for the M3 screws and the IR LED cable using a <a href="misc/audiosphere_drilling_template.pdf">template</a>. The drill itself is set to rotate left. That way, the holes are more or less melted into the plastic to lower the risk of breaking the case.
</p>
<p>
After drilling, washers and screws are added and the infrared LED is glued directly in front of the speaker's IR sensor in order to send it commands. Before that the PINs of the IR LED are soldered to cables that are long enough to connect it to the circuit board through one of the additional holes. Also, all the electronics should be tested together before anything is hot-glued into the case.
</p>
<p>
(Disclaimer: Until now, I only did a proof of concept test script for remote contolling the speaker via the IR LED. I am planning on using that component later on via a web app but for the time being you could as well leave it out.)
</p>
<p class="gallery">
<a href="images/jbl_01.jpg" class="fancybox" rel="collection02"><img src="images/jbl_01.jpg" width="320" alt="The opened speaker case with the drilling template" /></a>
<a href="images/jbl_02.jpg" class="fancybox" rel="collection02"><img src="images/jbl_02.jpg" width="320" alt="The re-assembled speaker with the IR LED in front of the IR sensor" /></a>
<a href="images/jbl_03.jpg" class="fancybox" rel="collection02"><img src="images/jbl_03.jpg" width="320" alt="The closed speaker case with the screws that hold the 3D printed case. (This photo was taken before adding the IR LED.)" /></a>
</p>
<h2 id="electronics">Electronics</h2>
<p>
When the speaker has been put back together, we can go for the circuit board. There are four electronic parts: The optical sensor that triggers the QR recognition, the LED that illuminates the QR card, the infrared LED which we already glued in front of the sensor and the 3 buttons that are used to pause/unpause playback and move within the current playlist. While the buttons and the LEDs are put directly in the case, all other elements are brought together on a circuit board from where they are connected to the RasPi via jumper cables. So this is what we're aiming for:
</p>
<p class="gallery">
<a href="images/audiosphere-electronics.png" class="fancybox"><img src="images/audiosphere-electronics.png" width="480" alt="The electronics in a single diagram with the optical sensor on the left, the LED, the infrared LED and the three buttons on the right. (<a href='https://github.com/tliero/audiosphere/blob/master/misc/electronics-final.fzz'>Source file</a> for <a href='http://fritzing.org'>fritzing</a>)" /></a>
</p>
<p>
Assembling the circuit is pretty straight forward. Be careful about the optical sensor, though: There are two versions out there, <a href="http://www.vishay.com/docs/83751/cny70.pdf">one from Vishay</a> and <a hreaf="http://smallsystems.isn-oldenburg.de/smallrobots/ws2001/Tischkante/cny70.pdf">one from TEMIC</a> that has the detector transistor upside down compared to the other one. Also note that I used a LED that can operate directly on the RasPi's 3.3&nbsp;V without a series resistor. If you use a smaller one (which should also be sufficient for illumination), you will need one.
</p>
<p>
After <!-- http://www.instructables.com/id/Multiroom-Client-With-Raspberry-Pi-ZERO-and-PHAT-D/?ALLSTEPS --><a href="https://learn.pimoroni.com/tutorial/sandyj/soldering-phats">soldering the PHAT DAC onto the Raspberri Pi</a> (preferably using a <a href="images/gpio-header.jpg">GPIO header</a> that directly routes through all the GPIOs) the used PINs are connected with the jumper cables. <!-- Where these were not soldered to the contact, I used hot glue to fix the connection which worked pretty well. -->
</p>
<p>
Once everything is connected together, it can be put in the case for the software installation and final adjustments. All components are connected but wait using the glue gun until everything is tested thoroughly. Especially the webcam might need some in-place live adjustment. Depending on the glossyness of your code cards, the angle of the illumination LED might be relevant as well. The easiest way to do this is by connecting the webcam to another computer while it is already in the case (see bash history below).
</p>
<p class="gallery">
<a href="images/buttons_and_circuit_board.jpg" class="fancybox" rel="collection03"><img src="images/buttons_and_circuit_board.jpg" width="320" alt="The circuit board after soldering with all resistors, the transistor and open contacts to be connected via jumper cables. In order to protect the wire cables and soldering points from breaking, I applied hot glue after testing." /></a>
<a href="images/phat_dac_soldering.jpg" class="fancybox" rel="collection03"><img src="images/phat_dac_soldering.jpg" width="320" alt="The PHAT DAC after soldering." /></a>
<a href="images/phat_dac_soldering_back.jpg" class="fancybox" rel="collection03"><img src="images/phat_dac_soldering_back.jpg" width="320" alt="By my low standards, that is a pretty decent soldering. You can also see the nylon nuts I used as spacers." /></a>
</p>
<p class="gallery">
<a href="images/circuit_board.jpg" class="fancybox" rel="collection03"><img src="images/circuit_board.jpg" width="320" alt="I did not solder the jumper wires to the RasPi but also fixed them with hot glue. This keeps them together as a unit, isolates them from one another, and the hot glue can be peeled off if something goes wrong." /></a>
<a href="images/piplayer-opened.jpg" class="fancybox" rel="collection03"><img src="images/piplayer-opened.jpg" width="320" alt="Interior view of the AudioSphere player with all components assebled. The circuit board is glued to the front side (not visible from this angle)." /></a>
</p>
<p>
What's missing in the pictures is how to get a screw thread behind the holes in the case: Use super glue to put three M3 nuts on washers (in order to enlarge the surface). When dried, use the super glue again to attach these nuts-on-washers behind the screw holes of the case. (Use the screws to adjust them so you can turn them in and out. I used <a href="http://www.uhu.com/produkte/alleskleber/detail/uhu-alleskleber-superstrong-safe.html?cHash=6d17927cfdf1797595540fe083329e0a">UHU Super Strong and Safe</a> which gives you some time for corrections after applying.) Et voilà, you now got yourself screw holes with threads on the player's case.
</p>
<h2 id="software">Software</h2>
<h3>Install and Configure Additional Packages and the Python Script</h3>
<p>
Now configure the additional software that is needed for the player. Before doing that, copy the contents of the <a href="https://github.com/tliero/audiosphere/tree/master/piplayer2">piplayer2 directory</a> (including subdirectories <code>sounds</code> and <code>test</code>) to <code>/home/pi</code> (either directly on the SD card or via SCP). Have also one of the <a href="https://github.com/tliero/audiosphere/raw/master/documentation/QR%20Card%20Template.odt">test cards from the template</a> ready for testing the QR recognition.
</p>
<pre class="pre-scrollable">
# Install additional software
sudo apt install lirc zbar-tools mc moc fswebcam python3 python-rpi.gpio python3-rpi.gpio
# As a first test turn the LED on and off
python3 ~/test/lighton.py
python3 ~/test/lightoff.py
# We can also test the buttons and the sensor (Press buttons to retrieve their ID, hold a card
# on the sensor to see if it switches from 'LOW' to 'HIGH')
# (Stop the scripts with Ctrl-C)
python3 ~/test/buttons.py
python3 ~/test/sensor.py
# Configure PHAT DAC (<a href="https://learn.pimoroni.com/tutorial/phat/raspberry-pi-phat-dac-install">https://learn.pimoroni.com/tutorial/phat/raspberry-pi-phat-dac-install</a>)
curl -sS get.pimoroni.com/phatdac | bash
# Check for errors
dmesg
# Plug in headphones or JBL connector cable, start mocp and test audio output via the PHAT DAC. (Don't forget to turn on the speaker!)
mocp -S
mocp -l ~/sounds/scanning.mp3
mocp -x
# Determine the webcam's USB ID and the available resolutions (<a href="http://askubuntu.com/questions/214977/how-can-i-find-out-the-supported-webcam-resolutions">http://askubuntu.com/questions/214977/how-can-i-find-out-the-supported-webcam-resolutions</a>)
# (The USB ID "001:006" in the second line has to be replaced with the actual ID of the camera)
lsusb
lsusb -s 001:006 -v | egrep "Width|Height"
# Webcam test: turn on the LED, take a photo and turn the LED off
# (The focus of the webcam should be adjusted to the window distance beforehand on another computer with a live picture)
python3 ~/test/lighton.py
sudo fswebcam -r 320x240 -d /dev/video0 -v ~/webcam-test.jpg
python3 ~/test/lightoff.py
# Copy ~/webcam-test.jpg to another computer and have a look at it
# If needed, adjust the webcam and repeat the step until the QR code recognition is reliable
# QR-Test: Hold a QR code card above the webcam then turn on the LED, decode the QR code and turn the LED off
# (Stop scanning for codes with Ctrl-C)
python3 ~/test/lighton.py
zbarcam --quiet --nodisplay --raw -Sdisable -Sqrcode.enable --prescale=320x240 /dev/video0
python3 ~/test/lightoff.py
## From here on it's about the configuration of the infrared sender - currently this is not used
# Enable lirc in /boot/config.txt and add parameters
sudo nano /boot/config.txt
# # Uncomment this to enable the lirc-rpi module
# dtoverlay=lirc-rpi,gpio_in_pin=23,gpio_out_pin=22
# adapt lirc configuration in /etc/lirc/hardware.conf
sudo nano /etc/lirc/hardware.conf
# LIRCD_ARGS="--uinput"
# LOAD_MODULES=true
# DRIVER="default"
# DEVICE="/dev/lirc0"
# MODULES="lirc_rpi"
# LIRCD_CONF=""
# LIRCMD_CONF=""
sudo reboot
# Copy the contents of the <a href="https://github.com/tliero/audiosphere/blob/master/documentation/lirc_jbl_iiip.conf">JBL remote configuration</a> to /etc/lirc/lircd.conf then restart lircd
sudo /etc/init.d/lirc restart
# Turn on music, list available commands and test remote control
mocp -S && mocp -l ~/sounds/scanning.mp3
sudo lircd -d /dev/lirc0
irsend LIST JBLIIIP ""
## Apparently the commands have to be sent two times in order to be recognized. I might need to
## improve the lirc configuration. As stated above, this is still work in progress.
# mute
irsend SEND_ONCE JBLIIIP KEY_MUTE && irsend SEND_ONCE JBLIIIP KEY_MUTE
# unmute
irsend SEND_ONCE JBLIIIP KEY_MUTE && irsend SEND_ONCE JBLIIIP KEY_MUTE
</pre>
<p>
When everything works as expected, all the electronic parts are fixed together using hot glue. I glued the webcam, the circuit board and the USB hub in the case so that nothing will fall out of place anymore, even if the player is moved around roughly.
</p>
<p>
<em>
While I really like hot glue, it's got its limits: I thought I could skip soldering the buttons to their wires by just twirling the cable ends to the contacts and then fix everything down with the hot pistol - bad idea. While being hot, the glue gets in between the wire ends and the contacts and perfectly isolates them. None of the buttons worked anymore. I had to peel the glue off the contacts with a cutter knife before soldering them properly back on again...
</em>
</p>
<h3>Configure Autostart and Mount SD Card in Read-Only Mode</h3>
<p>
Now that everything is in place, we are ready for the final adjustments: Configure autostart for the player script and mount the SD card in read-only mode which makes the player robust against sudden loss of power. For that, we redirect the write access to a RAM disk.
</p>
<pre>
# Autostart for piplayer2.py with log output redirection (<a href="http://raspberrypi.stackexchange.com/questions/8169/run-startup-application-as-a-specific-user">http://raspberrypi.stackexchange.com/questions/8169/run-startup-application-as-a-specific-user</a>)
sudo nano /etc/rc.local
# ...
# su pi -c 'python3 /home/pi/piplayer2.py >> /home/pi/piplayer2.log 2>&1 &'
# exit 0
sudo reboot
# Check if running after restart
ps -ef | grep python
# Watch the log output while testing with QR code cards
tail -f /home/pi/piplayer2.log
# Switch to RAM disk and set the filesystem read-only (<a href="https://www.heise.de/ct/ausgabe/2016-21-Den-Raspi-als-Bluetooth-Empfaenger-einsetzen-3330683.html">https://www.heise.de/ct/ausgabe/2016-21-Den-Raspi-als-Bluetooth-Empfaenger-einsetzen-3330683.html</a>)
sudo nano /etc/fstab
# proc /proc proc defaults 0 0
# /dev/mmcblk0p1 /boot vfat defaults,ro 0 2
# /dev/mmcblk0p2 / ext4 defaults,noatime,ro 0 1
# tmpfs /var/log tmpfs nodev,nosuid 0 0
# tmpfs /var/tmp tmpfs nodev,nosuid,mode=1777 0 0
# tmpfs /tmp tmpfs nodev,nosuid,mode=1777 0 0
# tmpfs /home/pi/.config tmpfs nodev,nosuid,mode=1777,uid=pi 0 0
# tmpfs /home/pi/.moc tmpfs nodev,nosuid,mode=1777,uid=pi 0 0
# # a swapfile is not a swap partition, no line here
# # use dphys-swapfile swap[on|off] for that
sudo rm -rf /var/lib/dhcp/ /var/spool /var/lock /etc/resolv.conf
sudo ln -s /tmp /var/lib/dhcp
sudo ln -s /tmp /var/spool
sudo ln -s /tmp /var/lock
sudo ln -s /tmp/resolv.conf /etc/resolv.conf
# Make /tmp on RAM disk writable
# Shown here with the former additions to rc.local - please note that the log redirect for the player script changed
sudo nano /etc/rc.local
# ...
#
# # make /tmp on RAM disk writable
# chmod 777 /tmp
#
# # disable HDMI
# /usr/bin/tvservice -o
#
# # start piplayer
# su pi -c 'python3 /home/pi/piplayer2.py >> /tmp/piplayer2.log 2>&1 &'
#
# exit 0
sudo reboot
</pre>
<p>
Test if it is read-only now:
</p>
<pre>
# This should produce an ERROR
touch ~/wontwork
</pre>
<p>
We can make the filesystem writeable again until next reboot for maintenance by remounting it like this:
</p>
<pre>
sudo mount -o rw,remount /
sudo mount -o rw,remount /boot
</pre>
<h3>Connect to SMB network share</h3>
<p>
Until now, we can only play local files from the SD card (and audiostreams from the Internet). The final step is to connect the local share that stores all of our MP3 files. How this is done depends upon the type of share you would like to use. The most common type should be a Windows/SMB share in the local network that can be connected like this:
</p>
<pre>
# Make SD writable
sudo mount -o rw,remount /
sudo mount -o rw,remount /boot
# Create mount point
mkdir /home/pi/share
# Connect smb share on /home/pi/share
sudo nano /etc/rc.local
# sudo mount -t cifs -o user=guest,password= //192.168.1.110/media /home/pi/share
</pre>
<p>
Of course, one might as well mount a cloud drive via WebDAV or something similar and play everything directly from the Internet. How this is done will depend on the supported protocols.
</p>
<h2 id="qr-cards">QR Cards</h2>
<p>
With the storage attached, all the MP3 files are accessible for the player. What's missing is some QR code cards to get the party started. For that, there's a <a href="https://github.com/tliero/audiosphere/raw/master/documentation/QR%20Card%20Template.odt">template</a> which can be used to create new cards. After printing a page from the template, it is simply cut into stripes which are folded in the middle and then glued together.
</p>
<p>
For generating the QR codes pretty much every software can be used. If you are using lots of non-ASCII letters, you should make sure that they are encoded properly. (You can always check the codes that have been read by the player in the logfile with <code>tail -f /tmp/piplayer2.log</code>.) Personally, I use QtQR which is a frontend for <code>qrencode</code>.
</p>
<p class="gallery">
<a href="images/audiosphere-template-structure.png" class="fancybox"><img src="images/audiosphere-template-structure.png" width="480" alt="The different areas of the QR code template." /></a>
</p>
<h2>What's Left</h2>
<p>
In the future I would like to have a web server running on the RasPi, which allows to control the player remotely. I'm not yet sure if this is going to be a web interface or an Android app that operates on a REST interface. I pretty often find myself skipping through the entire code card stack in the dark in order to switch to a different bedtime story that has been requested.
</p>
<p>
Also, I would like to have the last say in volume control. This is where the infrared LED that has been installed in the speaker case will come in handy.
</p>
<p>
If you have any questions or improvements please send me an e-mail to <a href="mailto:tliero@gmx.net">tliero@gmx.net</a>.
</p>
</div>
</body>
</html>