Home > Arduino > Ethernet DMX

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, 0x35, 0x35, 0x87, 0x66, 0x45 };
//                     EL    EK    TR    ON    IK
byte ip[] = { 192, 168, 2, 123 };


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();
    }
}
Categories: Arduino Tags: , ,
  1. abe
    October 4th, 2010 at 22:11 | #1

    Hello Thomas , very cool indeed , i tried the dmx MAX485 arduino configuration a few times before succesfully, but i can not make it work with the ethernet udp , what message structure should arduino received for the 5 channels , i see that the ethernet is connected and react to messages but they dont seem to be the right messages , any example please ?
    thanks

  2. October 16th, 2010 at 17:36 | #2

    @abe
    The code I’ve made makes a website, which you access by using a normal browser! So I doesn’t send RAW UDP packages to the Arduino, instead I chose the different DMX outputs on the webpage, redered by the Arduino!

    Thomas

  3. Jannick
    November 2nd, 2011 at 14:16 | #3

    hello Thomas, for my GIP( this is a project in Belgium for school that decides that we past the 6 year of not) i also used your program. i’ve tried a lot of programs that i’ve find on the net and these al works. now i want to use your program as example and after that modify for my fixtures. my problem is that i’ve got a lot of errors if i want to upload your program to my arduino uno. he complains that there is al program missing called “From_Code” and i can’t find this program on your site. could you please help me? (my apologies for my bad english because I’m from belgium)

    thanks
    Jannick

  4. November 3rd, 2011 at 22:15 | #4

    @Jannick
    Dear Jannick.
    Please try and copy paste the code from below again, because I made it easier to copy (without <pre> and such codes).
    I can’t find anything about “From_Code” in my code, so I don’t know why it should complain about it.

    Thomas

  5. Jannick
    November 15th, 2011 at 19:49 | #5

    @Thomas Jespersen
    thank you very much! now i can compile it. i shel test it on my school, because i haven’t an arduino uno at my home. again thak you very much!!

    Jannick

  6. November 15th, 2011 at 19:58 | #6

    @Jannick
    Great. Please keep us updated about your project 🙂

  7. Jannick
    December 2nd, 2011 at 13:47 | #7

    Thomas Jespersen :
    @Jannick
    Great. Please keep us updated about your project

    now I’m using another ethernetshield. one form iteadstudio.com.
    i can control it using HTML codes from the internet but now is the problem that i can’t insert buttons. can you help me?

    Jannick

  8. Jannick
    December 16th, 2011 at 14:36 | #8

    now i’ve got an other question. i can insert my buttons but i don’t know how i must read this in. where do you find al the information you’ve used to make this html page?

    Jannick

  9. December 23rd, 2011 at 17:59 | #9

    @Jannick
    Well this sounds like you are missing some of the basic HTML knowledge.
    To make a button you must use the < input > tag, which you probably figured out. To set it to do something when pressed, you must use some of the action parameters like onClick, onMouseOver.
    I would recommend you to take a look at the following very good HTML guiding page: http://www.w3schools.com/html/html_forms.asp

    Best Regards
    Thomas Jespersen

  10. Matt
    January 20th, 2012 at 19:30 | #10

    Hello, I’m trying to use your code, but I’m having an error with “pins_arduino.h” where can I find the arduino pins library?

    Thanks

  11. January 21st, 2012 at 15:31 | #11

    @Matt
    I guess you are using Arduino 1.0, as I am unable to compile my code with the new version too.
    If you would like to test the code please download one of the ealier versions of Arduino IDE and try to compile again.

  12. Marty
    January 22nd, 2012 at 15:41 | #12

    Hey I’ve been looking at these projects because im looking at doing this for a church. Would your project be compatible with an open source program such as freestyler instead of using the webpage?This would be very helpful because then I could control the lights with the above program with out being physically tethered to the dmx cable or network cable. Thanks for your help and I love the project.

  13. January 22nd, 2012 at 22:49 | #13

    @Marty
    Hi Marty.
    You wouldn’t be able to use my code as it is currently, as it’s functions is very limited and is running thru a browser.
    But you would definitely be able to expand this project and make it use a socket connection to a program running on a computer, so you would be able to remotely control all the DMX channels!

  14. Marty
    January 24th, 2012 at 00:26 | #14

    @Thomas Jespersen
    I am fairly uneducated when it comes to code so I would not know how to do that. If you could point me in the right direction or tell me something else I could do I would greatly appreciate it
    Thanks

  15. January 24th, 2012 at 17:58 | #15

    Dear Marty.
    I will recommend you to buy and Arduino and an Ethernet shield to play around with that first, so you can get a feeling on the environment.
    You could also have a look at our WiFi controlled robot, which is controlled using a Visual Basic .NET application, connecting to a local port on the WiFi shield (on the Arduino).

    Another option is to let us do the project for you. We will do all the required hardware and software and you will end up with an easy, inexpensive, plug and play solution.

    Best Regards
    Thomas Jespersen

  1. June 3rd, 2010 at 09:06 | #1