artnet to dmx project. memory issues?

the project:
my goal is to use a arduino UNO to make a artnet node. this will convert artnet to dmx.

hardware: Arduino UNO with a ethernet shield and a proto shield with sn75176 ic connected to digital pin 3 for dmx out.

IDE: arduino 1.0

libraries used: DmxSimple, SPI, Ethernet, EthernetUdp.
Link to DmxSimple Library: Google Code Archive - Long-term storage for Google Code Project Hosting.

The Dmx Simple Library is modified to work with arduino 1.0

The code is 99% made by Christoph Guillermet
original code can be downloaded from here:
http://vvvv.org/contribution/artnet-arduino-set-v2

I have added the dmx out feature to the code and adapted it for Arduino 1.0.

to my problem! This code sort of works. It is working for about 10 seconds of changeing values and then i freezes.
Im guessing this has to do with some sort of memmorie issue. im also guessing it has to do with the DmxSimple library bacuse the original sketch does not have this issues.

Things i have tried: Instead of receiving all of the 512 dmx channels i have tried to limit this to just one. but same thing happens but after ca 25 seconds instead of 10.

so does some one have clue how i can solve this ?

The Code

/*
ARTNET RECEIVER V2

This SCRIPT allows you to use arduino with ethernet shield or wifi shield and recieve artnet data. Up to you to use channels as you want.


If you have implemented ameliorations to this sketch, please, contribute by sending back modifications, ameliorations, derivative sketch. It will be a pleasure
to let them accessible to community



For VVVV patchers, please think to put a mainloop node in your patch: minimum frame rate is 40fps with bulbs. But do not go too much higher ( max 100 fps).

This sketch is part of white cat lighting board suite: /http://www.le-chat-noir-numerique.fr  
wich is sending data to many different types of devices, and includes a direct communication in serial also with arduino likes devices
you may find whitecat interresting because its theatre based logic ( cuelist and automations) AND live oriented ( masters, midi, etc)

(c)Christoph Guillermet
http://www.le-chat-noir-numerique.fr
karistouf@yahoo.fr
*/

#include <DmxSimple.h>
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>          // UDP library from: bjoern@cs.stanford.edu 12/30/2008
#define short_get_high_byte(x) ((HIGH_BYTE & x) >> 8)
#define short_get_low_byte(x)  (LOW_BYTE & x)
#define bytes_to_short(h,l) ( ((h << 8) & 0xff00) | (l & 0x00FF) );


//MAC and IP of the ethernet shield
//MAC adress of the ethershield is stamped down the shield
//to translate it from hexa decimal to decimal, use: http://www.frankdevelopper.com/outils/convertisseur.php
//HARDWARE
byte mac[] = {  144, 162, 218, 00, 16, 96  };//the mac adress of ethernet shield or uno shield board
IPAddress  ip(192,168,0,60 );// the IP adress of your device, that should be in same universe of the network you are using, here: 192.168.1.x

// the next two variables are set when a packet is received
byte remoteIp[4];        // holds received packet's originating IP
unsigned int remotePort; // holds received packet's originating port

//customisation: edit this if you want for example read and copy only 4 or 6 channels from channel 12 or 48 or whatever.
const int number_of_channels=512; //512 for 512 channels
const int channel_position=1; // 1 if you want to read from channel 1

// buffers

char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to store incoming data
byte buffer_dmx[number_of_channels+channel_position]; //buffer to store filetered DMX data

// art net parameters
unsigned int localPort = 6454;      // artnet UDP port is by default 6454
const int art_net_header_size=17;
const int max_packet_size=576;
char ArtNetHead[8]="Art-Net";
char OpHbyteReceive=0;
char OpLbyteReceive=0;
short is_artnet_version_1=0;
short is_artnet_version_2=0;
short seq_artnet=0;
short artnet_physical=0;
short incoming_universe=0;
boolean is_opcode_is_dmx=0;
boolean is_opcode_is_artpoll=0;
boolean match_artnet=1;
short Opcode=0;
EthernetUDP Udp;

void setup() {
  //déclaration des ports PWM 
  //ici une diode pour test
  pinMode(3, OUTPUT);  //check with leds + resistance in pwm, this will not work with pins 10 and 11, used by RJ45 shield
 
  // démarrage ethernet et serveur UDP
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

}

void loop() {
  
   int packetSize = Udp.parsePacket();
  if( packetSize>art_net_header_size && packetSize<=max_packet_size)//check size to avoid unneeded checks
  {
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);  
    //read header
     match_artnet=1;//valeur de stockage
     for (int i=0;i<7;i++)
     {
      if(char(packetBuffer[i])!=ArtNetHead[i])
      {match_artnet=0;break;}//if not corresponding, this is not an artnet packet, so we stop reading
     } 
     if (match_artnet==1)//if its an artnet header
     { 
          /*artnet protocole revision, not really needed
          is_artnet_version_1=packetBuffer[10]; 
          is_artnet_version_2=packetBuffer[11];*/
      
          /*sequence of data, to avoid lost packets on routeurs
          seq_artnet=packetBuffer[12];*/
          
          /*physical port of  dmx N°
          //artnet_physical=packetBuffer[13];*/
      
     //operator code enables to know wich type of message Art-Net it is
     Opcode=bytes_to_short(packetBuffer[9],packetBuffer[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 adress of the device)
     } 
 
     if(  is_opcode_is_dmx=1)//if its DMX data we will read it now
     {
     //if you need to filter DMX universes, uncomment next line to have the universe rceived
     //incoming_universe= bytes_to_short(packetBuffer[15],packetBuffer[14])
     
     //getting data from a channel position, on a precise amount of channels, this to avoid to much operation if you need only 4 channels for example
     for(int i=channel_position-1;i< number_of_channels;i++)//channel position
      {
     buffer_dmx[i]= byte(packetBuffer[i+17]);
     DmxSimple.write(i,buffer_dmx[i]);
       }
      }
 
     }//end of sniffing 
    
  }

}
byte buffer_dmx[number_of_channels+channel_position]; //buffer to store filetered DMX data

There's a 1/4 of your memory, if you have other than a Mega.

Things i have tried: Instead of receiving all of the 512 dmx channels i have tried to limit this to just one. but same thing happens but after ca 25 seconds instead of 10.

Doesn't really look like that...

Quote
Things i have tried: Instead of receiving all of the 512 dmx channels i have tried to limit this to just one. but same thing happens but after ca 25 seconds instead of 10.
Doesn't really look like that...

To change the amount of channels, i have used this part of the code:

//customisation: edit this if you want for example read and copy only 4 or 6 channels from channel 12 or 48 or whatever.
const int number_of_channels=512; //512 for 512 channels

and i dont think it is the part you suggest, that i have problems in beacuse that is from the original artnet reciving code and that one works.

I get this problem too and it seems like maybe the w5100 buffer is getting too full and not clearing properly (uneducated guess)

I get the same problem when using the UDPsendReceiveString sketch that comes with the ethernet library. If I send udp packets one at a time the arduino reports back correctly but if I send a constant stream of artnet data (I think 538 bytes per packet and usually at a rate of 40-60 pps) the arduino freezes (or probably just the w5100 freezes)

As artnet is a realtime communication all I need is to read one packet from the buffer every time the arduino's loop passes round, therefore I have no use for buffered packets apart from the one I want to read that cycle.

I tried flushing with Udp.flush but that didn't seem to work.

It's spinning out with even smaller packets too.

I've tried 2 units. And I don't know if it's just me but it seems to get worse over time.

I had the same problem, reported here

what is the size of your UDP_TX_PACKET_MAX_SIZE
Its defined in the Udp.h or EthernetUdp.h , depending on which arduino version you are using.
I am asking, because sometime people tinker with this value.

Try to change your code from
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
into
char packetBuffer[512];
// packetBuffer[512] is working for me on Uno, but you should aim using the value originally which was 2048

I guys, I did not understand if you resolved the problems, did you ??

And where I can find assembly instructions ??

Thank You !!

The fix for me was to use an arduino mega

indeed mrboni. I also previously switched to Mega+Ethernet shield and my program started to work properly.
but, than, I changed the UDP_PACKET_MAX_SIZE from 2048 to 576, which is artnet max packet size , and the program is now running properly using Uno+Ethernet
(sorry for not posting the code. the development is still in progress.)

Hi mrboni, i'm sorry but I'm not so expert about ARDUINO, can you explain me more what you've done... I'm trying to build something like this:

proximity sensor-->-->control lighting software-->-->lighting fixtures

I have a software, I have a dmx OUT hardware, but I need to understand how to make comunicate the sensor with a software.

I know that I have to convert the sensor signal into dmx; I think that the right way is to use an artnet to dmx device, is that you use right for this ?

if yes, can you tell me exactly what kind of hardware I need and how to assemble it ... than I will think about the ARDUINO code...

THANK YOU VERY MUCH !!!!!

I know this is a very old topic. Did this project ever get finished? I am new to Arduino, and am interested to learn about Artnet and DMX implementations before I move into something more complex.

Apologies for trying to drag up such an old topic but I'm hoping to get a bit of help with a project i'm attempting.

I want to make an ArtNet node based on an Arduino Nano and an ENC28J60 Ethernet module (both of these chosen for a nice compact unit) and this seems to be the most promising code example i've came across online.

Would it be possible to modify this project to work with my hardware? ...and would i also need to use an older version of the Arduino IDE?

I'm guessing i'd need to use different a different library for the ENC28J60 (such as the Ethercard library?).

Could anybody direct me in the steps i'd need to take to do this? I'm not asking for someone completely to do it for me, i would like to pick up a bit of knowledge on the subject while i'm at it.

Thanks!

Cricky:
I want to make an ArtNet node based on an Arduino Nano and an ENC28J60 Ethernet module (both of these chosen for a nice compact unit) and this seems to be the most promising code example i've came across online.

My words exactly Cricky....

Have you got anywhere with this yet mcnobby?

I think i might have found some things that might come in handy for porting this over to the ethercard library...

Migrating from EtherShield to EtherCard library:
http://blog.thiseldo.co.uk/?p=623

Art-Net user guide:

Here is a project using OSC to control DMX via Art-Net that could be handy:
http://oschub.asia/weblog/?p=165

I'm a complete n00b with this stuff so i'm learning as i go (i hope). This started off as a simple DMX over USB project but has now grown into an attempt at an Art-Net node which is more than i bargained for!

Hi Cricky, yes I have moved along quite nicely
I am currently using a UNO and Ethernet Shield using some standard libs
But I have written an HTML interface to configure your ArtNet in a browser (see pic)

I have also written some assembler to take the ArtNet (DMX) data direct to WS2812 LEDs (not using Neopixel or FastLed Libraries)

There are some severe memory limitations, but I think I can get 2 universes decoded and output without any trouble

Migrating to the ENC29J60 may cause some more problems too, but we shall see when I get there

I am hoping to make some very small ArtNet/sACN to WS2812 adaptors using a NANO and the Tiny ENC28J60 Nano Ethernet shield

FB_IMG_1458817407373[1].jpg

That's cool! Liking the web interface.

I had another go at this one last night. I took the project from the original post and tried replacing the ethernet.h library with the UIPEthernet library since you don't need to change anything in the code to use it. I had a few compile errors then fixed them but not its not compiling due to lack of memory. I'm getting this:

Sketch uses 17,014 bytes (55%) of program storage space. Maximum is 30,720 bytes.
Global variables use 2,712 bytes (132%) of dynamic memory, leaving -664 bytes for local variables. Maximum is 2,048 bytes.

I've changed the line

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

to

char packetBuffer[576];

I've also went into the UIPUdp.h library file and changed it in there too. It's named differently though...See below:

#define UIP_UDP_MAXDATALEN 1500
#define UIP_UDP_PHYH_LEN UIP_LLH_LEN+UIP_IPUDPH_LEN
#define UIP_UDP_MAXPACKETSIZE 576 //edited for ARTNET program
//#define UIP_UDP_MAXPACKETSIZE UIP_UDP_MAXDATALEN+UIP_UDP_PHYH_LEN

And when i checked the normal, unedited stock ethernet.h file, UDP_TX_PACKET_MAX_SIZE was 24. Something seems weird....

Any ideas what might be going on here?

I'll post my code below. Its near enough the same as above but i'll post it either way:

/*
ARTNET RECEIVER V2

This SCRIPT allows you to use arduino with ethernet shield or wifi shield and recieve artnet data. Up to you to use channels as you want.


If you have implemented ameliorations to this sketch, please, contribute by sending back modifications, ameliorations, derivative sketch. It will be a pleasure
to let them accessible to community



For VVVV patchers, please think to put a mainloop node in your patch: minimum frame rate is 40fps with bulbs. But do not go too much higher ( max 100 fps).

This sketch is part of white cat lighting board suite: /http://www.le-chat-noir-numerique.fr  
wich is sending data to many different types of devices, and includes a direct communication in serial also with arduino likes devices
you may find whitecat interresting because its theatre based logic ( cuelist and automations) AND live oriented ( masters, midi, etc)

(c)Christoph Guillermet
http://www.le-chat-noir-numerique.fr
karistouf@yahoo.fr
*/

#include <DmxSimple.h>
#include <SPI.h>             // needed for Arduino versions later than 0018
#include <UIPEthernet.h>
#include <UIPUdp.h>

#define short_get_high_byte(x) ((HIGH_BYTE & x) >> 8)
#define short_get_low_byte(x)  (LOW_BYTE & x)
#define bytes_to_short(h,l) ( ((h << 8) & 0xff00) | (l & 0x00FF) );


//MAC and IP of the ethernet shield
//MAC adress of the ethershield is stamped down the shield
//to translate it from hexa decimal to decimal, use: http://www.frankdevelopper.com/outils/convertisseur.php
//HARDWARE
byte mac[] = {  144, 162, 218, 00, 16, 96  };//the mac adress of ethernet shield or uno shield board
IPAddress  ip(192,168,0,20 );// the IP adress of your device, that should be in same universe of the network you are using, here: 192.168.1.x

// the next two variables are set when a packet is received
byte remoteIp[4];        // holds received packet's originating IP
unsigned int remotePort; // holds received packet's originating port

//customisation: edit this if you want for example read and copy only 4 or 6 channels from channel 12 or 48 or whatever.
const int number_of_channels=512; //512 for 512 channels
const int channel_position=1; // 1 if you want to read from channel 1

// buffers

char packetBuffer[UIP_UDP_MAXPACKETSIZE]; //buffer to store incoming data
byte buffer_dmx[number_of_channels+channel_position]; //buffer to store filetered DMX data

// art net parameters
unsigned int localPort = 6454;      // artnet UDP port is by default 6454
const int art_net_header_size=17;
const int max_packet_size=576;
char ArtNetHead[8]="Art-Net";
char OpHbyteReceive=0;
char OpLbyteReceive=0;
short is_artnet_version_1=0;
short is_artnet_version_2=0;
short seq_artnet=0;
short artnet_physical=0;
short incoming_universe=0;
boolean is_opcode_is_dmx=0;
boolean is_opcode_is_artpoll=0;
boolean match_artnet=1;
short Opcode=0;
EthernetUDP Udp;

void setup() {
  // pin 3 commonly used for DMX 
  DmxSimple.usePin(3);

  // start ethernet and udp server
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

}

void loop() {
  
   int packetSize = Udp.parsePacket();
  if( packetSize>art_net_header_size && packetSize<=max_packet_size)//check size to avoid unneeded checks
  {
    Udp.read(packetBuffer,UIP_UDP_MAXPACKETSIZE);  
    //read header
     match_artnet=1;//valeur de stockage
     for (int i=0;i<7;i++)
     {
      if(char(packetBuffer[i])!=ArtNetHead[i])
      {match_artnet=0;break;}//if not corresponding, this is not an artnet packet, so we stop reading
     } 
     if (match_artnet==1)//if its an artnet header
     { 
          /*artnet protocole revision, not really needed
          is_artnet_version_1=packetBuffer[10]; 
          is_artnet_version_2=packetBuffer[11];*/
      
          /*sequence of data, to avoid lost packets on routeurs
          seq_artnet=packetBuffer[12];*/
          
          /*physical port of  dmx N°
          //artnet_physical=packetBuffer[13];*/
      
     //operator code enables to know wich type of message Art-Net it is
     Opcode=bytes_to_short(packetBuffer[9],packetBuffer[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 adress of the device)
     } 

     if(  is_opcode_is_dmx=1)//if its DMX data we will read it now
     {
     //if you need to filter DMX universes, uncomment next line to have the universe rceived
     //incoming_universe= bytes_to_short(packetBuffer[15],packetBuffer[14])
     
     //getting data from a channel position, on a precise amount of channels, this to avoid to much operation if you need only 4 channels for example
     for(int i=channel_position-1;i< number_of_channels;i++)//channel position
      {
     buffer_dmx[i]= byte(packetBuffer[i+17]);
     DmxSimple.write(i,buffer_dmx[i]);
       }
      }

     }//end of sniffing 
    
  }

}

*Edit - I've changed the number of channels from 512 to 48 (just a random low value) and it compiles now! Obviously i'd like a full universe though but this seems like progress!

Ignore the above, i realised i'd also changed the udp max tx buffer size to 24 too when it compiled....

I might try porting over to ethercard.h but i think there's a lot needs changed to do that.

Also, i've made this nice wee tidy unit (see attached) so it'd be nice to get this thing working! Just need to cut it out and house it in something if i ever manage to program it!

Cricky,
I think either way, because of the nature of the ENC28J60, you will be lacking in Ram

I had to use sourcery to get 2 full ArtNet (or sACN) universes out to WS2812 LEDs

The way I did it is this

packetBuffer, stores the currently received packet from ethernet
Once I received it, and checked the right headers, universe, sub etc etc
I then jumped to the code to output to WS2812 LEDs
The code I used scanned the packetBuffer starting at [125] and output the bytes from there

This way I didnt need to use any other array for storing my values (the WS devices did that !)
I then went on to decode another universe, and output in the same way
(still not using any extra ram)
I wanted to carry on until I had decoded and output 2048 bytes, but I had problems with the ethernet chip buffer ram being full or something (my universe 3 was jittery !)

Unfortunately for you the DMXserial needs the second array to be in place so it can access it in the interrupt and output the byte(s)

I am still fiddling.....

I might just throw the head up and buy the bigger arduino for this. Getting this artnet node running is actually only a minor part of my uni project and I've been at it way too long already.

Like you say, I'm probably gonna encounter RAM issues with my setup regardless.

Could maybe try a teensy. Have you any experience with them?

I havent used a teensy, as yet !

On my Nano+ENC28J60, I have about 500bytes left, running either a 2 universe sACN or ArtNet, and also the ability to boot it into a config mode that serves a webpage to a browser for set up of IP etc

So, it is possible, and stable

Once I get this up and running nicely I shall post some code, I might even try and do something like you are doing to see if it is possible, I reckon you could get 2 universes out to DMX (but that would need 2 uarts), so one is definately possible

Awesome! Yeah, I seen you post that on the DIY DMX Facebook page. Good job!

Would be cool to see your code when you've it sorted. I'm gonna go see my project supervisor tomorrow in uni, hopefully he'll be able to spot something in this that'll help me.