Ethernet DMX

Last week I recieved the Arduino Ethernet Shield – http://www.arduino.cc/en/Main/ArduinoEthernetShield
There were all ready complete examples provided, so it was very easy to get started.
Then I thought it would be nice to have a Ethernet DMX Controller, so i could type the IP-Adress of the Ethernet Shield in explorer, and from there control my movinghead (Stairville MV250H)

 

Then I found this page showing how to use an MAX485 and the Arduino as a DMX interface – http://iad.projects.zhdk.ch/physicalcomputing/hardware/arduino/dmx-shield-fur-arduino/
I tried it, and it worked :) – And the Arduino could communicate with my movinghead.
Then I combined the Ethernet example and the DMX example, to make a HTML Page where i could click on different buttons to change the DMX values that would be sent to my movinghead.

 

Try it out yourself… You need a MAX485, follow the link above on how to connect it to the Arduino. Just use pin 3 instead of pin 11, as the Ethernet shield uses Pin 9 to 13!

 

Here is the Arduino code:

#include <Ethernet.h>
#include <stdio.h>

// include pin definition library -----------------------------------------------
#include "pins_arduino.h"

// variable definitions ---------------------------------------------------------
int sig = 3;       // DMX signal pin - DO NOT CHANGE

// network configuration.  gateway and subnet are optional.
byte mac[] = { 0x00, 0x12, 0x34, 0x56, 0x78, 0x90 }; // Change this to the MAC the Ethernet shield should have
byte ip[] = { 192, 168, 1, 1 }; // Change this to the IP-Adress the Ethernet shield should have

byte DMX_Get[]={0,0,0,0,0};
byte Buffer[]={0,0,0,0,0};

Server server = Server(80);
unsigned long time;

// function definitions ---------------------------------------------------------
/* Sends a DMX byte out on a pin.  Assumes a 16 MHz clock.
* Disables interrupts, which will disrupt the millis() function if used
* too frequently. */
void shiftDmxOut(int pin, int theByte)
{
  int port_to_output[] = {
    NOT_A_PORT,
    NOT_A_PORT,
    _SFR_IO_ADDR(PORTB),
    _SFR_IO_ADDR(PORTC),
    _SFR_IO_ADDR(PORTD)
    };

    int portNumber = port_to_output[digitalPinToPort(pin)];
  int pinMask = digitalPinToBitMask(pin);

  // the first thing we do is to write te pin to high
  // it will be the mark between bytes. It may be also
  // high from before
  _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
  delayMicroseconds(10);

  // disable interrupts, otherwise the timer 0 overflow interrupt that
  // tracks milliseconds will make us delay longer than we want.
  cli();

  // DMX starts with a start-bit that must always be zero
  _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask;

  // we need a delay of 4us (then one bit is transfered)
  // this seems more stable then using delayMicroseconds
  asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
  asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");

  asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
  asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");

  asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
  asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");

  for (int i = 0; i < 8; i++)
  {
    if (theByte & 01)
    {
      _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
    }
    else
    {
      _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask;
    }

    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");

    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");

    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");

    theByte >>= 1;
  }

  // the last thing we do is to write the pin to high
  // it will be the mark between bytes. (this break is have to be between 8 us and 1 sec)
  _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;

  // reenable interrupts.
  sei();
}

void SendDMX_Values() {
  /***** sending the dmx signal *****/

  // sending the break (the break can be between 88us and 1sec)
  digitalWrite(sig, LOW);
  delay(10);

  // sending the start byte
  shiftDmxOut(sig, 0);

  shiftDmxOut(sig, DMX_Get[0]); // Pan value
  shiftDmxOut(sig, DMX_Get[1]); // Tilt value
  shiftDmxOut(sig, DMX_Get[2]); // Shutter open
  shiftDmxOut(sig, DMX_Get[3]); // Clear gobo
  shiftDmxOut(sig, DMX_Get[4]); // Color fade

  for (int count = 1; count <= 507; count++)
  {
    shiftDmxOut(sig, 0);
  }
  /***** sending the dmx signal end *****/
}

void setup()
{
  pinMode(sig, OUTPUT);       // data pin to dmx board
  // initialize the ethernet device
  Ethernet.begin(mac, ip);  //, gateway, subnet);
  server.begin();
  Serial.begin(9600);
}

void strcat(char* original, char appended)
{
    while (*original++)
  ;
    *original++ = appended;
    if (appended)
  *original = '\0';
}

void Form_Code(Client client, char type, byte arraynumber, byte number, byte value, char text[15]) {
  char ValueToBePrinted[4];
// if (type == 'p') {
    server.print("<form name='");
    server.print(type);
    server.print(number+48);
    server.print("' method='get'><input name='");
    server.print(type);
    server.print("' type='hidden' value='");
    sprintf(ValueToBePrinted, "%d", int(value));
    server.print(ValueToBePrinted);
    server.print("'>");
    server.print("<input type='submit' value='");
    server.print(text);
    server.print("'");
    if (DMX_Get[arraynumber] == value) {
      server.print(" disabled='disabled'");
    }
    server.print("></form>");
  //}
}

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

    server.print("HTTP/1.0 200 OK\r\nServer: arduino\r\nContent-Type: text/html\r\n\r\n");
    server.print("<HTML><HEAD><TITLE>");
    server.print("Arduino Web-Server - ");
    server.print(millis());//to make sure that we habve a new page
    server.print("</TITLE>");
    server.print("<script type=\"text/JavaScript\"><!--function timedRefresh(timeoutPeriod){setTimeout(\"location.reload(true);\",timeoutPeriod);}//--></script>");
    server.print("</HEAD><BODY>");
    capturevariable(client);//dump the headers and recover any values passed in from the form
    server.print("<br><br>");

    server.print("Pan:");
    Form_Code(client, 'p', 0, 1, 0, "0");
    Form_Code(client, 'p', 0, 2, 127, "127");
    Form_Code(client, 'p', 0, 3, 255, "255");
    server.print("Tilt:");
    Form_Code(client, 't', 1, 1, 0, "0");
    Form_Code(client, 't', 1, 2, 127, "127");
    Form_Code(client, 't', 1, 3, 255, "255");
    SendDMX_Values();
    server.print("Color:");
    Form_Code(client, 'c', 4, 1, 0, "White");
    Form_Code(client, 'c', 4, 2, 20, "Green");
    Form_Code(client, 'c', 4, 3, 30, "Magenta");
    Form_Code(client, 'c', 4, 4, 40, "Light Blue");
    Form_Code(client, 'c', 4, 5, 50, "Amber");
    Form_Code(client, 'c', 4, 6, 60, "Red");
    Form_Code(client, 'c', 4, 7, 70, "Blue");
    Form_Code(client, 'c', 4, 8, 80, "UV Purple");
    Form_Code(client, 'c', 4, 9, 90, "Light Green");
    Form_Code(client, 'c', 4, 1, 100, "Orange");
    Form_Code(client, 'c', 4, 2, 110, "Yellow");
    Form_Code(client, 'c', 4, 3, 120, "Pink");
    server.print("Shutter:");
    Form_Code(client, 's', 2, 2, 255, "ON");
    Form_Code(client, 's', 2, 1, 0, "OFF");

    server.print("</BODY></HTML>");
    client.stop();//close the connection with the client
    delay(20);//pause wait  for a new connection
  }  

  SendDMX_Values();

}

void capturevariable(Client client){
  //we get a string like:GET /?p=255&t=100&o=255 we enter here after the ? or the &
  byte count = 0;
  int count_all = 0;

  char c = client.read();
  server.print(c);
  while ((c!= -1) && (c != '?')){
    c = client.read();
    server.print(c); // Debug
    count++;
  }

    count = 0;
    count_all = 0;

    while ((c != -1) && (count_all < 64) && (c != 'H')){
      c = client.read();
      server.print(c); // Debug
      count_all++;

      if(c=='p'){
        Serial.print("P=");
        c = client.read();//skip the =
        server.print(c); // Debug

        count = 0;
        while ((c != -1) && (count < 4) && (c != '&') && (c != ' ')){
          if (c != '&') {
            c = client.read();
            server.print("<b>"); // Debug
            server.print(c); // Debug
            server.print("</b>"); // Debug
            Buffer[count] = c-48;
            count++;
          }
        }
        if (count == 2) {
          DMX_Get[0] = Buffer[0];
        }
        if (count == 3) {
          DMX_Get[0] = Buffer[1];
          DMX_Get[0] = DMX_Get[0] + (Buffer[0] * 10);
        }
        if (count == 4) {
          DMX_Get[0] = Buffer[2];
          DMX_Get[0] = DMX_Get[0] + (Buffer[1] * 10);
          DMX_Get[0] = DMX_Get[0] + (Buffer[0] * 100);
        }
        Serial.print(DMX_Get[0], DEC);
      }

      if(c=='t'){
        Serial.print("T=");
        c = client.read();//skip the =
        server.print(c); // Debug

        count = 0;
        while ((c != -1) && (count < 4) && (c != '&') && (c != ' ')){
          if (c != '&') {
            c = client.read();
            server.print("<b>"); // Debug
            server.print(c); // Debug
            server.print("</b>"); // Debug
            Buffer[count] = c-48;
            count++;
          }
        }
        if (count == 2) {
          DMX_Get[1] = Buffer[0];
        }
        if (count == 3) {
          DMX_Get[1] = Buffer[1];
          DMX_Get[1] = DMX_Get[1] + (Buffer[0] * 10);
        }
        if (count == 4) {
          DMX_Get[1] = Buffer[2];
          DMX_Get[1] = DMX_Get[1] + (Buffer[1] * 10);
          DMX_Get[1] = DMX_Get[1] + (Buffer[0] * 100);
        }
        Serial.print(DMX_Get[1], DEC);
      }  

      if(c=='s'){
        Serial.print("S=");
        c = client.read();//skip the =
        server.print(c); // Debug

        count = 0;
        while ((c != -1) && (count < 4) && (c != '&') && (c != ' ')){
          if (c != '&') {
            c = client.read();
            server.print("<b>"); // Debug
            server.print(c); // Debug
            server.print("</b>"); // Debug
            Buffer[count] = c-48;
            count++;
          }
        }
        if (count == 2) {
          DMX_Get[2] = Buffer[0];
        }
        if (count == 3) {
          DMX_Get[2] = Buffer[2];
          DMX_Get[2] = DMX_Get[2] + (Buffer[0] * 10);
        }
        if (count == 4) {
          DMX_Get[2] = Buffer[2];
          DMX_Get[2] = DMX_Get[2] + (Buffer[1] * 10);
          DMX_Get[2] = DMX_Get[2] + (Buffer[0] * 100);
        }
        Serial.print(DMX_Get[2], DEC);
      } 

      if(c=='c'){
        Serial.print("C=");
        c = client.read();//skip the =
        server.print(c); // Debug

        count = 0;
        while ((c != -1) && (count < 4) && (c != '&') && (c != ' ')){
          if (c != '&') {
            c = client.read();
            server.print("<b>"); // Debug
            server.print(c); // Debug
            server.print("</b>"); // Debug
            Buffer[count] = c-48;
            count++;
          }
        }
        if (count == 2) {
          DMX_Get[4] = Buffer[0];
        }
        if (count == 3) {
          DMX_Get[4] = Buffer[4];
          DMX_Get[4] = DMX_Get[4] + (Buffer[0] * 10);
        }
        if (count == 4) {
          DMX_Get[4] = Buffer[4];
          DMX_Get[4] = DMX_Get[4] + (Buffer[1] * 10);
          DMX_Get[4] = DMX_Get[4] + (Buffer[0] * 100);
        }
        Serial.print(DMX_Get[4], DEC);
      }      

    }

    while ((c != -1)){
      c = client.read();
    }
}

  1. December 22nd, 2009 at 10:25 | #1

    Wow, impressive!

    I’d like to ask you about the performance. I’m sure you can output the DMX in time, but how long does it take to process the request, how responsive the system is?

    Can you please measure how much time was spent between submitting the form (hitting enter in your browser) and the lamp’s reaction?

  2. February 2nd, 2010 at 07:12 | #2

    Hey, great blog…but I don’t understand how to add your site in my rss reader. Can you Help me, please :)

  1. No trackbacks yet.