[Solved] WizNet W5500 - incorrect linkStatus returned

I have just purchased a W5500 board to replace my W5100 shield. The W5100 does not have the link status reporting feature, but my understanding is that the W5500 should correctly report the status of the Ethernet link. My board is connected to a Cisco SRW2008 Gigabit switch using a standard Ethernet CAT5 patch cable. There is one light on the router port which is correct as the board is not a Gigabit device so is negotiated as 10/100 speed. There is only one light lit on the port on the board although the LHS light does blink every now and then.

I have tried an alternative patch cable as well as connecting to another switch. In both cases the link is always reported as being down. At the same time, I can ping the interface on the assigned IP address so clearly the link is connected and working.

Here is the function in the sketch that initialises my Ethernet connection:

bool initEthernet(){
  // Initialise the ethernet object
  Ethernet.begin(macAddr, ipAddr, ipDns, ipGate, ipMask);
//  Ethernet.begin(macAddr, ipAddr);
  delay(1);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    return false;
  }else{
    ethDetected = true;
    if (Ethernet.hardwareStatus() == EthernetW5100) {
      // Start - LinkOFF has no meaning on WS5100
      Serial.println(F("Started W5100 ethernet."));
      ethConnected = true;
      return true;
    }
    if (Ethernet.hardwareStatus()==EthernetW5200 || Ethernet.hardwareStatus()==EthernetW5500){
      Serial.println(F("Started W5200/W5500 ethernet."));
      if (Ethernet.linkStatus() == LinkOFF){
        Serial.println(F("Ethernet link is down."));
        return false;
      }else{
        Serial.println(F("Ethernet link is up."));
        ethConnected = true;
        return true;
      }
    }
  }
  return false;
}

The report I get is:

Started W5200/W5500 ethernet.
Ethernet link is down.

So it seems that hardware is being detected but the result of "if (linkStatus() == linkOFF) is being evaluated incorrectly. Programming for Ethernet shields is still pretty new to me so I might be missing something? Anyone know why it might be mis-reporting the status?

I did find this issue, but the final solution seems unrelated to the problem? I mean, to be sure, the wrong IP address would not have helped matters, but how could that relate to resolving the status of the Ethernet link, i.e. whether the cable is physically plugged in or not? That is surely detected at some hardware level? or does it perhaps detect whether ARP has been successful?

In my case I CAN ping the IP address of my interface so I know it is up and running.

I should probably add that I am using the built-in Ethernet.h library. My IDE seems to have no Ethernet2.h library.

try the link check in the loop()

Thank you for that suggestion about putting it in the loop. I experimented by adding a line at the beginning of the loop to just print the status of the link. This showed that the status does change when the cable is unplugged and then plugged back in again. I also noticed that initially in the loop the link was showing as being down, but after handful of iterations it came up. Evidently a delay was required. In the Arduino chat server example this is placed immediately after Ethernet.HardwareStatus() so I tried a delay of up to 5 seconds using delay() but this didn't work. Instead I tried a timeout loop like this:

if (Ethernet.hardwareStatus()==EthernetW5200 || Ethernet.hardwareStatus()==EthernetW5500){
      unsigned long timeout = millis()+3000;
      Serial.println(F("Started W5200/W5500 ethernet."));
      // Wait for LinkON
      while (Ethernet.linkStatus() == LinkOFF) {
        // Break out if timeout reached
        if (millis() > timeout) break;
        delayMicroseconds(100);
      }
      if (Ethernet.linkStatus() == LinkOFF){
        Serial.println(F("Ethernet link is down."));
        return false;
      }else{
        Serial.println(F("Ethernet link is up."));
        ethConnected = true;
        return true;
      }
    }

This works although I'm not sure why a simple delay() didn't. I also plan to put some detection into the loop so that if the link becomes disconnected, the Arduino will not keep trying to send data over it.

and W5100?

Dealt with for now by the preceding IF statement which I omitted from the above:

   if (Ethernet.hardwareStatus() == EthernetW5100) {
      // Start - LinkOFF has no meaning on WS5100
      Serial.println(F("Started W5100 ethernet."));
      ethConnected = true;
      return true;
    }

Since there is no automatic detection, this simply assumes the link is up. I don't know yet whether it is possible to add some alternative software based detection routine, for example testing for a response to a ping from the host we are communicating with or a response to an arp/rarp request or something similar but I'm not sure that would be entirely satisfactory and the process would have to be implemented in the loop anyway.