Posts Tagged ‘music’

So I’ve gone through two use cases so far, and I have successfully got these working using the basic plug and play parts of an introduction to electronics kit. No soldering, just pushing pins into the prototyping board. The next couple of use cases I think I’ve figured out, but as the cheap electronics are coming from eBay via China, I’m still waiting for the parts to arrive before I actually try these ones….

So this is (at time of writing) all theory!

Use Case 3 – Volume Control

While the X400 has an on-board volume dial, I’m not convinced that I can build a suitable mechanical coupling to allow me to expose this outside of the enclosure. My gut reaction is to use this as the max level control and then use software to control the volume up to this hard limit. Volumio will then treat this as the 100 (max) point in its volume scale and allow users to set volumes. Volumio can also set the mute the same way, but how do I control the volume?

I believe that I can control the volume via the software mixer in Volumio. Like with mpc, I should be able to issue a command to increase or decrease the volume. As with my previous two use cases, adding a switch to the GPIO and detecting it appears to solve this problem.

Adding another set of switches seems ‘wrong’…. So perhaps I should try something a little bit more complex and user friendly? Maybe using a rotary encoder (a dial!) instead to control the volume? Maybe I should be really smart and try a rotary encoder with a push button (a dial you can click) to allow for mute as well?

usecase3

Rotary Encoder – NO Switch

Python Code:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from RPi.GPIO import GPIO
from time import sleep

#Define GPIO Pins that have buttons
clk = 5            #volume dial clk
dt = 6             #volume dial dt

GPIO.setmode(GPIO.BCM)
GPIO.setup(clk, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(dt, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

volume = 0
clkLastState = GPIO.input(clk)

def changeVol(newVolume):
    print ("New volume is " + newVolume)

try:
    while 1:
        clkState = GPIO.input(clk)
        dtState = GPIO.input(dt)
        if clkState != clkLastState:
            if dtState != clkState:
                volume += 1
            else:
                volume -= 1
            changeVol(volume)
        clkLastState = clkState
        sleep(0.01)
finally:
        GPIO.cleanup()

Update: The encoder I have has 5 pins, not 3…. clk/dt/GND/3.3V/something…. and that is represented in the code above. It still doesn’t have a ‘switch’.

Update: The latest version of Volumio has its own command line client that allows for volume setting.

volumio volume <value>

Use Case 4 – Radio Stations

The final use case is the ability to switch to live radio streams – something that is a must in a kitchen radio! I think we’re back to simple GPIO buttons on this one, with each one triggering a predefined playlist of a single stream. How we trigger the actual stream is something I’ve yet to figure out.

usecase4

Radio Preset 1, 2 & 3

Still working on this bit…. #sigh

 

Use Case 5 – Modes

OK, so I lied. While playing with the HiFiPi I realised that the music is playing out of both the speakers and the headphone socket. As it was late and I didn’t want to wake the kids I needed someway to turn the speakers off. The X400 comes with 3 jumpers that are used to turn the amp on & off, the headphones on & off and mute all the outputs. Trouble is moving these around once inside the enclosure will be impossible.

x400-drawing

X400 Output Jumpers

As these are fixed jumpers, it should be possible to use locking switches to fix the state in either open or closed, thus enabling the device component. A quick email to Suptronics support revels that this is true, so I now need to add locking switches to the shopping list to test.

This will mean I can add a mute button without using up a GPIO or adding code. The other two modes – headphones & speakers are more useful to me using the setup in the study at night. That way I can turn off the speakers and just use the headphones to stop me from waking the kids.

Parts List (so far):

Wire – whatever is appropriate to you setting!

2x 1 row pin headers

Momentary contact switch x1 – for ON

Momentary contact switch x1 – for OFF

Momentary contact switch x4 – Media shuttle commands

1x Rotary encoder

Momentary contact switch x3 – Radio preset buttons

Locking switches x3 – Mode output control

So now the real learning starts. I need to decide what I want the box to do, how to do it and then build it. Easy huh? The code that I reference here is also in my GitHub repo, it’s likely that these snippets get superseded as I figure out how the stuff works. I’m also using the excellent Fritzing to figure stuff out with the wiring, so it may pay to look at that as well if you want to design your own parts.

The other thing to note is that my switch circuits run from the GPIO Pin to GND – making the Pins use the PULL UP resistor in the Python code. If I had run the switches from Pin to 3.3V, PULL DOWN resistors would need to be declared.

As we are access the GPIO, all the python code will need to be run under sudo to gain access.

Use Case 1 – We must be able to turn the player On and Off via a switch

OK so after a lot of Googling it becomes apparent that all the normal method to deal with this – add on boards with switches – are inappropriate because of the X400. As the X400 provides power to the Pi, none of the aftermarket solutions will work.

Use Case 1 (Amended) – We must be able to turn the player On and Off

The answer (in theory) is to use the ‘reset’ switch header as an ON and to add a switch to the GPIO with some code to handle the OFF part.

There is a P6 header on the RPi boards that allows you to reset the device when it is shorted. While absolutely not suitable for a clean shutdown, it will restart the box if it is in a powered but shutdown state. The issue is that this header isn’t populated, so we will need to add some pins prior to connecting a switch of some kind. This means soldering the pin header to the board itself (gulp) and then connecting the new header pins to a switch. So that’s the ON part sorted.

For OFF, connecting a momentary switch to one of the GPIO Pins and then detecting it with some Python to trigger the appropriate shutdown command appears to be the easiest and safest method. This protects the SD card and ensures that everything is clean before shutting down. As power is still applied, we can use the new ON switch to restart when required.

usecase1
Simple shutdown switch
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Assumes switch is connected to GND - so uses PULL UP

import subprocess
import time
import os
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

button = 20

GPIO.setup(button, GPIO.IN, GPIO.PUD_UP)

while True:
 button_state = GPIO.input(button)
 if button_state == GPIO.HIGH:
  pass
 else:
  print ("Shutdown")
 #os.system("sudo shutdown -h now") # Send shutdown command to os
 time.sleep(0.5)

Use Case 2 – Play, Pause, Next, Previous & Stop

So after some more Googling it seems that I can use the MPC client (the Music Player Daemon command line bit) to control playback from the command line. As Volumio includes this part, simply issuing commands allows us to control things via the terminal.

 mpc play

mpc pause

mpc stop

Issuing just

mpc

Will return a list of commands you can use.

So we’re back to the GPIO with an additional 5 4 momentary switches, each of which then uses Python to issue the appropriate mpc command.

** UPDATE **

Oops. While working on building the device modes (see Part 5), I realised that GPIO Pin 17 (Board Pin11) is already claimed by the IR receiver on the X400. This means that I have now lost my ‘play’ button. The solution is to remove GPIO 17 from the code and change the GPIO 27 (Board Pin13) from

mpc pause

To

mpc toggle

Which, unsurprisingly, toggles play/pause. The other advantage is 1 less button to fit somewhere on the final case!

usecase2

Play/Pause, Stop, Previous & Next

Python Code:

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Assumes switch is connected to GND - so uses PULL UP

import os
import subprocess
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#Define GPIO Pins that have buttons
play_pause = 27 #Play/pause mpc toggle
stop = 22 #mpc stop
prev_track = 18 #mpc prev
next_track = 23 #mpc next

power_off = 20 # sudo halt now

#Configure PULL Up and pin connections
GPIO.setup(play_pause, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(stop, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(prev_track, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(next_track, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(power_off, GPIO.IN, GPIO.PUD_UP)

#Begin loop to wait for button press
while True:
 if GPIO.input(play_pause) == GPIO.LOW:
  print ("Play/Pause")
  subprocess.call(['mpc', 'toggle' ])
 elif GPIO.input(stop) == GPIO.LOW:
  print ("Stop")
  subprocess.call(['mpc', 'stop' ])
 elif GPIO.input(prev_track) == GPIO.LOW:
  print ("Previous")
  subprocess.call(['mpc', 'prev' ])
 elif GPIO.input(next_track) == GPIO.LOW:
  print ("Next")
  subprocess.call(['mpc', 'next' ])
 elif GPIO.input(power_off) == GPIO.LOW:
  print ("Shutdown")
  #os.system("sudo shutdown -h now") # Send shutdown command to os
 else:
  #print ("Nothing")
  pass

 time.sleep(0.25)
Parts List (so far):

Wire – whatever is appropriate to you setting!

2x 1 row pin headers

Momentary contact switch x1 – for ON

Momentary contact switch x1 – for OFF

Momentary contact switch x54 – Media shuttle commands

Links & Refs:

GitHub: https://github.com/nwootton/HiFiPi

Reset Switch – http://www.raspberry-pi-geek.com/Archive/2013/01/Adding-an-On-Off-switch-to-your-Raspberry-Pi

In the previous two parts I’ve looked at building something a little more capable for audio playback. What I’ve built works brilliantly with headphones, but isn’t in any way  suitable for use by ‘normal’ people and definitely not with small children around.

So I decided to look at following the herd and try to build the new music player in an old enclosure. After much eBay hunting, I found several nice radios that could be refactored. My issue with them was the size.

If I want to build a stereo radio I need 2 speakers (obvious huh?), but most of these radios are mono, so adding a second speaker either means running two tiny speakers or modifying the case to allow for a second speaker. Either way two speakers take up space and the X400 is already considerably bigger than the HiFiBerry or equivalent board.

If I go the whole hog and try to include some form of interface/screen then a repurposed radio chassis is completely unsuitable. I can try and find a large (think valve type) radio from before the modern radio. These are generally quite large but come with wooden cases that can make the end product look gorgeous. This scenario gives me the opposite problem. The end product would be far too big to sit in the kitchen, it would be more appropriate for the dining room or somewhere as a centre-piece.

The X400 is rated to drive 2x 20W speakers, I had originally planned to buy some car speakers from eBay once I had the rough dimensions of the enclosure I wanted them to go into. So everything really hung off of finding a decent box to put it in.

Being a total novice at this stuff, I decided that it makes more sense to try and build something, learning as I go. I’d have to be prepared to completely get it wrong, throw away stuff and to start again. Once I’d figured things out, maybe then I could build the ‘final’ version.

With this in mind I decided I would get a broken Roberts Colourstream internet radio. While big and modern, it has a couple of decent speakers and a touch screen that I hoped I could re-use. The case should be big enough to fit everything inside and it is already configured for stereo.

roberts_colourstream

Roberts Colourstream Internet DAB Radio

The previous owner had attempted to ‘fix’ the device – resulting in the guts basically being supplied in a separate bag, but that was just one less thing for me to do. Removing the facia allowed me to get to the speakers and after a couple of minutes work  I had stripped the plugs off the speakers and had wired them directly into the X400. A boot of the Pi and suddenly we have music from the speakers.

The next part is figuring out what I want to do, how to do it and what parts are needed!

 

So the X400 board arrived is a small cardboard box. The board was wrapped in an appropriate anti-static bag and the jumpers, nylon screws and standoffs were in their own little bag. No instructions in the box, but the website has pretty good documentation. Customer support is pretty rapid as well given the time difference between the UK and China when I did have a question.

x400_860p_1

X400 Image from Suptronics WebSite

As the X400 board also powers the Pi, it needs it’s own power supply. The docs say that it needs between 18 – 25 V supply that it then steps down to the levels necessary to supply the both devices. After rummaging around to find a suitable power supply, I ended up using an old laptop adapter that had the right size plug.

X400 itself fits on the RPi2/RPi3 via the 40 pin GPIO interface with nylon standoffs to support the card. There are also 3 jumper pegs in the box that allow you to turn on and off the headphones output, amp and to mute the audio. I guess these are used to disable the services you don’t want to use.

Volumio was the OS of choice based on my previous experiments with Audio OS’s, and as it supports the X400 card natively (an added bonus I found after reading the Suptronics website). As I already had an SD card built, I just used that. I didn’t do anything special to get the X400 working, although the Suptronics site talks about ensuring certain kernel modules are installed, I think these are more for older Raspbian versions. All I did with the Volumio build was select the correct device from the dropdown list in the config. page and it was all working!

At this point I got the new Volumio device to scan the FLAC library on the NAS and used it to playback some tracks via the headphone s. I’m not an audiophile, my FLACS aren’t the highest quality you can do and the headphones are cheap Sony ones I got from work a couple of years ago, but even with those limitations playback of a variety of tunes was impressive. Details and quality were much better that the ‘norm’ I’ve come to expect from high quality VBR MP3 via my iPod.

The only other thing I had to do was find a case. I’d seen some bundles that included the board and case, but I’d decided that the bundle was too expensive. After quite a bit of searching I actually only found one supplied who could get me an enclosure to protect the electronics. That was ordered from an Italian shop on eBay UK that then shipped the stand direct from China (isn’t international commerce great!?). This isn’t a case, but rather a clear stand with a top to prevent things coming into contact with live electronics – be they fingers or errant wires.

To be honest at this point I’ve completed the first and most basic version of my HiFiPi. If I can figure out how to do things like get power and channel selection buttons to work via the GPIO, find a suitable enclosure and speakers I’ll try and get the Kitchen Radio version built.

As usual I found myself with more ideas and things to experiment with when building the MooMusic prototype. Seeing all the possible things I could build made me want to move the project on far beyond my original ideas. But that wouldn’t be fair as the use case for MooMusic was very specific – a simple music player for my daughters. So I decided to use one of the various Pis floating around and try to build something more ambitious. I’d seen lots of people restoring antique radios or building small touchscreen enabled devices, so I wanted to do something like that.

First stop is to figure out the best way to get decent quality sound out of the Pi. Do I install something with a headphone style jack, something with phonos (RCA) or something that can take speakers? My initial thoughts were to install a DAC with some phono outs. If I wanted to use headphones I can easily get a phono-headphone adapter (assuming there isn’t one in my cable bin already!).

From the forums related to this kind of project it became apparent that HiFiBerry make some excellent small scale expansion boards that provide all of the connections I can think of and more. The prices aren’t bad either, and are cheaper than some of the true audiophile level DACs that I could try to use.

The problem is, I don’t actually have a real-world use case for this project: I’m not building this for a specific reason, just because I can. I soon realised that because I have no real use case, trying to build something that is suitable suddenly becomes much more complex. If I want speakers, I need an amp. If I want headphones I need a suitable jack. If I want to connect to an external amp, I need phono or maybe SPDif/Optical. Do I need to support Bluetooth? Will I use WiFi or ethernet?

Head-spin.

After taking a step back I decided that I want this to either be my audio source in my office OR to replace the annoying kitchen radio. The actual outcome would depend on how easy to use the final thing was and how pretty it was.

Based on that it became apparent that I needed the ability to drive speakers AND the ability to output via headphone jack. Faced with this, the HiFiBerry boards became a bit too expensive for me to play with. ~£45 for the Amp and ~£23 for the headphone with no indication that I can stack them and use both boards in a single build.

I’m not confident that what I end up making will be good enough to use in the kitchen, so just buying the amp is risky.

While trying to resolve this matter I came across a reference to the X400 board. A bit more digging revealed the X400 board from Suptronics. This board includes phonos, amp (with speaker terminals) AND headphone jack. The downside is that all that requires a separate power supply. Thankfully the power supply also powers the Pi, so there’s no need to use 2 plugs! For ~£20 via eBay (of course) I ordered the board and crossed my fingers.

Building this little box has unfortunately had two side effects.

The first and less of which is me now trying to figure out how to get the MPD binding working in OH2 so I can do things like control the music player as part of a rule or scene. Maybe ensuring that the box turns off at a certain time each night so that my daughter isn’t listening to music all night. Or turning it on in the morning with something loud and inappropriate to wake her up.

The bigger problem is the desire to build something a little bit more ‘sophisticated’ with maybe some better speakers and a better interface….. Maybe my own HiFiPi

So I’d bought a TECEVO T4 NFC Bluetooth Wireless Speaker on an Amazon lightning deal a while back, partly because of wanting to play with Moo Music and partly to plug into my desktop so I can have sound that’s not via headphones.

I found plenty of people talking about connecting BT speakers to their Debian based systems, but a distinct lack of info about doing it specifically for Volumio. Working with the various guides I totally failed. Either the changes would result in  Volumio becoming unstable/not booting or would result in no audio anywhere.

If you dig deep enough you will find several requests for native BT support in Volumio, but they have all been rejected. While this is annoying, I actually agree with the reasons. Volumio is designed/tweaked to work as a High End Audiophile device when added to a suitable DAC. In no way is a BT speaker (no matter the cost) a high end output device. Providing support for such a device goes against the basic ethos of the platform.

Knowing that trying to install BT on Rune Audio was doubly cursed – I’m ignorant of ArchLinux AND it probably doesn’t support BT for the same reason, I went back to PiMusicBox.

As PiMusicBox is more of a wrapper for the Python based Mopidy system that is an extension of MPD, it is a bit less Audiophile biased. It also means that I can add and remove stuff to the OS without worrying about breaking some obscure kernel header tweak.

After a few false starts I managed to get the speaker to automatically connect to the Pi when they are powered. Audio from PiMuiscBox is sent to the speaker and as it is basically streaming VBR MP3 files, the quality is pretty good.

In fact I was so happy with the final result that I decided not to bother playing with the USB Sound card when it did eventually turn up…. about 2 weeks later!

#Install libraries
sudo apt-get install bluetooth bluez bluez-utils bluez-alsa

#Turn on BT Interface/Card
sudo hciconfig hci0 up 

#Use the BT device to scan for the speaker
hcitool scan # scan for your bluetooth device

This will return a list of devices and their MAC addresses, find the speaker you want to connect to and copy the MAC string. The run the  following commands:

#tell the adapter to connect to the MAC address and use 0000 as the pin
bluetooth-agent  --adapter hci0 0000 XX:XX:XX:XX:XX:XX 

#Test that the Pi and speaker are connected - should get you some beeps
bluez-test-audio connect XX:XX:XX:XX:XX:XX 

#Tell the Pi to trust this bluetooth device
bluez-test-device trusted XX:XX:XX:XX:XX:XX yes 

#Check that the device is now trusted - a 1 means it is
bluez-test-device trusted 48:5A:B6:A8:1C:A2 

#Restart the BT service on the Pi
sudo /etc/init.d/bluetooth restart

Now we need to modify some files

In /boot/config/settings.ini:

Change

output = alsasink

To

output = alsasink device=bluetooth

Rename the /etc/asound.conf

cp /etc/asound.conf /etc/asound.conf.bak

Replace the contents of asound.conf with:

pcm.bluetooth {

type bluetooth

device XX:XX:XX:XX:XX:XX ## your device id##

profile "auto"

}

Rename /opt/musicbox/setsound.sh

mv /opt/musicbox/setsound.sh /opt/musicbox/setsound.sh.bak

Backup the bluetooth audio config

cp /etc/bluetooth/audio.conf /etc/bluetooth/audio.conf.bak

And amend it, under [General] add the following

[General]

Enable=Source,Sink,Socket

Further down under the commented out #Disable add the following line

Disable=Media

Now reboot MusicBox….