Friday, May 22, 2015

Arduino speaker controller











Pretty plain, but it does the right thing.


#include <SPI.h>
#include <Ethernet.h>
#include <string.h>


// Some unused IP address on the local network.

EthernetServer server( 80 ); 

#define RELAY_ON 0
#define RELAY_OFF 1

boolean showStatus = false;

boolean zone1 = false;
boolean zone2 = false;
boolean zone3 = false;
boolean zone4 = false;

// pin definition, one pin per speaker, 
static const int zone1L = 2;
static const int zone1R = 3;
static const int zone2L = 4;
static const int zone2R = 5;
static const int zone3L = 6;
static const int zone3R = 7;
static const int zone4L = 8;
static const int zone4R = 9;

void setupPins() {
    digitalWrite(zone1L, RELAY_OFF);
    digitalWrite(zone1R, RELAY_OFF);
    digitalWrite(zone2L, RELAY_OFF);
    digitalWrite(zone2R, RELAY_OFF);
    digitalWrite(zone3L, RELAY_OFF);
    digitalWrite(zone3R, RELAY_OFF);
    digitalWrite(zone4L, RELAY_OFF);
    digitalWrite(zone4R, RELAY_OFF);

    pinMode( zone1L, OUTPUT );
    pinMode( zone1R, OUTPUT );
    pinMode( zone2L, OUTPUT );
    pinMode( zone2R, OUTPUT );
    pinMode( zone3L, OUTPUT );
    pinMode( zone3R, OUTPUT );
    pinMode( zone4L, OUTPUT );
    pinMode( zone4R, OUTPUT );

void setup() {
    Ethernet.begin( mac, ip );


// set up buffer for reading web requests
static const int bufferMax = 128;
int bufferSize;
char buffer[ bufferMax ];

void loop() {
    EthernetClient client = server.available();
    if ( client ) {
        waitForRequest( client );

void waitForRequest( EthernetClient client ) 
    bufferSize = 0;

    while ( client.connected() ) {
        if ( client.available() ) {
            char c =;
            if ( c == '\n' ) {
            else {
                if ( bufferSize < bufferMax ) {
                    buffer[ bufferSize++ ] = c;
                else {

void handleRequest() {
    String request = String(buffer);
    request = request.substring(firstSpace, lastSpace);
    zone1 = request.indexOf("1") > -1;
    zone2 = request.indexOf("2") > -1;
    zone3 = request.indexOf("3") > -1;
    zone4 = request.indexOf("4") > -1;

      zone1 = true;
      zone1 = false;
      zone2 = true;
      zone2 = false;
      zone3 = true;
      zone3 = false;
      zone4 = true;
      zone4 = false;

    if (!showStatus) {

void setSpeakerState() {
    digitalWrite(zone1L, zone1 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone1R, zone1 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone2L, zone2 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone2R, zone2 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone3L, zone3 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone3R, zone3 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone4L, zone4 ? RELAY_ON : RELAY_OFF);
    digitalWrite(zone4R, zone4 ? RELAY_ON : RELAY_OFF);

void sendPage() {

void printHead() {

void printForm() {
   int pinState = digitalRead(zone4L);                                           

   pinState = digitalRead(zone3L);                                           
   pinState = digitalRead(zone2L);                                           
   pinState = digitalRead(zone1L);

void printTail() {


Unknown said...




Thank you.

Unknown said...

Ah, I figured the speaker wiring out.


Anonymous said...

Hi, Nice to meet you.

My name is Oscar, at WIZnet in Korea.




Hopefully, keep contacting us for the friendship.

Thank you very much.

Dale Anson said...



Dale Anson said...

Oscar, that's fine with me.

Unknown said...


Dale Anson said...


Etara said...


Anonymous said...

Great job Dale!




Dale Anson said...

Hi Oleg,



Anonymous said...



Mike V said...

Hi Dale,




Thank you in advance for any help.


Rodger said...


Dale Anson said...


Dale Anson said...


Unknown said...

Thank you for posting this project. I do have a question regarding an issue I am having connecting to my home network. I connect to the internet using a modem and EERO. EERO provides me the ability to manually set the IP Address and the MAC address. However, the MAC address in EERO is formatted as xx:xx:xx:xx:xx:xx. When I connect the speaker selector project to EERO using the Ethernet cable, the device does not show on EERO as being connected. I am able to put the IP Address in my phone and see the “Speaker Control Screen” but the when a speaker pair is selected on the screen, the relay does not function. I believe the MAC Address is not being recognized and that is why the device does not show on my EERO app as being connected and therefore the functionality fails.
Are you aware of anyone using this project with an EERO and if so did the code included in the project need to be altered in order accommodate the EERO MAC Address formatting

Thank you

Jim A.

Dale Anson said...

@Jim A. -- I would be surprised that it's problem with the MAC address. You can change it in the code and recompile just to make sure it's some number that's not already on your network. Did you change the IP address in the code? This version uses a hard-coded IP address, so if it's not one that is in range for your network, your EERO won't see it. (I'm not familiar with EERO, I assume it's router of some sort).

Unknown said...

Thank you for your response. I am fairly certain my issue is not the IP address. I did change it in the code and entered the same IP address number when manually entering this device on my network using the EERO app. EERO does replace the router and is a mesh system. In my system I have 3 EERO access points which provides excellent access to all areas of my house with no signal speed or strength of signal degradation when using multiple devices. Each access point has 2 Ethernet ports and one of those ports on one of the three access points is what I have the w5100 Ethernet shield device connected to.
In my post I focused on the MAC address because in the code the MAC address was formatted with 6 sets of 4 digits each separated by a comma. In EERO all devices have MAC Addresses formatted with 6 sets of 2 digits each separated by a colon. I received a compiling error when I tried to use a unique 6 sets of 2 digits each separated by a colon in the code with the error indicating the use of the colon was causing the error. I am referring to the line in the code beginning with “ byte Mac [ ] = “. Since I can’t seem to match the MAC address in the code with the MAC address I need to manually enter into the EERO app because of the formatting difference, I have assumed the MAC address is the crux of my issue.
Currently I have the same 6 sets of 2 digits in both the code and the MAC address line on EERO app device set up screen. The difference is in the EERO app set up screen the 6 sets of 2 digits are separated by a colon and in the code the 6 sets of 2 digits are separated by a comma. This approach does not result in a functioning display on my phone. When I enter the IP address I do get the phone to display the Speaker Control screen with the room names as I had coded them. The buttons on the phone do not activate the relays when pressed (highlighted). As I mentioned in my original post the device does not show in the EERO app on my list of connected devices, either as connected and active or connected and inactive device. This MAC address being used is unique to all other Mac addresses on my list of devices as shown in the EERO app.

Thank you again for the response. I reached out hoping either you or some reader may have tried to connect the speaker selector to an EERO network and had an answer I could try.

Once again I appreciate your posting this project. It is a perfect solution for my audio system. I will continue to see if I can find a solution.

Jim A

Dale Anson said...

Okay, I read up on EERO. It sounds a lot like Google Wifi. The MAC address isn't the problem, I'm certain of it. The 6 sets of 4 digits in the code for the MAC address are just hex values, so you can put the same values minus the "0x" in your EERO and use semi-colons there. I suspect the problem is actually the EEROs themselves causing the problem. If you can see the speaker control screen on your phone, then you are connecting to the arduino with a good IP address and the MAC address doesn't matter at that point. I've had no end of problems getting the Google Wifi to route correctly on my home network. These little mesh systems work well when it's all wifi, but seem to not do so well with wired networking and routing in general. If you have the time, patience, and a little more money, you could try using a wireless card like I did here:

Unknown said...


Thank you. I will check out the link attached.

Jim A

Unknown said...

Hi Dale,

Thank you so much for this. I already had a 4 Channel Speaker Control, which is fed via a Sonos Amp, and was looking for a way of making the speaker selection automated rather than manual. Came across your page and have been putting it all together over the past couple of weeks.
Everything is working great and I have successfully renamed my zones (using all 4) and set it up as per my network, however, I have one strange thing where when I go into the web server page, by default, all zones are ticked as on and only work when unticked.
I have tried changing the code where I think may help but can't get it right.
Any ideas?

Many thanks in advance, Steve.

Dale Anson said...

Hi Steve,

Did you see the lines that are crossed out in the code above in the handleRequest method? The if/else block below that is the replacement.

Mike V said...

Hey Dale,

I just wanted to comment that I find it amazing that you are still helping others with this project you did five years ago.

I know I crack a smile every time I use this project to switch speakers around my home or in the backyard.

Thanks again for posting this so long ago and many thanks for continuing to support it.


Unknown said...

Hi Dale,

Many thanks for your response but, unfortunately it only made things worse!
Probably something I'm doing wrong no doubt.

I removed the section of code which you scored out. The section "if/else" below was already in my code so verified, saved and uploaded to Arduino.
Now, the zones are checked/ticked at start, as before, but when you uncheck and click "save" they turn straight back to checked/ticked! Also, no switching of relay happens either :)

I tried changing some things myself but to no avail, so went back to my original code which was at least bringing speakers on and off albeit with the zone checks/ticks back to front, i.e. unchecked = relay/zone on.

Apologies in advance for your troubles.

A frustrated Steve.

Dale Anson said...

Hey frustrated Steve! Any chance your code is available somewhere that I could see it?

Unknown said...

Hi Dale,

Thanks for your response.

I can share a file with you but need an email address?
Can't post it on here either as we're restricted to characters.

Cheers, Steve.

Dale Anson said... should work