Possible causes for failure/hang while sending UDP Packets

I'm trying to have an arduino ethernet send UDP packets to a computer on a local network. I have my target server running at 10.2.12.39, listening on port 2011. My arduino ethernet connects with an IP at 10.2.12.36. Whenever a sensor reaches a threshold, the following code runs:

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <avr/wdt.h>

byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0x40, 0x9F};
byte ip[] = {10,2,12,36};
byte secondServer[] = {10,2,12,39};
int port = 2011;
char output[12];
EthernetUDP UdpClient;

//sensor parameters
byte NUM_SENSORS = 4;
byte readPin[] = {2,3,5,4};
byte ledPin[] = {6,7,8,9};
byte val[] = {0,0,0,0};
byte sensorState[] = {0,0,0,0};

String content;

void setup() {
  wdt_enable(WDTO_8S);
  
  Serial.begin(9600);
  
  Serial.println("Opening Serial Port...");
  
  Serial.println("Initializing HTTP Client...");
  Ethernet.begin(mac, ip);
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  delay(1000);
  
  for(int i = 0; i < NUM_SENSORS; i++) {
    pinMode(readPin[i],INPUT);
    pinMode(ledPin[i],OUTPUT);
  }
}

void loop() {
    wdt_reset();
  
  /* READ SENSOR */
  Serial.println("Checking card readers...");
  for(int i = 0; i < NUM_SENSORS; i++) {
    val[i] = digitalRead(readPin[i]);

    if ((sensorState[i] ^ val[i]) & (!val[i])) {
      //rising edge
      Serial.println("Rising edge detected!");
      content = "do 6 ";
      content.concat(i+1);
      content.concat(" card");
      content.toCharArray(output, content.length());
      
      Serial.println("Sending UDP packet to server.");
      UdpClient.beginPacket(secondServer, port);
      UdpClient.write(output);
      UdpClient.endPacket();
      Serial.println("UDP packet sent.");
      
      digitalWrite(ledPin[i], 1);
    }
    else if ((sensorState[i] ^ val[i]) & (val[i])) {
      //falling edge
      Serial.println("Falling edge detected!");
      digitalWrite(ledPin[i],0);
    }
    sensorState[i] = val[i];
  }
  delay(100);
}

String split(String data, char delimiter, int index) {
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==delimiter || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

I always receive the first message, and then the program hangs before displaying the second serial message (after the UDP.endpacket()). I'm using a watchdog timer set to 8 seconds, so after 8 seconds the program resets.

I've tried pinging the arduino from the computer on the network, and receive pings -- but i'm not sure how to check if the port's open by asking the arduino to ping the computer.

That said, my understanding was that UDP would effectively send-it-and-forget-it, so I'm a bit confused by why sending UDP packets is causing the arduino to hang. Any suggestions as to what's going on?

I always receive the first message, and then the program hangs before displaying the second message.

What's the output on the serial interface if that code runs? Show the complete sketch, maybe the problem is somewhere else. BTW: you don't check any return code of the calls you make. If there's any problem you'll never notice. May be your biggest problem.

I edited my first post to include the full code.

What return codes should I be looking for? Which functions have useful return codes that I should be verifying? I'm not away of ones that might help me debug this.

thanks!

I edited my first post to include the full code.

Do you also have the serial output? That would help to find the location of the freeze.

What return codes should I be looking for? Which functions have useful return codes that I should be verifying?

All three UDP calls you made return 0 in case of an error. If you write at least an error to the serial interface you might know where you have to look for the problem.

UdpClient.write(output);

output is defined as a 12 byte character array. You use the single argument version of write() which writes out one byte. As you provide a pointer to a character array it sends the lowest significant byte of the pointer in the UDP packet. I'm almost sure the compiler generates a warning for this line of code whle compiling.
Try to eliminate the use of the String class by using snprintf() to write directly to the character array.

The serial output is as I said -- it sends the message before the UDP.beginPacket(), but not the message after endPacket(). I don't have the arduino physically with me at the moment, but I can't copy/paste exactly what it outputs, but nothing unexpected happens in the output other than the freeze.

I tried compiling the code to check for any errors, but I get no errors in the arduino IDE while trying to compile it.

How would I fix the UDP.write() line?

The arduino page for it (Ethernet - Arduino Reference) shows them sending a string:

  Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());

    Udp.write("hello");

    Udp.endPacket();

and I tried changing my line to

      UdpClient.beginPacket(secondServer, port);
      UdpClient.write(output, 12);
      UdpClient.endPacket();

but this generates a compile error:

cardReader.ino: In function 'void loop()':
cardReader:119: error: invalid conversion from 'char*' to 'const uint8_t*'
cardReader:119: error: initializing argument 1 of 'virtual size_t EthernetUDP::write(const uint8_t*, size_t)'

asymptoticdesign:
The arduino page for it (Ethernet - Arduino Reference) shows them sending a string:

  Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());

Udp.write("hello");

Udp.endPacket();

That's wrong there too.

Change your code to:

      if (! UdpClient.beginPacket(secondServer, port)) Serial.println(F("beginPacket error"));
      if (! UdpClient.write((uint8_t *) output, content.length)) Serial.println(F("write error));
      if (! UdpClient.endPacket()) Serial.println(F("endPacket error"));

Post the output you get.

I replaced my code with yours, and received:

Opening Serial Port...
Initializing HTTP Client...
My IP address: 10.2.12.36
Running initialization sequence.
Checking card readers...
[repeat for  while...]
Rising edge detected!
write error

It looks like the major difference (besides error codes) is that you cast output as a byte array, yes?

Maybe you should start a UDP socket first. I added one to this code after the delay.

void setup() {
  wdt_enable(WDTO_8S);
  
  Serial.begin(9600);
  
  Serial.println("Opening Serial Port...");
  
  Serial.println("Initializing HTTP Client...");
  Ethernet.begin(mac, ip);
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  delay(1000);
  
// start a UDP socket
  UdpClient.begin(port);

  for(int i = 0; i < NUM_SENSORS; i++) {
    pinMode(readPin[i],INPUT);
    pinMode(ledPin[i],OUTPUT);
  }
}

You are absolutely correct. That's an embarassing mistake to make -- thanks!