Inter-Arduino Comms w/ UDP

I have written two sketches to test development features. I have the Ethernet Shield and based my sketches on the sample UDP program.

They don't work. They both seem to initialize properly. The debug statements look like everything is working. Except, no packets appear to be received.

First, I have had some confusion on which libraries to use. Of the four libraries listed below,

  • Ethernet.h
  • Ethernet2.h
  • EthernetUDP
  • EthernetUDP2
  • no UDP library

The sketch compiles with only Ethernet.h and no UDP library.

I am providing listings below, as well as attaching the source code.

Any ideas?

This sketch is used to send a message:

// sends a message first

#include <SPI.h>
#include <Ethernet.h>
// #include <EthernetUdp2.h>

#define localID 10 // local
#define remoteID 20 // remote
#define localPORT 8888 // Port
#define EthMegPin 53
#define debugDelay 2500
#define Halt while(true)
#define Forever while(true)
#define aWait 2000

// define UDP object
EthernetUDP sendUdp;

char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[] = "ack";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, localID };

IPAddress  local_IP(10, 1, 1, localID);
IPAddress remote_IP(10, 1, 1, remoteID);
int packetSize;
byte localScriptToken = 0;
int remote_message = 100;



void setup() {
  Serial.begin(9600);

  pinMode(EthMegPin, OUTPUT);
  digitalWrite(EthMegPin, HIGH);
  // Ethernet.init(10);  // Most Arduino shields

  // localID read in setup
  // mac[5] = localID;
  // local_IP[3] = localID;
  // remote_IP[3] = remoteID;
  for (int i = 0; i < 4; i++) {
    Serial.print(local_IP[i]);
    if (i < 3) Serial.print(", ");
  }; Serial.println(" <-local");

  IPAddress remote_IP(10, 1, 1, remoteID);
  for (int i = 0; i < 4; i++) {
    Serial.print(remote_IP[i]);
    if (i < 3) Serial.print(", ");
  }; Serial.println(" <-remote");
  Serial.println();

  Ethernet.begin(mac, local_IP);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    Halt;
  } else {
    Serial.println("Setup: Found Ethernet Shield");
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Setup: Ethernet cable is not connected.");
    Halt;
  } else {
    Serial.println("Setup: Cable connected");
  }

  int Udp_Conn = sendUdp.begin(localPORT);

  if (Udp_Conn) {
    Serial.print("Setup: UDP port connection successful to ");
    Serial.println(localPORT);
  }
  else {
    Serial.print("Setup: UDP port connection failed to ");
    Serial.println(localPORT);
    Halt;
  }
  Serial.println();
}


void loop() {
  // int UdpConn = sendUdp.beginPacket(remote_IP, sendUdp.remotePort());
  int UdpConn = sendUdp.beginPacket(remote_IP, localPORT);


  for (int i = 0; i < 4; i++) {
    Serial.print(remote_IP[i]);
    if (i < 3) Serial.print(", ");
  }; Serial.print(":");
  Serial.print(localPORT);
  Serial.println(":  <-remote");

  if (UdpConn) {
    Serial.println("Loop: Begin packet successful");
  }
  else {
    Serial.println("Loop: _UDP packet begin failed. Host not found");

    for (int i = 0; i < 4; i++) {
      Serial.print(local_IP[i]);
      if (i < 3) Serial.print(", ");
    }; Serial.println(" <-local");

    for (int i = 0; i < 4; i++) {
      Serial.print(remote_IP[i]);
      if (i < 3) Serial.print(", ");
    }; Serial.println(" <-remote");
  }

  remote_message ++;
  itoa(remote_message, UDPSendBuffer, 10);
  int charsSent = sendUdp.write(UDPSendBuffer);
  //  delay(debugDelay);
  delay(100);
  Serial.print(charsSent);
  Serial.println(" characters sent");
  int UdpSent = sendUdp.endPacket();
  if (UdpSent) {
    Serial.println("Loop: Message sent via UDP");
  }
  else {
    Serial.print("Loop: Error occurred during write [");
    Serial.print(UdpSent);
    Serial.println("]");
  }
 delay(aWait);
  Halt;
}

This sketch is used to receive a message.

/* #include <Dhcp.h>
  #include <Dns.h>
  #include <Ethernet2.h>
  #include <EthernetClient.h>
  #include <EthernetServer.h>
  #include <EthernetUdp2.h>
  #include <Twitter.h>
  #include <util.h> */

// receives a message first

#include <SPI.h>
#include <Ethernet.h>
// #include <EthernetUdp2.h>

#define localID 20
#define remoteID 10
#define localPORT 8888
#define EthMegPin 53
#define interpacketDelay 250
#define Halt while(true)
#define Forever while(true)

// define UDP object
EthernetUDP recvUdp;

char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[] = "ack";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xFE, 0x00 };
byte local_IP[4];
byte remote_IP[4];
int packetSize;
byte localScriptToken;
int remote_message = 0;


void setup() {
  Serial.begin(9600);

  // localID read in setup
  mac[4] = localID;
  IPAddress local_ip( 10, 1, 1, localID );
  IPAddress remote_IP(10, 1, 1, remoteID);

  Ethernet.begin(mac, local_ip);

  //print out the IP address
  Serial.print("Setup: Local IP = ");
  Serial.println(Ethernet.localIP());
  Serial.print("Setup: Rem't ID = ");
  Serial.println(remote_IP);

  /* Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    Halt;
    } */
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Setup: Ethernet cable is not connected.");
    Halt;
  }


  int Udp_Conn = recvUdp.begin(localPORT);
  if (Udp_Conn) {
    Serial.print("Setup: UDP port connection successful to ");
    Serial.println(localPORT);
  }
  else {
    Serial.print("Setup: UDP port connection failed to ");
    Serial.println(localPORT);
    Halt;
  }

  Serial.println(F("Starting..."));

}

void loop() {
#define Forever (true)
  int displayCount = 0;
  const int displayBlock = 10;
  while Forever {

  packetSize = recvUdp.parsePacket();
    if ((displayCount % displayBlock) == 0) {
      displayCount = 1;
      Serial.print(F("Packet Size  "));
      Serial.print(packetSize);
      Serial.print(" | ");
    }
    // receive a message
    if (packetSize > 0) {
      // display buffer
      recvUdp.read(UDPRecvBuffer, packetSize);
      Serial.print(F("Buffer  "));
      Serial.println(UDPRecvBuffer);
      // display token
      localScriptToken = atoi(UDPRecvBuffer);
      Serial.print(F("Recv'd "));
      Serial.println(localScriptToken);
      remote_message = localScriptToken;
      delay(interpacketDelay);
      // increment display count
      displayCount++;
    }
  }
}

How do you connect the two Ethernet shields?

Thanks for your reply.

With an Ethernet Cat-5 Crossover cable.

Without the crossover cable each shield does not see the other.

Without the crossover cable each shield does not see the other.

"see the other" means they get a link?

The sending sketch sends exactly one UDP packet. If that one isn't received by the other Arduino you won't see anything. Try sending at least one packet every few seconds.

“See each other” indeed means a link is established. The status LEDs on the Ethernet shield don’t illuminate. With a crossover cable, power, link, full duplex and 100M light up.

I will try sending a message multiple times. But why is that necessary?

Sorry I missed your post. I haven’t checked back in a while. But if you can help me get this to work, that would be great!

Looking through you code on the recieving side I can see 2 problems though not sure if either is adversely affecting things.

First you define the mac[] with 5 bytes, then in the code you reset the 5th byet with mac[4] = local_ip
You would be better suing the same method as you have in the send side of things and include the local_ip in the mac definition. IE use: byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, localID };

Second in the loop procedure you surrond almost everything inside a blocking loop of you own where you have "while Forever {"
This is bad and will probably result in blocking the Arduino from processing other things outside of your code resulting in no apparent activity. Discard your "while forever" loop and rely on the void loop function. You could make the two variables you declare global.

You also appear to have multiple declarations of the same thing in different contexts which can lead to confusion It would be worth simplifying that by having just one, for example in the transmit code just have the global "IPAddress remote_IP(10, 1, 1, remoteID);"

Can you also post the output you get from the two when you test them?

Thanks for the advice on defining mac[]. I’ll make that change.

And I’ve already renamed the values used in defining. You’re correct that they could be confusing. I now have remote_IP and IDremote.

Also, I added additional debugging code and print out sendUDP.remoteIP() and sendUDP.remotePort() after each call to a UDP function.

THEY ARE ALL ZERO! I’m going back to see why that may be so... please let me know if you see anything.

Addendum

Re: Forever. I’ve gotten into the practice of using an infinite loop which contains my processing. I didn’t trust that the loop() mechanism was preserving calculated values needed in successive executions.

I will remove that by changing my #define. However, I’ve used this structure in many sketches. Including one that uses SD cards for run-time parameters, controls 16 servos, plays MP3 files, sends the output to an internal amplifier and a sound mixer and controls servos based on those files.

Using the Forever macro. Without any problems.

djsfantasi:
Thanks for the advice on defining mac[]. I’ll make that change.

And I’ve already renamed the values used in defining. You’re correct that they could be confusing. I now have remote_IP and IDremote.

Also, I added additional debugging code and print out sendUDP.remoteIP() and sendUDP.remotePort() after each call to a UDP function.

THEY ARE ALL ZERO! I’m going back to see why that may be so... please let me know if you see anything.

I think it best for you to post your revised code otherwise there is too great a chance of misunderstanding or missing somethng.

Hello!

I have gotten the transmit code working somewhat. At least, the sendUdp.print() command isn't returning an error. As you asked, I am posting the send code and the output from that sketch. Note what happened. One is that when I commented out the block of code after the if test "if (Ethernet.linkStatus() == LinkOFF)", then the sendUdp.print() worked.

// sends a message first

#include <SPI.h>
#include <Ethernet.h>


#define idLocal 10 // local
#define idRemote 20 // remote
#define localPORT 8888 // Port
#define EthMegPin 53
#define debugDelay 2500
#define Halt while(true)
#define Forever while(true)
#define aWait 2000

// define UDP object
EthernetUDP sendUdp;

char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[] = "ack";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, idLocal };

IPAddress  local_IP(10, 1, 1, idLocal);
IPAddress remote_IP(10, 1, 1, idRemote);


void setup() {
  Serial.begin(9600);
  Serial.println("Send module");

  Ethernet.begin(mac, local_IP);
  delay(1000);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    Halt;
  } else {
    Serial.println("Setup: Found Ethernet Shield");
  }

 /* if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Setup: Ethernet cable is not connected.");
    Halt;
  } else {
    Serial.println("Setup: Cable connected");
  } */

  int Udp_Conn = sendUdp.begin(localPORT);

  if (Udp_Conn) {
    Serial.print("Setup: UDP port connection successful to ");
    Serial.println(localPORT);
    Serial.print(Udp_Conn);
    Serial.print(" function return code ");
    Serial.print("to ");
    Serial.print(sendUdp.remoteIP());
    Serial.print(":");
    Serial.println(sendUdp.remotePort());
  }
  else {
    Serial.print("Setup: UDP port connection failed to ");
    Serial.println(localPORT);
    Serial.print("Loop: Error occurred during begin [");
    Serial.print(Udp_Conn);
    Serial.println("]");
    Serial.print("to ");
    Serial.print(sendUdp.remoteIP());
    Serial.print(":");
    Serial.println(sendUdp.remotePort());
    Halt;
  }
  Serial.println();
}


void loop() {

int remote_message = 100;

//  Forever {

    int UdpConn = sendUdp.beginPacket(remote_IP, localPORT);

    if (UdpConn) {
      Serial.println("Loop: Begin packet successful");
    }
    else {
      Serial.print("Loop: _UDP packet begin failed. Host not found");
      Serial.println(sendUdp.remoteIP());
    }

    remote_message ++;
    itoa(remote_message, UDPSendBuffer, 10);
    //  int charsSent = sendUdp.write(UDPSendBuffer);
    int charsSent = sendUdp.print(remote_message);
    //  delay(debugDelay);
    delay(1000);
    Serial.print(charsSent);
    Serial.println(" characters sent");

    int UdpSent = sendUdp.endPacket();
    if (UdpSent) {
      Serial.println("Loop: Message sent via UDP");
      Serial.println();
    }
    else {
      Serial.print("Loop: Error occurred during write [");
      Serial.print(UdpSent);
      Serial.println("]");
      Serial.print("to ");
      Serial.print(sendUdp.remoteIP());
      Serial.print(":");
      Serial.println(sendUdp.remotePort());
      Halt;
    }
    delay(aWait);
//  }
}

Here is the output attached to this post.

Capture.JPG

More information...

The previous screenshot from the output was taken while each Arduino was connected to my laptop. I was running a packet capture program there. All link lights were on when I used a cross-connect cable. I tested the receiver in a similar manner and the listing and output are below/attached.

However, now when I connect the two Arduino Megas and Ethernet shields together, the status checks still succeed, but the link lights arent on... The send sketch appears to work but the receive sketch doesn't get anything...

I am confused, so I'm going to stop for the night. Hopefully, you can get an idea.

// receives a message first

#include <SPI.h>
#include <Ethernet.h>
// #include <EthernetUdp2.h>

#define idLocal 20
#define idRemote 10
#define localPORT 8888
#define EthMegPin 53
#define interpacketDelay 250
#define Halt while(true)
#define Forever while(true)

// define UDP object
EthernetUDP recvUdp;

char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[] = "ack";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xFE, 0x00 };


void setup() {
  Serial.begin(9600);
  Serial.println("Receive module");

  // idLocal read in setup
  mac[4] = idLocal;
  IPAddress local_ip( 10, 1, 1, idLocal );
  IPAddress remote_IP(10, 1, 1, idRemote);

  Ethernet.begin(mac, local_ip);
  delay(1000);

  //print out the IP address
  Serial.print("Setup: Local IP = ");
  Serial.println(Ethernet.localIP());
  Serial.print("Setup: Rem't ID = ");
  Serial.println(remote_IP);

  /*
      Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    Halt;
    } */
  /*
    if (Ethernet.linkStatus() != LinkOFF) {
    Serial.println("Setup: Ethernet cable is not connected.");
    Halt;
    }
    else
    {
    Serial.println("Cable properly connected");
    }
  */

  int Udp_Conn = recvUdp.begin(localPORT);
  if (Udp_Conn) {
    Serial.print("Setup: UDP port connection successful to ");
    Serial.println(localPORT);
  }
  else {
    Serial.print("Setup: UDP port connection failed to ");
    Serial.println(localPORT);
    Halt;
  }

  Serial.println(F("Starting..."));

}

void loop() {

  //  Forever {

  int packetSize = recvUdp.parsePacket();
  // receive a message
  if (packetSize > 0) {
    recvUdp.read(UDPRecvBuffer, packetSize);
    Serial.print(F("Buffer  "));
    Serial.println(UDPRecvBuffer);
    delay(interpacketDelay);
    // increment display count
  }
  //  }
}

Capture.JPG

I am ny clear on how you connected everything (it may be just too late in the day), but you refer to each arduino conncted to your laptop - were you using a hub/switch, or do you mean on at a time? All lights were on when you used a cross connect cable - did you try with a straight cable? Many laptops will accept either as will many hubs and switches.

Connecting the two arduinos you say the link lights are not on. Are the link lights just for the link or to indicate speed - sometimes a light is on for 100MBps andnot for 10 - though most seem to use different colours. Again was this the cross cable or straight cable you used?

One very obvious thing, have you checked the ethernet cable works with both the arduinos using a simple test sketch to the PC? It would not be the first time hours are send trying to debug some code only to discover a faulty cable!

The mac address on your receive sketch is still wrong, you only set the first 5 bytes and then reset the 5th byte.

I am also a little concerned about the ports you are using, though ths may simply be terminology. On the client you refer to the localPort (8888) but when sending a UDP packet you need to tell it which port to send to on the remote receiving machine. On the server side you normally have to tell it which localport you want to read from. I think the sending sketch should use the term remotePort and the receiving sketch localPort - though that is not the cause of the problem.

When receiving data using Udp.read is would be normal to pass the buffer size as the second argument rather than the packetsize - so Udp.read(UDPRecvBuffer, UDP_TX_PACKET_MAX_SIZE);
Your server side does not send an acknowledgement - I presume you have just not got that far yet.

The delay function blocks, that is nothing else can take place whilst waiting for the delay to finish which could be a cause of problems. I suggest for the time being you just comment that line out and let the code simply loop repeatedly as fast as it can. In ethernet terms 250ms is a very long time and packets could conceiveably be missed.

When testing, it looks as though you will have to start the server up before the client

Testing the send/receive modules is done with one Mega connected to the laptop with a cross-over cable. When testing both together, the two modules are connected with a cross-over cable.

I have tested with a straight-through cable. It doesn’t work. I have tested both Ethernet cables and they are good.

The lights I’m referring two are on the Ethernet2 shield. I’ve documented their function in an earlier post. They are power, link, full duplex and 100M. I also check the link light on the laptop.

I see what you’re saying about the mac[] setup. But it shouldn’t make a difference, as long as both mac addresses are unique. I’ll test setting the mac the same way I do in the send module.

As far as the UDP port, they are the same on both modules. I don’t use a variable for the remote port. Perhaps it will be clearer if I renamed localPort to portUDP.

I did some more testing while waiting for your reply. I found two issues. One, the send module had a duplicate IP address. Two, the Ethernet2 shields locked up with all the cable swapping (and the duplicate IP address).

I’m going to repeat the tests tomorrow. I’ll only use the cross-over cable. I’ll correct the duplicate IP address. And when swapping cables, I’ll power cycle the modules.

After addressing the items you mentioned, both module were able to work with my laptop. The most obvious change came about when I discovered on my own a problem with the MAC address - then I finally understood what you were saying. In the receive module, I only set 5 of 6 bytes.

However, when I connect them together, they don't work. Or at least the send module. Since that wasn't working, I cant say anything about the receive module.

Here is the current code... The output of each module is attached. First, the send module.

// sends a message first

#include <SPI.h>
#include <Ethernet.h>


#define idLocal 10 // local
#define idRemote 20 // remote
#define localPORT 8888 // Port
#define EthMegPin 53
#define debugDelay 2500
#define Halt while(true)
#define Forever while(true)
#define aWait 2000

// define UDP object
EthernetUDP sendUdp;

char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[] = "ack";
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, idLocal };

IPAddress  local_IP(10, 1, 1, idLocal);
IPAddress remote_IP(10, 1, 1, idRemote);

int remote_message = 100;


void setup() {
  Serial.begin(9600);
  Serial.println("Send module");

  Ethernet.begin(mac, local_IP);
  delay(1000);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    Halt;
  } else {
    Serial.println("Setup: Found Ethernet Shield");
  }

 /* if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Setup: Ethernet cable is not connected.");
    Halt;
  } else {
    Serial.println("Setup: Cable connected");
  } */

  int Udp_Conn = sendUdp.begin(localPORT);

  if (Udp_Conn) {
    Serial.print("Setup: UDP port connection successful to ");
    Serial.println(localPORT);
    Serial.print(Udp_Conn);
    Serial.print(" function return code ");
    Serial.print("to ");
    Serial.print(sendUdp.remoteIP());
    Serial.print(":");
    Serial.println(sendUdp.remotePort());
  }
  else {
    Serial.print("Setup: UDP port connection failed to ");
    Serial.println(localPORT);
    Serial.print("Loop: Error occurred during begin [");
    Serial.print(Udp_Conn);
    Serial.println("]");
    Serial.print("to ");
    Serial.print(sendUdp.remoteIP());
    Serial.print(":");
    Serial.println(sendUdp.remotePort());
    Halt;
  }
  Serial.println();
}


void loop() {

//  Forever {

    int UdpConn = sendUdp.beginPacket(remote_IP, localPORT);

    if (UdpConn) {
      Serial.println("Loop: Begin packet successful");
    }
    else {
      Serial.print("Loop: _UDP packet begin failed. Host not found");
      Serial.println(sendUdp.remoteIP());
    }

    remote_message ++;
    itoa(remote_message, UDPSendBuffer, 10);
    //  int charsSent = sendUdp.write(UDPSendBuffer);
    int charsSent = sendUdp.print(remote_message);
    //  delay(debugDelay);
    delay(1000);
    Serial.print(charsSent);
    Serial.println(" characters sent");

    int UdpSent = sendUdp.endPacket();
    if (UdpSent) {
      Serial.println("Loop: Message sent via UDP");
      Serial.println();
    }
    else {
      Serial.print("Loop: Error occurred during write [");
      Serial.print(UdpSent);
      Serial.println("]");
      Serial.print("to ");
      Serial.print(sendUdp.remoteIP());
      Serial.print(":");
      Serial.println(sendUdp.remotePort());
      Halt;
    }
    delay(aWait);
//  }
}

And the receive module...

// receives a message first

#include <SPI.h>
#include <Ethernet.h>

#define idLocal 20
#define idRemote 10
#define portUDP 8888
#define EthMegPin 53
#define interpacketDelay 250
#define Halt while(true)


// define UDP object
EthernetUDP recvUdp;

// define IP addresses
  IPAddress local_ip( 10, 1, 1, idLocal );
  IPAddress remote_IP(10, 1, 1, idRemote);


char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[UDP_TX_PACKET_MAX_SIZE];
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, idLocal };


void setup() {
  Serial.begin(9600);
  Serial.println("Receive module");

  // idLocal will be read in setup
  IPAddress local_ip( 10, 1, 1, idLocal );
  IPAddress remote_IP(10, 1, 1, idRemote);
  mac[5] = idLocal;

  Ethernet.begin(mac, local_ip);
  delay(1000);

  //print out the IP address
  Serial.print("Setup: Local IP = ");
  Serial.println(Ethernet.localIP());
  Serial.print("Setup: Rem't ID = ");
  Serial.println(remote_IP);

  /*
      Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    Halt;
    } */
  /*
    if (Ethernet.linkStatus() != LinkOFF) {
    Serial.println("Setup: Ethernet cable is not connected.");
    Halt;
    }
    else
    {
    Serial.println("Cable properly connected");
    }
  */

  int Udp_Conn = recvUdp.begin(portUDP);
  if (Udp_Conn) {
    Serial.print("Setup: UDP port connection successful to ");
    Serial.println(portUDP);
  }
  else {
    Serial.print("Setup: UDP port connection failed to ");
    Serial.println(portUDP);
    Halt;
  }

  Serial.println(F("Starting..."));

}

void loop() {

  int packetSize = recvUdp.parsePacket();
  
  // receive a message
  if (packetSize > 0) {
    recvUdp.read(UDPRecvBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.print(F("Buffer  "));
    Serial.println(UDPRecvBuffer);
  }
}

Send.png

Recv.png

The fact there are lo lights on but no errors being reported does seem strange. Do you have a spare ethernet switch/hub you could use to connect the two arduinos (with straight ethernet cables)? Whilst I realise you probaby don't want that longer term it may help to eliminate a possible issue at present.

Two things I've noticed on the client side

  1. In setup you begin a UDP server on port 8888, but you try and get the remote ip and port both of which are invalid at that point so return 0.0.0.0 and 0 respectively which you duly print out in the log. Becasue the server is only listening at that point and has not received anything there will be no remote client for it. You can probably drop trying to obtain the remote IP & port and not report it since it is not relevant at that time and can be confusing (I was confused about it for a while!)

  2. In the loop you have commented out the "int charsSent = sendUdp.write(UDPSendBuffer);" which I believe should be left in but should be "int charsSent = sendUdp.write(UDPSendBuffer, 10);" as you want to send more than just the one character. I'm not sure what you are trying to achieve with int charsSent = sendUdp.print(remote_message); since remote_message is simply a counter

On the server side:

  1. You define the ip adresses twice then redfine one of them again!

  2. Again you try and log the remote IP - but before any connection has been made.

  3. Not sure if you need a recvUdp.flush(); to finish reading the packet - but since we don't appear to be getting anything thats rather acedemic at present

Send side:

  1. Good information about the .remoteIP and .remotePort(). I’ll remove that debug code.
  2. That line was commented out because I decided to use the .print() routine instead and left the old line there if that didn’t work. Remote_message IS a counter AND the actual message I want to send.

I’ve ordered a small switch to test your suggestion. The final product will consist of 6-20 modules, talking to each other.

Thanks for all your help.

Receive/server side:

  1. I define the IP address twice because it needs to be a global variable, but the final value won’t be known until execution of loop() in the final sketch. I was testing if I could do that.
  2. Ok. I’ll remove that as it was only debug code.
  3. I’ll look into .flush(). Right now, when connected to my laptop, it works without it.

djsfantasi:
Send side:

  1. Good information about the .remoteIP and .remotePort(). I’ll remove that debug code.
  2. That line was commented out because I decided to use the .print() routine instead and left the old line there if that didn’t work. Remote_message IS a counter AND the actual message I want to send.

I’ve ordered a small switch to test your suggestion. The final product will consist of 6-20 modules, talking to each other.

Thanks for all your help.

Receive/server side:

  1. I define the IP address twice because it needs to be a global variable, but the final value won’t be known until execution of loop() in the final sketch. I was testing if I could do that.
  2. Ok. I’ll remove that as it was only debug code.
  3. I’ll look into .flush(). Right now, when connected to my laptop, it works without it.

Send 2 - I didn't realise that, makes more sense now.

With 6 -20 modules I think you need a large switch - well medium maybe :slight_smile:

Receive 1 - OK, Again I didn't realise makese sense now.

Receive 3 - OK, I don't know about flush it was only a passing comment. If it works without it, leave the code alone until the other issues are resolved - then maybe try it, if it looks as though it should be there.

Hello!

It works!

I removed the debug code regarding the UDP.remoteIP, etc...

I hooked up the switch to each module and the laptop (so I could monitor with a UDP capture tool on the laptop. Picture attached...

One thing! I tested the straight through cable. However, it was old. And the RJ45 jack on the Ethernet2 shield is right above the USB jack. It is difficult to insert and remove a patch cable. Apparently, a wire broke at the RJ45 connector while plugging and removing the cable. Using new cables which I had ordered, the status lights on the Ethernet2 shield (previously referred to incorrectly as link lights) were correct. Pictures attached.

So, with the switch, everything works! However, if I cabled directly between the Ethernet2 shields, it doesn’t.

Since the final application requires a switch, this is not really a problem.

Thanks immensely for your help. Another pair of eyes is always helpful! You helped me find (and resolve) many problems.

I'm pleased you've got it working, well done for persisting.

I would be interested in seeig the pictures if you have time to put them up.

Out of curiosty what UDP capture tool did you use on the PC?

FYI, I'm including the working code.

The tool that I use is called "Packet Sender". It's free and (although I don't need it) contains a feature to save your results to a free cloud account. You can download it from packetsender.com Other tools I recommend are NMAP and WIRESHARK.

Here are the final sketches. First the Send sketch:

// sends a message first

#include <SPI.h>
#include <Ethernet.h>


#define idLocal 10 // local
#define idRemote 20 // remote
#define portUDP 8888 // Port
#define Halt while(true)

// define UDP object
EthernetUDP sendUdp;

char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[UDP_TX_PACKET_MAX_SIZE];
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, idLocal };

IPAddress  local_IP(10, 1, 1, idLocal);
IPAddress remote_IP(10, 1, 1, idRemote);

int remote_message = 0;


// *****************************************
void setup() {
  Serial.begin(9600);
  Serial.println("Send module");

  Ethernet.begin(mac, local_IP);
  delay(1000);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    Halt;
  } else {
    Serial.println("Setup: Found Ethernet Shield");
  }

  int Udp_Conn = sendUdp.begin(portUDP);

  if (Udp_Conn) {
    Serial.print(F("Setup: UDP port connection successful to "));
    Serial.println(portUDP);
    Serial.print(Udp_Conn);
    Serial.print(F(" send.Udp.begin return code "));
  }
  else {
    Serial.print(F("Setup: UDP port connection failed to "));
    Serial.println(portUDP);
    Serial.print(F("Loop: Error occurred during begin ["));
    Serial.print(Udp_Conn);
    Serial.println(F("]"));
    Halt;
  }
  Serial.println();
}


// *****************************************
void loop() {

  IPAddress remote_IP(10, 1, 1, idRemote);
  int UdpConn = sendUdp.beginPacket(remote_IP, portUDP);

  if (UdpConn) {
    Serial.println(F("Loop: Begin packet successful"));
  }
  else {
    Serial.print(F("Loop: _UDP packet begin failed. Host not found"));
    Serial.println(sendUdp.remoteIP());
  }

  remote_message++;
  remote_message %=  255;

  itoa(remote_message, UDPSendBuffer, 10);
  //  int charsSent = sendUdp.write(UDPSendBuffer);
  int charsSent = sendUdp.print(remote_message);
  Serial.print(charsSent);
  Serial.println(F(" characters sent"));

  int UdpSent = sendUdp.endPacket();
  if (UdpSent) {
    Serial.println(F("Loop: Message sent via UDP"));
    Serial.println();
  }
  else {
    Serial.print(F("Loop: Error occurred during write ["));
    Serial.print(UdpSent);
    Serial.println(F("]"));
    Halt;
  }
  delay(2000);
}

And the receive sketch:

// receives a message first

#include <SPI.h>
#include <Ethernet.h>

#define idLocal 20
#define idRemote 10
#define portUDP 8888
#define Halt while(true)


// define UDP object
EthernetUDP recvUdp;

// define IP addresses
IPAddress local_ip( 10, 1, 1, idLocal );
IPAddress remote_IP(10, 1, 1, idRemote);


char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
char UDPSendBuffer[UDP_TX_PACKET_MAX_SIZE];
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, idLocal };


// *****************************************
void setup() {
  Serial.begin(9600);
  Serial.println(F("Receive module"));

  // idLocal will be read in setup
  IPAddress local_ip( 10, 1, 1, idLocal );
  IPAddress remote_IP(10, 1, 1, idRemote);
  mac[5] = idLocal;

  Ethernet.begin(mac, local_ip);
  delay(1000);

  //print out the IP address
  Serial.print("Setup: Local IP = ");
  Serial.println(Ethernet.localIP());
  Serial.print("Setup: Rem't ID = ");
  Serial.println(remote_IP);

  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println(F("Setup: Ethernet shield was not found.  Sorry, can't run without hardware. :("));
    Halt;
  } else {
    Serial.println(F("Setup: Found Ethernet Shield"));
  }

  int Udp_Conn = recvUdp.begin(portUDP);
  if (Udp_Conn) {
    Serial.print(F("Setup: UDP port connection successful to "));
    Serial.println(portUDP);
  }
  else {
    Serial.print(F("Setup: UDP port connection failed to "));
    Serial.println(portUDP);
    Halt;
  }
  Serial.println(F("Ready to receive..."));
}


// *****************************************
void loop() {

  int packetSize = recvUdp.parsePacket();

  // receive a message
  if (packetSize > 0) {
    recvUdp.read(UDPRecvBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.print(F("Buffer  "));
    Serial.println(UDPRecvBuffer);
  }
}
1 Like