Ethernet control for my office “traffic lights”

A couple of years ago, I wrote about the “traffic lights” I’d created for my home office (and subsequent “upgrade”). Shortly after that, I updated the solution to use three LEDs (as shown below) but it still wasn’t quite what I needed. Walking to the door to push a button and change the light defeated the object somewhat.  I needed to enable this device with a “web service”!

The solution comes in the form of an Arduino Ethernet Shield, allowing pin control over a standard Ethernet connection.  I didn’t use the official shield though – cheap imports can be found on eBay for around £7.  Following that, I amended my code using the Instructables Arduino Ethernet Shield Tutorial and another Instructables post on controlling an LED over the Internet using an Arduino.

The end result is below (or on Github) – and the Arduino uses DHCP to obtain an IP address (reservations can be used to control which one – or DHCP logs can be analysed) and a simple query string is read to set the light using:

  • http://xxx.xxx.xxx.xxx/?r for red.
  • http://xxx.xxx.xxx.xxx/?a for amber.
  • http://xxx.xxx.xxx.xxx/?g for green.

Anything else fails back to red.  

/*
Red/green LED indicator with pushbutton control
Based on http://www.makeuseof.com/tag/arduino-traffic-light-controller/

USE_GITHUB_USERNAME=mark-wilson

*/

// Setup Ethernet Shield
#include <SPI.h>
#include <Ethernet.h>
boolean reading = false;

// Enter a MAC address and IP address for your controller below.
// The IP details will be dependent on your local network (commented out if DHCP in use):
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// byte ip[] = { 192, 168, 0, 112 }; //Manual setup only
// byte gateway[] = { 192, 168, 0, 1 }; //Manual setup only
// byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// Pins for coloured LEDs
int red = 3;
int amber = 4;
int green = 5;
int light = 0;

int button = 2; // Pushbutton on pin 2
int buttonValue = 0; // Button defaults to 0 (LOW)

void setup(){
Serial.begin(9600);

// Set up pins with LEDs as output devices and switch for input
// Pins 10,11,12 & 13 are used by the Ethernet Shield
pinMode(red,OUTPUT);
pinMode(amber,OUTPUT);
pinMode(green,OUTPUT);
pinMode(button,INPUT);

// start the Ethernet connection and the server:
Ethernet.begin(mac);
//Ethernet.begin(mac, ip, gateway, subnet); //for manual setup

server.begin();
Serial.println(Ethernet.localIP());
}

void loop(){

// listen for incoming clients, and process qequest.
checkForClient();

// Read the value of the pushbutton switch
buttonValue = digitalRead(button);
if (buttonValue == HIGH){
changeLights();
delay(1000); // Wait 1 second before reading again
}
}

void changeLights(){
// Change the lights based on current value: 0 is not set; 1 is red; 2 is amber; 3 is green
switch (light) {
case 1:
turnLightAmber();
break;
case 2:
turnLightGreen();
break;
case 3:
turnLightRed();
default:
turnLightRed();
}
}

void turnLightGreen(){
// Turn off the red/amber and turn on the green
digitalWrite(red,LOW);
digitalWrite(amber,LOW);
digitalWrite(green,HIGH);
light = 3;
}

void turnLightAmber(){
// Turn off the green/amber and turn on the red
digitalWrite(green,LOW);
digitalWrite(amber,HIGH);
digitalWrite(red,LOW);
light = 2;
}

void turnLightRed(){
// Turn off the green/amber and turn on the red
digitalWrite(green,LOW);
digitalWrite(amber,LOW);
digitalWrite(red,HIGH);
light = 1;
}

void checkForClient(){

EthernetClient client = server.available();

if (client) {

// An http request ends with a blank line
boolean currentLineIsBlank = true;
boolean sentHeader = false;

while (client.connected()) {
  if (client.available()) {

    if(!sentHeader){
      // Send a standard http response header
      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println();
      sentHeader = true;
    }

    char c = client.read();

    if(reading && c == ' ') reading = false;
    if(c == '?') reading = true; //found the ?, begin reading the info

    if(reading){
      Serial.print(c);

       switch (c) {
         case 'a':
           turnLightAmber();
           break;
         case 'g':
           turnLightGreen();
           break;
         case 'r':
           turnLightRed();
           break;
       }
    }

    if (c == '\n' && currentLineIsBlank)  break;

    if (c == '\n') {
      currentLineIsBlank = true;
    }else if (c != '\r') {
      currentLineIsBlank = false;
    }

  }
}

delay(1); // give the web browser time to receive the data
client.stop(); // close the connection:

}

}

All it needs now is another service to read my Lync status and call the Arduino accordingly, although, having got this far, I have to admit the form factor is not exactly brilliant and I probably should spend the money on a Busylight or a Blynclight instead so that my Arduino can be repurposed for a new project!

Or, of course, there’s Garry Martin (@GarryMartin)’s beautifully simple approach:

Leave a Reply