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 <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();
}
}
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
@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
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
@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
@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
@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
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
@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
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
@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.
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.
@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!
@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
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