UDP Freezing and other issues with W5500

Hi

I have seen many people having the same issue - but none of the solutions proposed worked for me. The closest it got was this topic: UDP freezes, possible cure found(???) - Networking, Protocols, and Devices - Arduino Forum

The problem is overall that the Ethernet lib freezes when sending a UDP packet.

The analysis I got so far:

  • The code gets stuck in the while loop in EthernetClass::socketSendUDP (bottom of socket.cpp file)
  • The loop is getting the value of the SnIR register (chipW5100.readSnIR) and waiting for either SEND_OK or TIMEOUT from the w5500, but it only gets 0.

I have 3 w5500 modules and the 3 modules give the same results: sometimes it hangs, sometimes it returns timeout, but it never stops if the Eternet cable is unplugged. And when sending a packet to a server, I can see the packet is sent right away (this part always works), and then sometimes the endPacket returns (SEND_OK) after 5-6 seconds, sometimes right away, and sometimes it never returns. And strangely if it returns right away (i.e. working), then it works fine for the next 20-30 times, and then it goes back to freezing.
But the actual UDP packet is always sent right away, as said this always works.

See below an example code and the output result.

#include <Ethernet.h>

#define PORT 9023

uint8_t mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAF};

EthernetUDP myUdp;

void setup() {
  IPAddress myLocalIP(192, 168, 87, 230);
  IPAddress serverIP(192, 168, 87, 187);
  
  Serial.begin(9600);
  Serial.println("##############");

  Ethernet.begin(mac, myLocalIP);

  Serial.print("Hardware: ");
  switch (Ethernet.hardwareStatus()) {
    case EthernetW5100:  Serial.println("W5100"); break;
    case EthernetW5200:  Serial.println("W5200"); break;
    case EthernetW5500:  Serial.println("W5500"); break;
    default:             Serial.println("No Hardware!");
  }
  
  Serial.print("Link Status: ");
  switch (Ethernet.linkStatus()) {
    case LinkON:  Serial.println("ON"); linkOn = true; break;
    case LinkOFF: Serial.println("OFF"); linkOn = false; break;
    default:      Serial.println("Unknown!");
  }

  if (!myUdp.begin(PORT))
    Serial.println("### UDP begin ERROR");

  if (!myUdp.beginPacket(serverIP, PORT))
    Serial.println("### UDP beginPacket ERROR");
  
  size_t len = myUdp.write("testing");
  Serial.print(len); Serial.println(" bytes written.");

  Serial.println("Calling endPacket() NOW");
  if (!myUdp.endPacket())
    Serial.println("### FAIL");
  else
    Serial.println("SUCCESS");
}

void loop() {
}

When the Ethernet cable is disconnected it never ends:

##############
Hardware: W5500
Link Status: OFF
7 bytes written.
Calling endPacket() NOW

When connected it ends "most of the times", with a variable delay before the SUCCESS (as written above):

##############
Hardware: W5500
Link Status: ON
7 bytes written.
Calling endPacket() NOW
SUCCESS

Ok I think I found the issue!!

Doing some further testing it turns out none of the register values I write on the w5500 are written properly, for example I write the local IP Address (SIPR common register), and then read it with Ethernet.localIP() and the value is partly the same (some bytes are the same) but different. And again same behavior - sometimes it works sometimes it does not.

Then I happen to touch the wires between the arduino and the Ethernet board, and realized their position influence a lot whether it works or not!!!

Bloody hell - the problem was simply my breadboard >_< !

I moved the arduino (nano) to a different breadboard, added a couple of 100nF caps around the power lines, and now everything works smoothly!!

PS: funny thing is just this morning I watched a YouTube video about how breadboards are not all the same quality - well I paid my cheap breadboard the high price, made me do intense 5 days of debugging :smiley: