Multi-Room Audio Control with Raspberry Pi

Raspberry Pi and relay board installed in the speaker selector. The lid just barely fits on top of this.

My parents’ house has a whole-house audio setup where an amplifier can drive built-in speakers in each of 5 rooms. This system is great for background music during dinner and parties, but we’ve rarely used it: it’s a hassle to go to the room with the sound system every time we want to turn it on, change the song, station, or volume, or turn a room on/off.

As a winter break project, I put together a controller using the $35 Raspberry Pi computer and some custom hardware and software. From a mobile Web interface, you can:

  • Switch room speakers on and off using a custom-built relay board.
  • Control the sound system. You can switch between CD, AM/FM, and Aux inputs, change the volume, change the track/station, and turn the system on/off. The controller emits IR signals that simulate the sound system’s remote control.
  • Stream music to the system using Apple AirPlay. You can play Pandora, YouTube, or your own music from any iPhone, iPad or Mac on the network.

Here are some photos and screenshots of the final result.

The Setup

The original sound system was hooked up like this:

Original sound system

Here is how the new system is hooked up:

New audio system

I modified the speaker selector box by inserting relays in parallel with the original switches. If either the relay or the physical switch is on, that room’s speakers will be on. The Pi’s analog audio output is also fed back to the sound system’s Aux input for AirPlay output. Finally, the Pi can also control the sound system with IR commands.

Hardware

  • Raspberry Pi Model B. A 700 MHz ARM-based Linux computer with 512 MB RAM. Ten programmable GPIO pins control the five relays: simply pulse the on or off coil for ~50ms. Another GPIO controls the IR diode.
  • IDE cable connector. I cut up an old 40-pin IDE connector to connect to the 26-pin GPIO header.
  • DPDT latching signal relays. Each relay controls left and right channels (hence dual poles). I opted for two-coil relays, so I could activate one coil to turn the relay on and the other coil to turn it off. (Digi-Key)
  • ULN2003A ICs to drive the relays. The Raspberry Pi’s GPIOs can’t drive the relays directly, so we control them with this transistor array. Each chip has 7 NPN Darlington pairs. It also has built-in flyback diodes that will dissipate the inductive kickback from the relay coils. (Digi-Key)
  • Stick-on IR diode. I had this emitter lying around. It came with a long cable that terminates in a mono 3.5mm headphone jack. I cut off a female headphone jack from a patch cable to make a plug for this and wired a 270 ohm current-limiting resistor to this.

Edit: Here’s a schematic for the relay board: Relay board schematic

Software

I wrote a Python script to control the relays and a Flask/jQuery Mobile web app for control from our phones/tablets. I’ve posted my code on GitHub. This project also leverages other open-source software:

  • Raspbian. The Debian distribution for Raspberry Pi.
  • Python, Flask, and jQuery Mobile for the control app.
  • RPi.GPIO to control GPIO ports from Python.
  • ShairPort, to enable AirPlay streaming to the Pi.
  • LIRC to learn and send IR commands to the sound system, using the lirc_rpi module.
  • uWSGI and Supervisor to run and deploy the webapp.

More details about the software setup can be found in the README on GitHub.

Result

A resounding success! It’s a joy to be able to control our music from anywhere in the house. My mom has been thinking of upgrading the system for a while, and she says it’s an awesome Christmas gift.

46 thoughts on “Multi-Room Audio Control with Raspberry Pi

  1. Cool project! I’m in the same situation. Existing multi-room audio setup in my parents house. I’ll probably need something like you did here.

    The only thing I’m bothered with is that currently every room plays at the same volume in our house. To be able to hear the speakers outside in the garden, the volume has to be a bit louder, causing the speakers in the kitchen to play very loudly in comparison with the speakers outside. So I’ll need to add some kind of volume control for every room and modify the electronic signal on each output. If you have suggestions on how to do this, please let me hear them :-)

    Thanks for the article, a great way to start my own project

  2. Hey Jesse,

    Great to hear that this was useful to you! In my case, we already had a volume control panel in each room. You might be able to find some sort of digital volume control IC that would attenuate the signal on each output line — in that case, you could even forgo the relays altogether and just turn the volume all the way down on rooms you want to disable. Hope this helps. Would love to hear how your project goes!

    Cheers, David

  3. David,

    Thanks for posting this. I have been meaning to do almost exactly this for a few months now, so I was very glad to see your detailed instructions… Any chance you could share a circuit diagram? I can’t tell from the picture how the transistors are wired up.

    Jed

  4. Hey Jed, I updated the post with a schematic, under the Hardware section. The transistor hookup is fairly straightforward: one output channel of the ULN2003A to the cathode of each relay coil. This IC really simplifies things because it has built-in base resistors for the transistors, as well as clamp diodes (necessary protection for driving an inductive load like the relay coils). There’s also one channel that goes to the IR blaster (connected via a headphone jack). Good luck!

  5. David,

    Thanks again! I got out my old breadboards from my circuits class and tried to fit those relays across the gap, but the gap is too large (it’s built for ICs and the relays have a smaller gap… Where did you get your breadboard and how are the internal connections set up? The only ways I can fit the relays on my breadboards would short opposing pins.

    Jed

  6. Actually… I take it back… You’ve probably got a perfboard there, no?

    Jed

  7. Right, I used a perfboard and the wires are on the reverse side. It was adequate for the prototype, although kind of tedious (lots of little wires to solder). For the next version I’d probably make a PCB!

  8. Dave,

    Thanks again for sharing this great project! Very impressive.

    I’ve made it through most of your instructions: the relays are working via your pandorica interface. I changed the pin mapping to use the gpio pins I had connected and renamed the rooms by editing the file in the templates directory. I wanted to note one or two things that may help others who try this:

    I found I had to install a few things upfront: sudo apt-get install python-dev sudo apt-get install libpcre3 libpcre3-dev

    Also, I still haven’t gotten nginx/uwsgi to work the way you describe… I get bad gateway errors, etc. I just run as follows for now:

    python spksel.py –bind 0.0.0.0

    This seems to work ok for my initial tests… I wonder: what are the disadvantages of doing it this way?

    Also, I am curious… Do you think that if I turned the volume up high enough the protoboard/high gauge wiring would have trouble handling the current? My amp puts out 90 watts per channel max, though I am sure that I seldom use a volume setting that approaches that level. I guess I could always manually select the buttons using the original mechanism if I ever turn the volume up high, since it is wired in parallel.

    As a final note, the only real differences between my configuration and yours are 1) I put the IR signal directly into a passive IR port on the back of my Onkyo amp without the need for a stick on diode; and 2) I already have an airplay enabled device hooked up to my amp, so I didn’t need to install the ShairPort software on my RPi.

    Jed

  9. Jed, it’s really cool to hear that you built this! I’m glad the software worked out for you, and I’d love to see photos of your setup.

    There’s no real disadvantage to running Flask’s built-in webserver for a small web service like this. You’ll probably just want to set it up so that the web server runs automatically when you boot up the Pi.

    You’re right that the relays and wires are too small for the possible current. (The speaker wire is huge compared to the relay board wire!) I wasn’t able to get a good measurement of the actual current though—I tried using an AC ammeter to measure current and only saw <100 mA. Either my setup wasn’t working (using a really old multimeter) or perhaps each wall speaker actually has its own amplification. In my case, the wires didn’t even get warm when I put fairly loud music on all channels.

    If you can measure the current in your system, I’d be curious to hear how much the speakers draw. Theoretically, P = I^2 / R would give I = sqrt(90 W / 8 ohm) = 3.4 amps!

  10. Yes… I’ll set up the server to run on startup. I’ll also post a picture on my blog soon and add a link here.

    I think most multimeters (mine included) don’t give accurate current readings for audio signals. Also, I think a 90 watt channel usually puts out a much smaller power for two reasons: 1) The peak voltage is much higher than the RMS voltage for audio, so you will get bad clipping long before you reach the RMS voltage that you compute for 90 W. 2) Volume is perceived in a log scale, so if my amp can produce X dB at 90W, and I have the volume at (X-20) dB (still loud), I am only using 1% of the power (10% of the current you computed, or 0.34 A)

    Jed

  11. This is great, David. Do you know if this can be configured for more than 5 speaker sets using the standard GPIO pins?

  12. Jed: Good point about the measurement technique–I suppose undersized speaker wiring here would probably reduce audio quality or volume before posing a heat issue. It’s probably good enough for casual listening, as I don’t notice any difference with/without the physical switch pressed.

  13. Thanks, Mark! I believe there may be GPIO pins free on the Raspberry Pi to control one or two more relays (check the pinout). If you want to control even more relays, you could use latched shift registers like the 74595 between the Raspberry Pi and the ULN2003A chips. Then you’d only need three lines to control any number of relays: clock, data and output enable.

  14. Hi i really glad that you shared this post and im looking to do something similar my question is can it play all rooms at the same time

  15. Hi David,

    a great project, thanks a lot for sharing this to the rest of the world!

    As i think about to build the whole thing, i had an ideas/a question, i’m interested in what you are thinking about: Q: why do you use two-coil-ralays instead of none latch one-coil-relays, what are the advantages? I: using non latch relays there will be enough free GPIO pins to change the original switches from the speaker selector box to GPIO push-buttons and just use the PasPi to control the ralays to turn on/off the speakers instead of the original switches. I would do this because if a speaker circus is turned on manually you can’t turn it off with the app, right?

    greetings

    Schappenberg

  16. Hey Schappenberg,

    I used latching relays so that I wouldn’t have to keep the coil energized to keep the speaker on. This isn’t good for the relays, unless your relays are rated for continuous duty.

    In my box, I wired the relays in parallel with the original switches so that I wouldn’t have to make too many modifications to the original speaker selector. That way if the Raspberry Pi stopped working for some reason, we could still use the speakers. You could certainly make the push buttons software-controlled instead.

    @Christopher: Yep, all the channels can be turned on at the same time!

    David

  17. Hi, very interesting project, gratz! I’m planning to adapt it to my needs, thank you for your provided ideas and stuff. Question: Have you considered using solid-state-relays? You won’t need the driver IC then. There are AC types available, for example the AQZ202. But maybe I’ve missed a thing. Greez, Harry

  18. David,

    This is a very impressive project. I have been looking for something exactly like this for my home. I’m using a Monoprice manual controlled speaker selector (Monoprice 6-Channel Speaker Selector) to control my speakers. Do you think your design would work with the Monoprice unit? In addition, I’m very much a novice at assembling electronics. Do you think someone with very little assembly experience could handle this? Thank you.

    Ralph

  19. Thanks Ralph. It would probably work — my speaker selector box was very simple, just a passive box with bunch of switches and a couple resistors inside. It looks like the Monoprice selector is similar. A good first step would be to open it up and figure out how it’s wired; use a multimeter to see what’s connected when the switches are on and off.

    In my case, the negative terminals were all already tied together, and each physical switch simply connected the positive sides of the output and input L/R channels together. I added relays in parallel to these switches; the actual modification to the speaker selector wasn’t very involved (soldering wires onto the huge leads on the back of those speaker wire terminals). I think it’d make a great and useful first project — let me know if you end up building one!

  20. David,

    Thank you for responding to my post. After looking at your schematic more carefully, I’m a little nervous because I’m not familiar enough with electrical design to understand all the symbols and pin call-outs. I have also never programmed the Raspberry Pi unit. I was wondering if would consider building and programming a module and what you would charge? Thank you.

    Ralph

  21. David,

    I appreciate you sharing this project! Do you happen to have an image of the underside of your perf board?

    Thanks, Tom

  22. Here you go, though it’s quite messy! I only had very rudimentary tools on hand at the time. If possible, I’d strongly recommend using perfboard with at least plated through holes; the unplated board I used was kind of a pain. Note that your parts may have different pinouts, too.

  23. Ralph, unfortunately I don’t have any time to make more of these right now. Maybe you can find a friend who could help you out?

  24. Nice write up, i think a lot of ppl could use this. I’m looking to do something similar, i have a denon amp for the home theater with a 2nd zone. the denon has a smartphone app to control everything. I plan on using zone 2’s low level signals going to a 12 channel amp, from there i need to think of something similar to what you did. in this case i need to control the volume for each channel that will be located throughout the house. I guess my question to you is did you ever have plans to give each channel individual volume control? if not do you think it would be possible to accomplish with the raspberry pi?

  25. Hey Bryan, in my setup each room has an in-wall volume control, so I didn’t consider adding individual volume controls. I’m not sure how it would be done. Perhaps you could try doing something with audio digipots in series with the output, and control them over SPI/I2C from the Raspberry Pi? They may have to pass a fair bit of current at max volume, though. You’d also want logarithmic steps in resistance for a volume control. A quick search only turned up parts suitable for high-impedance outputs; they don’t seem suitable for the speaker side of the amplifier. I’d like to hear if you find a better way.

  26. Hi David,

    Yes that was my fear of having to pass that much current. I also wouldn’t want to change the impedance presented to the amp and cause it to be unstable. I think if i try anything it might be a servo motor controlling the gain knobs for each zone, using either an arduino or raspberry pi. or i’ll just live with it and keep the volume rockers.

  27. Ok I give up. Still early in the process of learning, I’ve done a lot of research to try to setup the server but cannot get it to serve the cloned github repo. Help anyone?

  28. Hi! Impressive setup and impressive skillset you got there!! Sorry to say I dont have neither the time nore the know-how to build the setup myself so therefore Im looking for a sollution that might be abit more “simple”…

    I want to be able to stream audio from my Synology NAS, controlled either by the build in interface or an android app, to six zones. Each zone is going to have two or three speakers.

    Can you maybe point me in the correct direction for a raspberry-sollution or should I cave in and just go for the “air play wifi sound reciver” sollution that Im leaning towards? (My three kids needs their dad daytime so I dont have time at the present to learn that much new skills…)

    Best regards, and again, impressive work!! Andreas Sweden

  29. Hi,

    Excellent project. I’m going to give it a go. However I have a few questions.

    I was going to use a Pi 2 and also add a few additional relays. However I can see where you specify the pinning pairs, and I saw where you define the sources, however I do not appear to see where you have defined the relation between pins and a relay for a destination device. Can you tell me where this is defined?

    Also, I see that you can either send the audio via the Pi to the relay or out the AUX to an external device and back into the relay. My audio will only stream via the Pi, so I was wondering where this is specified where the audio source exists i.e. only via the Pi. However, as I understood it, the gpios cannot be used for audio as standard, a circuit using MCP3008 would have to be used for example, but I didn’t see this in your hardware list or cicruit diagram.

    Thanks. And again, awesome project :)

  30. Hi,

    I just noticed. You are feeding everything through the AUX jack. So you can ignore the last question. I only need to know the answer to the first question :)

  31. Hey DABBLER, the pins for the relays are defined here: https://github.com/iceboundflame/pandorica-spksel/blob/master/control.py in the variable PIN_MAP. Each entry in PIN_MAP is a pair of pins for a given room. The first and second pins in the pair control the “off” and “on” coil for that relay, respectively. The rooms are indexed from 0 through 4, and you can test it out by running control.py (more info in the README). You can also change the labels of the rooms in the templates/index.jade file.

  32. Hi,

    Thanks.

    I didn’t see the .jade file. I never noticed this until now, this explains what I was missing.

    Thanks again.

  33. Me again :)

    OK one last question I think. For your hifi, aux connection. How is this original circuit connected and how are you controlling it?

    Like I mentioned before, I want to stream directly from the Pi, but I don’t quite follow where the audio stream comes in to your board and how its split from the source to the various destination speakers.

    If you could explain it would be a great help.

    Thanks.

  34. Hi, originally, I just had the hi-fi’s speaker output connected to a speaker selector, which splits the signal to 5 sets of speakers, each with a switch. What I’ve done now is to connect the Pi to the hi-fi’s input as an AirPlay source. The Pi also controls the relay board which controls which of the rooms’ speakers are enabled.

  35. IDE cables have a key in the middle, reventing insertion onto the RPI. How did you get it to work?

  36. Hey; I think my Raspberry Pi just had bare header pins, there was no plastic shroud which interfered with the connector key. You can also just use a bunch of female jumper cables.

  37. No…

    The RPI has an array of pins.

    The IDE cable has an array of slots, with one missing slot near the center.

    Attempting to insert an IDE cable onto a RPI is impossible because there’s no slot for the pin.

  38. Ah I see now; some IDE cables have pin 20 blocked. My IDE cable had no key (40 holes). I cut the 40-pin connector down to a 26-pin connector with a razor blade and hot glued it to keep it together; kind of hacky but workable. Looks like the Model B+ now has 40 pins. Maybe you could drill out pin 20 on the connector to allow it to fit, or remove the pin on the Raspberry Pi side with a soldering iron.

  39. What a great tutorial David. I’m planning to build this system for a friend who just bought a house. I just want to control 3 zones. I have an amplifier with 4 speakers output (2 zones). I will split one output off the amplifier, so I get my 3 zones and don’t need a physical zone-selector. I want to control the power to the amp also with a relay, so i’m sure when accidently no zones are selected then the power to the amplifier will shut down also. Unless my raspberry pi will get a hard reset ;). What do u think of this setting (No selector)? Is it nescessary to build this relay board with the IC? Or can I use another simple (pre-build) relay board also (Like one from SainSmart). Till now, i have only experience with those relays icw Pi. I don’t need to care for load to my amplifier if no speakers are selected, because it’s turned off then. And honestly, i don’t know anything about the noise what can be produced by the relays… So I guess thats why u build it your own.

    Kindly Regards

  40. Thanks Ron! In my case I used IR to control amplifier on/off. If you want to switch mains power to the amplifier instead, then you’ll need relays rated for that voltage. That is a common use case and I would recommend using one of the many commonly available relay boards; need to make sure it is properly enclosed/protect from shock hazards.

    In my case, I was switching low-voltage speaker wires with the small relays. I needed latching relays with dual poles (one for each channel), and I couldn’t find such a relay board already available. If you want to control the third zone independently of the other two zones, it seems you will still need two relays for the speakers. So you’d have: Amp Zone 1 => first set of speakers, and Amp Zone 2 => audio relay board => second and third set of speakers. This is separate from the power control of the amplifier.

    On noise: Since my relays are latching, they are not energized except when switching on/off. The output side (between amp and speakers) has very high levels and is not sensitive to noise anyway.

  41. Hi. I am looking to do a similar project but for a public announcement system so that I can control what speaker(s) the announcement will be heard.

    However, the amp I am using is a 100v amp as it makes wiring easier for the large site.

    Can you advise what relays should be used for switching these 100v speakers?

  42. David, Thx for your very quick reply. I know how to switch the amplifier with high voltage relays. I build such circuits before. And this will be seperate from the speaker selectors. This part was just some extra information ;).

    I don’t think I explained my question well. Other situation: my Amp has 2 speakers output (1 left and 1 right in 1 zone). I will split these 2 outputs to 6 speakers (3 left, 3 right in 3 zones), just by adding some parrallel wires. Because i’ll never use 3 zones at the same time.

    Anyway, i think above is not relevant for my question: Is it possible to switch one speaker by putting only the + through a relay? I have this relay: http://www.ebay.com/itm/270852225053?_trksid=p2060353.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT
    Or am I thinking to cheap, and isn’t this the right solution? If i’m right this relay is also only energized at switching on/off.

    It is my lack of knowledge about relays and maybe low current circuits to know how to build this. I have no idea what physical specs this relay must have or must not have.

    Thx again!

  43. Ron: From a quick look it seems like it should work. Yes, only one wire of the speaker needs to be interrupted. You will have to use one relay per speaker, since your relays are single pole. It doesn’t look like those relays are latching; they only have one magnetic coil inside. So it will have to stay energized the whole time the speaker is enabled (i.e. Raspberry Pi will output logic ON to keep the speaker on). That should be perfectly fine, now that I think about it more carefully. These relays appear to be way more capable than you need for switching speaker audio (10A is far more than you will see in a speaker wire).

    Note the Raspberry Pi GPIOs are 3.3V and the ebay listing is a “5V relay board”. But looking carefully at the listing I think it may still work. The schematic from the listing you linked indicates:

    1. It already has internal drivers for each relay. The relay actuators (electromagnets) are powered from 5V on “JD-VCC”. There is a separate power supply “VCC” for signal. They are jumpered together but you can remove that jumper, probably intended for 3.3V signals.
    2. The input signals are opto-isolated from the relays. When input signal == VCC, the relay is off. When input signal is pulled to ground, the relay is on.

    Thus, try powering VCC with 3.3V and JD-VCC with 5V on this relay. Then, set the GPIO LOW to turn on the relay. Best of luck!

  44. Sam: Sounds like a cool setup! I have no experience with such systems, but I guess the relays must be rated for at least 100V AC. Do you know the power rating or impedance of the speakers? You can use that to compute how much current is expected on each relay. I think a relay board like the one Ron linked above (SainSmart 8 Channel DC 5V Relay Opto-couple) will probably work.

    Note that we’re taking some shortcuts as the amp will see very different impedances as different numbers of speakers are enabled/disabled. Profeessional selector boxes seem to have huge dummy resistors inside for when the speakers are off. I’m not sure if this really matters (I didn’t see much practical effect, maybe a tiny decrease in speaker volume when more speakers selected), but you may want to investigate further if you are playing with an expensive amp.

Leave a Reply

Your email address will not be published. Required fields are marked *