Go Down

Topic: Art-Net transmission via UDP ver 1.0 vs ver 22 (Read 1 time) previous topic - next topic

trussmky

I have a sketch for transmitting the Artnet UDP protocol that works properly when compiled and uploaded with Arduino V22.  When I compile and upload with Arduino 1.0 (after changing what I think are the appropriate calls), it does not transmit properly. 
When I run wire shark on the transmission, it is being transmitted as an ARP packet, instead of a UDP packet.
I am running a Duemilanove, with a w.5100 Ethernet Shield.

Attached you will find both the V22 and v1.0 sketches.

Here is the v1.0 sketch

Code: [Select]
/*
artnet_Send for V1.0

potentiometers attached to analog in 0 and 1
sends artnet packets every 3.5 seconds, or when Potentiometers change.

*/
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

byte mac[] = {  0x90, 0xA2, 0xDA, 0x00, 0x87, 0xD5  };
byte ip[] = { 192, 168, 15,12};  //  local network IP
//byte ip[] = { 2, 0, 0, 177 }; // proper Artnet protocol IP
byte gw[] = {ip[0], ip[1], ip[2],  1 };
byte sn[] = { 255,   0,   0,   0 };

byte sendIp[] = {ip[0], 255, 255, 255};
unsigned int localPort = 6454;      // art-net communicates via UDP Port=6454

//  ****  Constants  ****
const int Number_of_Channels=512;
const int MAX_BUFFER_UDP = 531;//18+512+1; //18bit UDP Header+512bit DMX Packet+1 stopbit
EthernetUDP Udp;

//  ****  buffers  ****
//char
uint8_t packetBuffer[MAX_BUFFER_UDP]; //UDP packet, 0-17 header, 18 - 530 dmx buffer
unsigned char buffer_dmx[Number_of_Channels];

//  ****  Art-Net identification Variables  ****

unsigned char ArtNetHead[8]="Art-Net";    //field 1, (0-7)
short Opcode=0x5000;
byte artnet_version_1= 0;        //field 3 (10)
byte artnet_version_2=14;        //field 4 (11)
byte seq_artnet=0;              //filed 5 (12)
byte artnet_physical=0;         //field 6 (13)
//int incoming_universe = 0;      //field 7 (15, 14)
int dmx_chan_tx = 512;         //field 8 & 9 (16-17)

int packetSize = 0;

int sendUniverse = 2;//universe of artnet to be sent
int sendDmxCh = 508; // Base channel of DMX to be sent on selected Universe
int sendDmxNum = 2;  //  Number of DMX Channels actually sent
long lastTxTime = 0;  //time of last transmission
int maxTxTime = 3500;  //3.5 seconds maximum between transmissions
boolean diffDmxVal = 0;  // has the DMX changed?
// slider pot input it generate DMX Value

const int levelPin[] = {0,1};

void setup()
{
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);  //Disables SD card
  Serial.begin(9600);
  Ethernet.begin( mac, ip, gw, sn);
  Udp.begin(localPort);
  for (int i = 0; i<dmx_chan_tx; i++)  //  Set initial DMX Values to 0
  {
    buffer_dmx[i] = 0;
  } //end set DMX values to 0
  for (int i = 18; i<MAX_BUFFER_UDP; i++)  //set packet buffer to all '0', except header
  {
    packetBuffer[i] = 0;
  }

//  Set PAcket Header into Buffer

  for (int i = 0; i<8; i++)
  {
    packetBuffer[i] = ArtNetHead[i];
  }
  packetBuffer[8] = 0x00;//Opcode;  // low byte
  packetBuffer[9] = 0x50;//(Opcode >> 8);  // high byte
  packetBuffer[10] = artnet_version_1;  //Protocol Version HIGH
  packetBuffer[11] = artnet_version_2;  // Prococol Version LOW
  //packetBUffer[12] = seq_artnet:  // sequence number(increment with each transmission)
  packetBuffer[13] = artnet_physical;  // physical input receiving DMX signal
  packetBuffer[14] = sendUniverse;  // universe being transmitted (LOW Byte)
  packetBuffer[15] = (sendUniverse >> 8);  // universe being transmitted (HIGH Byte)
  packetBuffer[16] = (dmx_chan_tx >> 8);  // # of transmitting DMX Chan (HIGH byte)
  packetBuffer[17] = dmx_chan_tx;  // # of transmitting DMX Chan (LOW byte)

}// end setup

void loop()
{
  //read potentiometer, convert reading to scale (0-FF)
  for (int i =0; i< sendDmxNum; i++)
  {
    buffer_dmx[sendDmxCh+i] = getLevel(i); //insert reading from potentiometer into DMX Buffer
    if (buffer_dmx[sendDmxCh+i] == packetBuffer[sendDmxCh+17+i] && diffDmxVal == false)
    {
      diffDmxVal = false;//if no change of DMX value, do not send packet
    } else
    {
      diffDmxVal = true;  //if change of DMX value, write into UDP buffer, and send packet
    }
    // copy values from buffer_dmx into packetBuffer
    packetBuffer[sendDmxCh+17+i] = buffer_dmx[sendDmxCh +i];
  }

//  *****  max time between transmissions

  if (millis() - lastTxTime > maxTxTime)
  {
    diffDmxVal = true;
  }

  packetBuffer[12] = seq_artnet;  //load seq# into UDP buffer 
  //Send Artnet packet if value change, or timeout
  switch (diffDmxVal)
  {
    case false:  //if no new DMX value, do not transmit
      break;
    case true:
  {
    Udp.beginPacket(sendIp, localPort);
    Udp.write(packetBuffer,MAX_BUFFER_UDP); //
    int goodUdp =  Udp.endPacket(); //send the built packet

//  int goodUdp = Udp.sendPacket(packetBuffer,MAX_BUFFER_UDP,sendIp, localPort);  //depreciated for Uno
    if (goodUdp == 1) 
    {
      lastTxTime = millis();  //packet sent, reset timer,
      seq_artnet ++; //increment Sequence Number in artnet header
    }
    diffDmxVal =false; //reset state change detection
  }
  break;
  }
  delay(10);

}//end loop
 
 
unsigned char getLevel(int i)
{
  int levelPot = analogRead(levelPin[i]);
  levelPot = map(levelPot,0,1023,0,255);
  return(levelPot);
}


V22 will follow in next post

trussmky

Here is the v22 sketch

Code: [Select]

/*
artnet_Send for V22

potentiometers attached to analog in 0 and 1
sends artnet packets every 3.5 seconds, or when Potentiometers change.

*/
#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>
#include <Stdint.h>

byte mac[] = {  0x90, 0xA2, 0xDA, 0x00, 0x87, 0xD5  };
byte ip[] = { 192, 168, 15,12};  //  local network IP
//byte ip[] = { 2, 0, 0, 177 }; // proper Artnet protocol IP
byte gw[] = {ip[0], ip[1], ip[2],  1 };
byte sn[] = { 255,   0,   0,   0 };

byte sendIp[] = {ip[0], 255, 255, 255};
unsigned int localPort = 6454;      // art-net communicates via UDP Port=6454

//  ****  Constants  ****
const int Number_of_Channels=512;
const int MAX_BUFFER_UDP = 531;//18+512+1; //18bit UDP Header+512bit DMX Packet+1 stopbit

//  ****  buffers  ****
//char
uint8_t packetBuffer[MAX_BUFFER_UDP]; //UDP packet, 0-17 header, 18 - 530 dmx buffer
unsigned char buffer_dmx[Number_of_Channels];

//  ****  Art-Net identification Variables  ****

unsigned char ArtNetHead[8]="Art-Net";    //field 1, (0-7)
short Opcode=0x5000;
byte artnet_version_1= 0;        //field 3 (10)
byte artnet_version_2=14;        //field 4 (11)
byte seq_artnet=0;              //filed 5 (12)
byte artnet_physical=0;         //field 6 (13)
//int incoming_universe = 0;      //field 7 (15, 14)
int dmx_chan_tx = 512;         //field 8 & 9 (16-17)

int packetSize = 0;

int sendUniverse = 2;//universe of artnet to be sent
int sendDmxCh = 508; // Base channel of DMX to be sent on selected Universe
int sendDmxNum = 2;  //  Number of DMX Channels actually sent
long lastTxTime = 0;  //time of last transmission
int maxTxTime = 3500;  //3.5 seconds maximum between transmissions
boolean diffDmxVal = 0;  // has the DMX changed?
// slider pot input it generate DMX Value

const int levelPin[] = {0,1};

void setup()
{
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);  //Disables SD card
//  Serial.begin(9600);
  Ethernet.begin( mac, ip, gw, sn);
  Udp.begin(localPort);
  for (int i = 0; i<dmx_chan_tx; i++)  //  Set initial DMX Values to 0
  {
    buffer_dmx[i] = 0;
  } //end set DMX values to 0
  for (int i = 18; i<MAX_BUFFER_UDP; i++)  //set packet buffer to all '0', except header
  {
    packetBuffer[i] = 0;
  }

//  Set PAcket Header into Buffer

  for (int i = 0; i<8; i++)
  {
    packetBuffer[i] = ArtNetHead[i];
  }
  packetBuffer[8] = 0x00;//Opcode;  // low byte
  packetBuffer[9] = 0x50;//(Opcode >> 8);  // high byte
  packetBuffer[10] = artnet_version_1;  //Protocol Version HIGH
  packetBuffer[11] = artnet_version_2;  // Prococol Version LOW
  //packetBUffer[12] = seq_artnet:  // sequence number(increment with each transmission)
  packetBuffer[13] = artnet_physical;  // physical input receiving DMX signal
  packetBuffer[14] = sendUniverse;  // universe being transmitted (LOW Byte)
  packetBuffer[15] = (sendUniverse >> 8);  // universe being transmitted (HIGH Byte)
  packetBuffer[16] = (dmx_chan_tx >> 8);  // # of transmitting DMX Chan (HIGH byte)
  packetBuffer[17] = dmx_chan_tx;  // # of transmitting DMX Chan (LOW byte)

}// end setup

void loop()
{
  //read potentiometer, convert reading to scale (0-FF)
  for (int i =0; i< sendDmxNum; i++)
  {
    buffer_dmx[sendDmxCh+i] = getLevel(i); //insert reading from potentiometer into DMX Buffer
    if (buffer_dmx[sendDmxCh+i] == packetBuffer[sendDmxCh+17+i] && diffDmxVal == false)
    {
      diffDmxVal = false;//if no change of DMX value, do not send packet
    } else
    {
      diffDmxVal = true;  //if change of DMX value, write into UDP buffer, and send packet
    }
    // copy values from buffer_dmx into packetBuffer
    packetBuffer[sendDmxCh+17+i] = buffer_dmx[sendDmxCh +i];
  }

//  *****  max time between transmissions

  if (millis() - lastTxTime > maxTxTime)
  {
    diffDmxVal = true;
  }

  packetBuffer[12] = seq_artnet;  //load seq# into UDP buffer 
  //Send Artnet packet if value change, or timeout
  switch (diffDmxVal)
  {
    case false:  //if no new DMX value, do not transmit
      break;
    case true:
  {
    int goodUdp = Udp.sendPacket(packetBuffer,MAX_BUFFER_UDP,sendIp, localPort);  //depreciated for Uno
    if (goodUdp > 0) 
    {
      lastTxTime = millis();  //packet sent, reset timer,
      seq_artnet ++; //increment Sequence Number in artnet header
    }
    diffDmxVal =false; //reset state change detection
  }
  break;
  }
  delay(10);

}//end loop
 
 
unsigned char getLevel(int i)
{
  int levelPot = analogRead(levelPin[i]);
  levelPot = map(levelPot,0,1023,0,255);
  return(levelPot);
}



Any thoughts about what I am doing wrong?

trussmky

I have just discovered that Udp.endPacket() is returning an error(value of 0), and taking 1800millis to do so.

Am I not implementing the new protocols correctly?
Udp.beginPacket returns a 1, which is a sucessful execution,
Udp.write returns a 531, which would be the correct size of the buffer being written

anyone have thoughts?

PaulS

Typically, 0 means success. Why do you think that 0 means that an error occurred?

trussmky

Well, I have it working, but I don't understand why.

I changed the IP to which I am sending, to be 255.255.255.255, instead of sending to ip[0].255.255.255.

my understanding is that I am now broadcasting to all IP's, where before I was only broadcasting to IP's in the same subnet.  am I misunderstanding this? 

Can someone explain why it would work in the old version, but not the current version?

trussmky

@Paul
this is copied from EthernetUdp.h

Code: [Select]
// Finish off this packet and send it
  // Returns 1 if the packet was sent successfully, 0 if there was an error
  virtual int endPacket();

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy