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();
}
}
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?
Hey, great blog…but I don’t understand how to add your site in my rss reader. Can you Help me, please