If you've got a Squeezebox then you've probably got an amplifer to go with it. Having to get up and turn the amp on and off when you need it is just far too tedious (especially if your Squeezebox is hidden away in a cupboard or something), so we need a gadget that can turn the amp on when the Squeezebox turns off, and turns the amp off again when it turns off. Sounds pretty simple, right?
There are a few other attempts to do this around the Internet. There's a server module called PowerCenter that can send commands via a serial port to and X10 sender. The X10 signals then control plug-in X10 modules on the amplifer power cord. This sort of approach works well, but needs quite a bit of X10 hardware to make it work.
There's a DIY hardware hack that uses a sensor on the front panel LED of a Duet Receiver to detect if the player is on or off. This particular hack uses power from inside the Receiver, and of course only works with a Duet. As it happens, my particular concern is with a Duet, but I'd rather not have to crack open the case and fit some dangling wires out of it.
So with all that in mind, this project uses the Squeezebox's power supply for it's power source, and passes that power on to the player (it should work with most of the modern Squeezebox models too - not quite with the Squeezebox 1 though - see below). It uses the Toslink (SPDIF) optical output of the Squeezebox as the means of detecting the players state, and it uses a mains relay to switch the amp on and off. It's possible to use the Squeezebox's coaxial digital output if you don't want to use the optical, or it could have an "optical pass through" if you still want to use the optical output.
The actual electronics can control two relays (the second isn't used in the pictures below though). The idea is that you can use one relay to control the amp power and the other to switch the speakers in or out. This can be used to avoid "switching bang" that some cheap amps suffer from when they turn on or off. The second relay essentially disconnects the speakers from the amp until the "bang" has subsided.
How does it work?
Toslink is pretty difficult to decode and use. Instead of trying to do that, this project looks at the carrier signal and uses that to work out the state of the player. It turns out that Toslink uses a 1413Khz carrier signal, which is running the whole time the player is on. However, if the player is off, that carrier frequency drops to 1323KHz. When the player is actually playing music the carrier frequency isn't stable, but it's usually up at about 1700Khz, and it doesn't seem to matter what the volume is or what type of music is playing. This is all detectable with a frequency counting multimeter, and also with a suitably setup Arduino.
The Arduino in the circuit acts as a frequency counter which periodically checks the carrier signal frequency. From that, it controls a relay, which switches the mains power to the amp on and off. The Arduino can't switch the relay directly, so we use a transistor to actually switch the relay. The circuit diagram is shown below.
The optical receiver is a powered device which operates at 5V. It's output is TTL compatible (although it's edges aren't necessarily square), so we just connect the output to the Arduino. We have to use Arduno digital pin 5 (physical pin 11) for the optical input (this isn't configurable) because it's the only pin connected to counter/timer 1. By letting the counter be incremented by the optical, we can count how many increments there were in a set time, and so work out the frequency of the incoming signal.
As a power saving measure, we power the optical receiver from the Arduino. When we look at the code, we'll see that we only read the frequency of the signal every so often, so for the rest of the time we can power-down the receiver. This saves us a few milliamps, but isn't strictly necessary (so you could permanently power the optical reciever and it'll work just fine). We found that you absolutely have to have an RF decoupling capacitor on the power for the optical receiver. WIthout it, it's really, really unreliable, so we put a 0.1uF capacitor across power and ground.
The Arduino then needs to switch one or two relays on and off. The chip's pins aren't powerful enough to do this on their own, so we use the chip to energise a transistor which switches the relay coil on and off. We used a 2N2222A transistor for this, but any sort of general purpose NPN transistor will do.
All the rest of the circuit is just to make the Arduino work. The power supply isn't shown, but is a linear PSU chip, something like a 7805 is perfect for the job. We found that when one relay was energised the whole circuit took about 80mA, so make sure that your supply chip can provide at least that much (if you're using two relays, then maybe rate your power supply at 200mA or so to give yourself plenty of spare capacity).
The program (or Arduino "sketch") we used is a bit more complicated than it strictly needs to be. We decided to try and make the whole circuit as low power as we could. The idea is that when the player (and amp) are switched off that the circuit should take an absolutle minimum of current for itself. We got it down to less than about 5mA, which seemed pretty good.
We've used lots of power saving tricks to get our consumption down. We use the main clock pre-scaler to reduce the Arduino's clock speed when we're not doing very much. We also have set all the ununsed pins into a low-power state, and use interrupts to do absolutely everything. To get all that to work, we've recycled timer/counter 0, which means that delay() and millis() aren't available in our sketch (delay() isn't low-power, so we don't use it here). We also power down the optical receiver when we're not using it.
Timer/counter 1 is entirely consumed by being a counter for the incoming optical signal. That means we've got timer 2 and timer 0 available. We use timer 2 to provide a "metronome" sort of interrupt, which notionally runs every 100mS (as we'll see, it's not that frequent in practice). When that interrupt fires, it does maintenance on the relays (ie. turns them on or off if they need it), and does frequency measurements every 4 interrupts (around about every half a second).
When a frequency measurement is taken, timer 0 is enabled and runs around every millisecond. When it fires, it reads the state of the counter (counter/timer 1) and adds whatever is in there to a total. It'll keep doing this until it's disabled, so by letting it run for (say) 100mS, we can measure 100mS of optical input in 1mS chunks (which means we can measure the fast input without counter 1 overflowing). The 100mS interrupt turns interrupt 0 on during one "tick", amd turns it off on the next "tick". This means we get about 100 counter measurements inbetween ticks.
Power savings on an Arduino chip can be achieved in a number of ways. We do the "easy" things like setting the unused pins into a low-power state, and we turn off the peripherals in the chip that we're not using (including the serial port). However, all this doesn't actually save that much power. To get the really great power savings, we have to run the chip at lower clock rate, and do as little "background" work as possible. Since timer 0 is no longer being used for delay() and millis(), we've saved a bit of background work when we're not doing frequency counting.
We tried dropping the clock speed down (using the clock pre-scaler) to a really low speed (after all, we're not doing that much work, so should be able to do it on a slow clock). The trouble was that the frequency measurements were very strange (we seemed to be getting higher values for lower input frequencies). Debugging this proved to be difficult, so we elected to run the chip at low speeds when we could, and higher speeds when doing frequency measurements. This means that the "100ms" interrupt no longer happens at 100mS intervals, because it's all dependent on the clock, and we're changing the speed of that clock in the code. However, a little experimentation got the interrupt to occur at about the right rate, even if it's not quite every 100mS.
All this makes the code a bit more complicated to read and to understand. However, we got the power consumption down to less than about 5mA, even though the chip is doing frequency measurements every half a second or so. We think that's pretty good going!
The Squeezebox 1
The older models of Squeezebox (like the Squeezebox 1) can't turn their digital outputs off when the player is off. This means that the optical carrier frequency doesn't change when the unit is off, so we can't easily detect the state of the player. It seems that the player does send a "I'm turning off" message via the digital output, which we can see as a short burst of lower frequency carrier signal. The trouble is that it's very short lived, so measuring it's frequency reliably is difficult, which makes reliably detecting it difficult.
One possible strategy is to measure the carrier frequency as we are, and to additionally detect when music is actually playing. This is easy because when music is playing the carrier frequency goes up to about 1700KHz (variable). We could simply turn the amp off after (say) an hour of no music being played. Indeed, this might be a good strategy anyway, because it avoids needing the server to power-down the players when they're not being used. We haven't implemented this strategy (yet), although as we've got a Squeezebox 1, we'll hopefully get to it soon.
The circuit construction is pretty simple - it's not much more than the Arduino itself. However, if you're going to switch mains power (as we are), then you really do need to take some precautions. Mains electricity will quite happily kill you if you don't respect it, so be very, very careful and double check your work!
We constructed our circuit on a piece of strip board. We used a pair of flying leads to connect to the relay, which we soldered directly to some mains flex connected to some IEC power sockets. We used lots of heatshrink to cover over all the mains power wires, and we even made a box with a divider in it so that it was clear where the mains is and where the low voltage is (see below). We used a 3D printer to make the box (which is on Thingiverse), but any suitably sized plastic box will do.
One problem we didn't solve very well is the power plug you need to connect power to the Squeezebox Duet Receiver. We couldn't find a supplier who had the exact same sort of plug anywhere, so ended up cutting the end off the power supply cable and using that (we put a standard 2.1" power plug on the end of the wire we just cut, by the way). This all means we've got the standard power supply with a 2.1" plug on the end of it, a corresponding socket on our circuit and a short length of flying lead with the Receiver's power plug on the end of it.
Here's a picture of the finished article:
Here you can see our little circuit on the right, with an optical receiver and a 2.1" power socket on it. The flying lead is connected to the power input, so it'll ouput the same thing as our circuit receives. The green and yellow flying leads go to a mains power relay (with a 5V coil) that switches the Live mains from the IEC socket on and off. The mains Neutral and Earth are just passed straight through to the IEC output socket.
Finally, here's a picture of the switch in it's final home, on top of the amp and underneath the Duet Receiver:
(Apologies for the low quality picture - it proved to be hard to get a decent shot inside a cupboard in the corner of our dining room!)
To make this gadget, you'll need:
- Strip board
- An Arduino Chip
- 16MHz crystal
- 0.1uF decoupling capacitors
- 22pF crystal capacitors
- A 5V power regulator
- A few resistors
- A mains power relay with a 5V coil
- A general purpose diode (eg. 1N4001)
- A general purpose transistor
- A male and a female IEC power socket
- A SPDIF/Toslink fibre optic receiver
- A power socket (we used a 2.1" socket)
- Various bits of wire
- A box
We can supply most of these things from stock. Contact us if you need any of the other bits.