Send Data

Hi, im working in a ArtNet node (Arduino+Enc28j60). So far so good. The only thing left is some extra data i want to send. This is what i got:

/****************************************************************
 * Art-Net to DMX Controller Interface                          *
 *                                                              *

 ****************************************************************/

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


#define bytes_to_short(h,l) ( ((h << 8) & 0xff00) | (l & 0x00FF) );

/* 
Set Ethernet interface ip address here. 
For direct link from PC Ethernet port 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
*/

byte myip[] = { 192,168,2,2 };   //set an IP address for the ENC device

//gateway ip address not needed
  //static byte gwip[] = { };
 
//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[] = { 0xD0,0x69,0x69,0x2D,0x30,0x31 };
 
byte Ethernet::buffer[580]; // tcp/ip send and receive buffer should be 512 dmx channels + Art-Net header + UDP header + Ethernet Header

const int number_of_channels=513; // 512 for one full DMX universe set to a low value to make the device work better
const int channel_position=1;
const int art_net_header_size=17;
const int max_packet_size=172;    //
char ArtNetHead[8]="Art-Net";    //first byte of an ARTDMX packet contains "Art-Net"
//char ShortName[18] = "ElLab Artnetnode\0"; // short name defaults to IP
//char LongName[64] = "Electric Laboratory Artnetnode\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
short Opcode=0;
//boolean is_opcode_is_dmx=0;
//boolean is_opcode_is_artpoll=0;

//buffers
//byte buffer_dmx[number_of_channels+channel_position]; //buffer to store filetered DMX data    ***bypassed this bit to save SRAM***


//function declarations
static void artnetPacket();
int checkARTDMX();
void sendDMX();
 

void setup()
{
// Serial.begin(9600);        //for testing
  DmxSimple.usePin(3);          // DMX output is pin 3
  DmxSimple.maxChannel(number_of_channels);    //should be 512
// Serial.println(F("\n[testDHCP]"));

//Serial.print("MAC: ");
//for (byte i = 0; i < 6; ++i) {
//Serial.print(mymac[i], HEX);
 //if (i < 5)
  // Serial.print(':');
//}
 // Serial.println();
  
//if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) 
 // Serial.println(F("Failed to access Ethernet controller"));

// Serial.println(F("Setting up DHCP"));
//if (!ether.dhcpSetup())
 //Serial.println(F("DHCP failed"));
  
// ether.printIp("My IP: ", ether.myip);
 //ether.printIp("Netmask: ", ether.netmask);
//ether.printIp("GW IP: ", ether.gwip);
//ether.printIp("DNS IP: ", ether.dnsip);

//  Serial.println("\n[getStaticIP]");
//  ether.copyIp(ether.myip, myip);
//ether.printIp("My IP: ", ether.myip);


 
  ether.begin(sizeof(Ethernet::buffer), mymac, 10);   //10 at end initialises CS pin as pin 10 on arduino instead of default pin 8

pinMode(4,INPUT_PULLUP);
if(digitalRead(4) == LOW){   //if button is pressed
  ether.staticSetup(myip);
}else{
  ether.dhcpSetup();
}


      // Static IP 
 // ether.staticSetup(myip);

 //ether.dhcpSetup();
    
  // 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());
  
}

// 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){     //if valid ArtDMX packet, send to DMX universe

sendDMX(data);

  }
  //else if (!check){ //ArtPoll packet received, send reply
    //artpollReply();  
  //}
}

/*
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) {   
  //Serial.println( "checkARTDMX reached");       //print to serial for testing
  
  if(messagelength > art_net_header_size && messagelength <= max_packet_size) //check packet size first
  {
  //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)   //test flag
     {
    //check if ArtPoll or ArtDMX
    Opcode=bytes_to_short(messagein[9],messagein[8]);
     
     if(Opcode==0x5000)//5000 = ArtDmx
      {
       return 1;
      }   
       
     else if(Opcode==0x2000)//2000 = ArtPoll 
     {
     //An ArtPollReply should be sent in response supplying the controller with device info
     return 0;
     } 
   }
  }
  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 = 0; 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]);
  }
}

What i want is to send ShortName and LongName, you can see here under ArtPollReply
Artnet data

And this is from another project and there is both short and long name:

/

  for ( i=0; i<ARTNET_REPLY_SIZE; i++ ) {
    replyBuffer[i] = 0;
  }
  replyBuffer[0] = 'A';
  replyBuffer[1] = 'r';
  replyBuffer[2] = 't';
  replyBuffer[3] = '-';
  replyBuffer[4] = 'N';
  replyBuffer[5] = 'e';
  replyBuffer[6] = 't';
  replyBuffer[7] = 0;
  replyBuffer[8] = 0;        //op code lo-hi
  replyBuffer[9] = 0x21;      
  replyBuffer[10] = ip[0];      //ip address
  replyBuffer[11] = ip[1];
  replyBuffer[12] = ip[2];
  replyBuffer[13] = ip[3];
  replyBuffer[14] = 0x36;    // port lo first always 0x1936
  replyBuffer[15] = 0x19;
  replyBuffer[16] = 0;      //firmware hi-lo
  replyBuffer[17] = 0;
  replyBuffer[18] = highByte(subnet+1);  //subnet hi-lo
  replyBuffer[19] = lowByte(subnet+1);
  replyBuffer[20] = 0;      //oem hi-lo
  replyBuffer[21] = 0;
  replyBuffer[22] = 0;      // ubea
  replyBuffer[23] = 160;    // status 1
  replyBuffer[24] = 't';    //     ESTA Code (2 bytes)
  replyBuffer[25] = 'm';

                            //short name
  for (int x = 26; x < 43; x++) {
    replyBuffer[x] = nodeName[x-26];
    if (nodeName[x-26] == 0)
      break;
  }
  
                            //long name
  for (int x = 44; x < 70; x++) {
    replyBuffer[x] = nodeName[x-44];
    if (nodeName[x-44] == 0)
      break;
  }

Like i said i just want to put that ArtPollReply in my project (actually is not mine), but i really suck at coding, i dont know where to start.

I have done some very successful projects using enc28j60, but I use the uipethernet library. I have found that few libraries will support a artpoll request when it comes from a local broadcast like 192.168.1.255, they will happily respond to 255.255.255.255. The make up of the artpollreply should be very carefully put together otherwise the receiving application will reject it. I have also found that artnet long and short name can cause issues if the wrong length. If you dont already have it, download artnetominator which will poll for your reply (using a broadcast), use a spare pin to light a LED to see that you have got it, then send either a broadcast reply packet, or a local IP reply and see if it gets through. Also watch the size of your buffers as you will eat up memory quickly. I use the same buffer to send and reply, as the two never happen at the same time and will also get overwritten

I place a switch to choose between static ip for ad hoc use PC---Node. And DHCP Node--Router. The thing is with the static ip theres no need of the node name, but when you use DHCP, you need to see the ip assigned by the Router. Unless you access to the router admin ap. You have to guess the ip, but if you have the artnet node information, you can see it in the lightning soft. The node actually works like a charm i dont see any delay or fault. So its the only thing left, i will dig into it, thanks for the answer.