Art-Net to DMX using Arduino Nano with ENC28J60 & Ethercard.h

I've done an Art-Net to DMX project using a Nano and ENC28J60 Ethernet module and thought i'd share in the hope some people might give it a more thorough testing than what i can do (i've currently only 3 white LED strips) to see where it might fall down...

I've stripped out what i can to save memory. Compiled i'm using 29% of program memory and 70% of dynamic memory.

I've used DMX Workshop and Jinx to blink the LED strips on and off but i've noticed a slight delay after every few on/off cycles when i set it to a higher strobe rate and i'm not sure what that might be but aside from that, it appears to be working OK.

Here's my code:

/*
 * Chris Lyttle                                                 
 * Art-Net to DMX Controller Interface                          
 *                                                              
 * Programmed for Arduino Nano with ENC28J60 Ethernet shield    
 * Works with Arduino 1.6.8 using EtherCard & DmxSimple Library 
 * Takes ArtDMX packets sent via Ethernet from a PC and sends   
 * DMX lighting values out to the DMX universe                  
 *                                                             
 * Based on ARTNET RECEIVER by Christoph Guillermet and E1.31   
 * Receiver and pixel controller by Andrew Huxtable ported                 
 * to use EtherCard library for ENC28J60 and Art-Net instead of 
 * E1.31.                                                       
 *                                                              
 * ENC26J60 pins wired as follows:                                                                                          
 *                                                              
 * Enc28j60 SO  -> Arduino pin 12                               
 * Enc28j60 SI  -> Arduino pin 11                               
 * Enc28j60 SCK -> Arduino pin 13                               
 * Enc28j60 CS  -> Arduino pin 10                               
 * Enc28j60 VCC -> Arduino 5V pin (3V3 pin didn't work for me)  
 * Enc28j60 GND -> Arduino Gnd pin                             
 *                                                              
 */

#include <EtherCard.h>
#include <DmxSimple.h>

#define bytes_to_short(h,l) ( ((h << 8) & 0xff00) | (l & 0x00FF) );
 
#define STATIC 1  // to use a static IP
 
#if STATIC
// ethernet interface ip address. please change to your own
//for direct link from PC ethernet to ENC board, make ip 192.168.2.2 
//on PC, in ipv4 settings, make static IP 192.168.2.1, subnet mask 255.255.255.0 and gwip left empty
static byte myip[] = { 192,168,1,177 };
// gateway ip address not needed
//static byte gwip[] = { };
#endif
 
//ethernet mac address - //genetated from http://www.miniwebtool.com/mac-address-generator/ using Microchip OUI
//verified at http://sqa.fyicenter.com/Online_Test_Tools/MAC_Address_Format_Validator.php
static byte mymac[] = {0x01,0x00,0x00,0x45,0x08,0x11};    
 
byte Ethernet::buffer[529]; // tcp/ip send and receive buffer should be 512 dmx channels + 17 bytes for header

const int number_of_channels=512; // 512 for one full DMX universe (THIS TAKES UP LOTS OF SRAM)
const int channel_position=1; // 1 if you want to read from channel 1
//byte buffer_dmx[number_of_channels+channel_position]; //buffer to store filetered DMX data    ***bypassed this bit to save SRAM***
const int art_net_header_size=17;
const int max_packet_size=529;    //should be 512 + 17 bytes
char ArtNetHead[8]="Art-Net";    //first byte of an ARTDMX packet contains "Art-Net"
short Opcode=0;
boolean is_opcode_is_dmx=0;
boolean is_opcode_is_artpoll=0;


 
// callback that deals with received packets 
static void artnetPacket(uint16_t port, uint8_t ip[4], uint16_t src_port, const char *data, uint16_t len) {
  //Serial.println( "artnetPacket reached");       //print to serial for testing
  //Make sure the packet is an ArtDMX packet
  int check = checkARTDMX(data, len);  
  if (check){
    // It is so process the data to the LEDS
    sendDMX(data);
  }
}

/*
Do some checks to see if it's an ArtNet packet. First 17 bytes are the ArtNet header, the rest is DMX values
Bytes 1 to 8 of an Art-Net Packet contain "Art-Net" so check for "Art-Net" in the first 8 bytes
Bytes 8 and 9 contain the OpCode - a 16 bit number that tells if its ArtPoll or ArtDMX
Don't worry about the rest of the bytes until byte 18 on (DMX channel levels) 
*/
int checkARTDMX(const char* messagein, int messagelength) {   //messagein prob dont need to use a pointer here since we aren't writing to it
  //Serial.println( "checkARTDMX reached");       //print to serial for testing
  
  if(messagelength > art_net_header_size && messagelength <= max_packet_size) //check size to avoid unneeded checks
  {
  //read header
     boolean match_artnet = 1;
     for (int i=0;i<7;i++)
     {
      if(messagein[i] != ArtNetHead[i])   //tests first byte for  "Art-Net"
    {
    match_artnet=0; break;      //if not an artnet packet we stop reading
    }   
     } 
     if (match_artnet==1)//continue if it matches
     {
    //check which type of packet it is: ArtPoll or ArtDMX
    Opcode=bytes_to_short(messagein[9],messagein[8]);
     
     if(Opcode==0x5000)//if opcode is DMX type
      {
       is_opcode_is_dmx=1; is_opcode_is_artpoll=0;
      }   
       
     else if(Opcode==0x2000)//if opcode is artpoll 
     {
     is_opcode_is_artpoll=1;is_opcode_is_dmx=0;
     //( we should normally reply to it, giving ip address of the device)
     } 
   }
  }
  return 1;
}

/*
function to send the dmx data out using DmxSimple library function
Reads data directly from the packetBuffer and sends straight out
*/
void sendDMX(const char* packetBuffer) 
{
  //Serial.println( "sendDMX reached");       //print to serial for testing
  for(int i = channel_position-1; i < number_of_channels; i++)//channel position
  {
  //buffer_dmx[i]= byte(packetBuffer[i+17]);    //bypassed the dmx buffer altogether to save memory
  //DmxSimple.write(i,buffer_dmx[i]);
  DmxSimple.write(i,packetBuffer[i+17]);
  }
}
 
void setup()
{
  //Serial.begin(57600);        //for testing
  DmxSimple.usePin(3);          // DMX output is pin 3
  DmxSimple.maxChannel(512);    //should be 512

  ether.begin(sizeof(Ethernet::buffer), mymac, 10);   //10 at end initialises CS pin as pin 10 on arduino instead of default pin 8
 
  // Static IP 
  ether.staticSetup(myip);
    
  // Register listener
  ether.udpServerListenOnPort(&artnetPacket, 6454);           //artnetPacket function to handle event, listen on port 6454 (default artnet port)
        //Serial.println( "register listener reached");       //print to serial for testing
}
 
void loop()
{
  // this must be called for ethercard functions to work.
  ether.packetLoop(ether.packetReceive());
  
}

Excellent work Chris

I hope others can try this out too :slight_smile:

Do you realise how near you are to ALSO being able to make this sACN E1.31 compatible

I hadn't actually thought of that! That might be a good thing to add in for some extra marks in my uni project!

I shall post you what I have got that determines the difference, maybe tonight or tomorrow as I cant access my files from here. B

Chris,

try the following to stop the LEDs from flickering

change

sendDMX(data);

to

cli();
sendDMX(data);
sei();

it might work for you, it worked for me on my software

Will do! Cheers!

hi Cricky

is it possible change your code to user can connect to hardware by browser and change hardware configuration ? for example change ip address .

Hi Dehghan13

I make something very similar that I sell on eBay, my browser configuration page looks like this

hi Cricky

I Live in iran and i can not sell from eBay ! is it another way ?

Hi Chris and mcnobby - I have this loaded up on the arduino nano with the same ethernet shield. How do I then send the data to one of these:
http://www.ebay.com.au/itm/252635274415

and then out to one of these:
https://www.aliexpress.com/store/product/DIN-DMX-5A-3CH-CV-DMX-Decoder-DC5-24V-input-5A-3CH-output/312912_32253355228.html

I think the RS485 to the DMX dimmer pack will be simple enough, but if you know what A and B on the terminal blocks on the rs485 converter are in terms of D+ or D- that would help.

I'm just doing three channels for now.

Is there a line or two of code I can insert to hookup some testing LEDs for those three channels? It would be great to see the signal received before I connect it to the DMX dimmer pack.

Thanks!

btw mcnobby - your unit on ebay looks great!

Hi SJP
I would start by testing the ethernet connection first (webpage or similar) there are lots of examples to try this, then once you are happy move to JUST TESTING the DMX

I have found this website very useful A Arduino Library for sending and receiving DMX

Once you have the two running separately and you are happy, find a way of combining them together

mcnobby:
Hi SJP
I would start by testing the ethernet connection first (webpage or similar) there are lots of examples to try this, then once you are happy move to JUST TESTING the DMX

I have found this website very useful A Arduino Library for sending and receiving DMX

Once you have the two running separately and you are happy, find a way of combining them together

Hi Mcnobby.

I'm trying to create small ArtNet adapter on Nano, and reached this topic. And tested dmx_lib, dmxsimple and dmxserial.
MAX485/SN75176 scheme as simple one (Arduino Playground - HomePage).

DMXserial:

I changed Cricky's code, to work with DMXSerial, and after series of test and debugging, I figured out, that EtherCard lib and DMXSerial has some Serial conflicts.
And even when I remove all debugging strings from EtherCard lib, it still generate noise to D1, when receive packets. So DMX devices receive payload plus noise on near channels.

As for DMXsimple:
DMXsimple sends nothing through D3 -> MAX485 -> 30CH DMX LED. DMX data receiving lamp doesn't blink on equipment.
Checked on Arduino Nano(ATMEGA328P wCH340) / UNO(ATMEGA328P) / MEGA (ATMEGA2560).

Checked with different Arduino IDE (1.0.6 / 1.6.8 / 1.8.1)
Checked with different transmitting pins (D1 / D3 / D5)
Checked with forced DMX_SIZE 512
Checked with FadeUp.

Hi Konstantin
Yes unfortunately there are some nasty conflicts which I found too, so in the end I hand coded some functions that drove the serial port directly which overruled the ethernet library functions

I found a much better way to serve the interrupt too, I used a standard timer to fire the bytes out and a state engine to deal with the rest of the DMX blurb

My combination of the UIPEthernet library and my code works a treat :slight_smile: perhaps it is time for me to publish something simple...

Yeah :slight_smile:
It's time to share your code :wink:

Couse as for me, dig into interruptions is suicide.

Sorry to revive this topic,
I was urgently needing Artnet to DMX node because of my next project... Waiting for it to come would take long so why not to make my own:)

This topic worked for me OK. Good work to everybody :). I found it very useful, but found problem in code that prohibited of using dmx above ~ channel 460, so time to share...
Problem is size of this buffor

byte Ethernet::buffer[529];

change it to

byte Ethernet::buffer[600];

this will fix problem with wrong data in last bytes.

only thing i have now is i think simple dmx library problem that causes my spots to blink sometime if used on high channels .
already changed :

sendDMX(data);

to

cli();
sendDMX(data);
sei();

I added also small delay in main loop

void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 20) {
// save the last time you blinked the LED
previousMillis = currentMillis;
ether.packetLoop(ether.packetReceive());
}

}

that helped also, but still it don't work for me as it should. I think it is interrupt related in DMXsimple library

I did't make a web config i added just 4 jumpers and some code in setup to be able to change channel so i can have up to 16 of them on network depending from jumper setting.

hello Cricky , I test your code, I see artnet receved on led of the ethernet box, but the modulation on pin 3, is not a dmx data. It's other but what's ???

Hi all!

I'm using also a Arduino Nano and ENC28J60 module.

I tried your code and I experienced some issues. I can't received any packets in the
ether.packetLoop(ether.packetReceive()); function. If I used basic UDP frames, I'm able to received frames.

Does Art-Net is seen as UDP packet by EtherCard ?
Also which version of Art-Net are you using (3 or 4) ?

TIA.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.