If you are building a hardwired IoT node or a local data logger in 2026, the WIZnet W5500 is the definitive chip for Arduino Ethernet projects. It replaces the obsolete W5100 and outperforms the ENC28J60 by offloading the TCP/IP stack to hardware, saving your microcontroller's limited RAM for actual application logic. This guide walks through the exact hardware selection, pin mapping, and a complete, error-handled web server build targeting the Arduino Uno R3.

Hardware Selection: W5500 vs W5100 vs ENC28J60

Before wiring anything, verify which chip is on your shield. Buying the wrong variant is the most common reason builders abandon Ethernet projects. The W5100 is officially obsolete, and the ENC28J60 requires heavy software overhead.

Arduino Ethernet Shield Chip Comparison
Feature WIZnet W5500 (Recommended) WIZnet W5100 (Obsolete) Microchip ENC28J60
Hardware TCP/IP Stack Yes (TCP, UDP, IPv4, ICMP, ARP) Yes (Older implementation) No (Requires UIPEthernet lib)
Internal RAM 32 KB (16KB TX / 16KB RX) 16 KB 8 KB (Shared with MCU)
SPI Interface Speed Up to 80 MHz Up to 14 MHz Up to 20 MHz
MCU RAM Overhead Minimal (~1 KB) Moderate Heavy (~4-6 KB on ATmega328P)
Typical 2026 Price $8 - $14 (Shield) $12+ (Rare/New Old Stock) $5 - $9 (Module)

Parts List and Pin Mapping

This build assumes you are using an Arduino Uno R3 (or any ATmega328P-based board like the Nano) paired with a generic W5500 Ethernet Shield featuring the HanRun HR911105A integrated magjack.

Required Components

  • MCU: Arduino Uno R3 (Rev3) or compatible clone
  • Network Shield: W5500 Ethernet Shield (look for the W5500 chip explicitly printed on the PCB; avoid shields simply labeled "Ethernet Shield" without a version number, as they are often W5100s)
  • Cabling: CAT5e or CAT6 RJ45 patch cable
  • Power: 5V 2A DC power supply (barrel jack) to handle the MCU and the shield's LDO heat dissipation

SPI Pin Mapping Table

The W5500 communicates via the SPI bus. On the Uno, these map to specific digital pins, but on the Mega 2560, they are routed exclusively through the 2x3 ICSP header. The shield uses the ICSP header to maintain compatibility across both boards.

Signal Arduino Uno R3 Pin Arduino Mega 2560 Pin ICSP Header Pin
MOSI (Master Out Slave In) D11 D51 4
MISO (Master In Slave Out) D12 D50 1
SCK (Serial Clock) D13 D52 3
SS / CS (Ethernet Chip Select) D10 D53 (but use D10 for shield) N/A (Routed via D10)
SD Card CS (If applicable) D4 D4 N/A

Step-by-Step Wiring and Assembly

  1. Inspect the ICSP Header: Look at the 2x3 female ICSP header on the bottom of the W5500 shield. Ensure none of the metal leaf contacts are bent inward. This is the #1 cause of "shield not found" errors.
  2. Stack the Shield: Align the ICSP header with the male ICSP pins on the Arduino Uno. Press down firmly and evenly. Do not rock it side-to-side, or you will bend the Uno's header pins.
  3. Verify D10 and D4 Clearance: Ensure no stray jumper wires are plugged into Digital Pin 10 (Ethernet CS) or Digital Pin 4 (SD Card CS). The SPI bus will fail if these pins are driven by external sensors.
  4. Connect Network and Power: Plug the CAT6 cable into your router or switch. Connect the 5V power supply to the Uno's barrel jack. Do not rely solely on USB power; the W5500's onboard 3.3V LDO can draw significant current during TX bursts.
💡 Bench Tip: The SD Card SPI Conflict
Most W5500 shields include a micro-SD slot. Because the SD card and the Ethernet chip share the same SPI bus (MOSI, MISO, SCK), they must be isolated using their respective Chip Select (CS) pins. If you are not using the SD card, you must set Pin 4 to HIGH in your code, or the SD card's controller will corrupt the Ethernet SPI traffic.

Complete W5500 Web Server Code

The following code targets the Arduino Uno R3 with a generic W5500 shield. It uses the official Arduino Ethernet library. It includes explicit CS pin initialization, SD card deselection, DHCP timeout handling with a static IP fallback, and hardware detection.

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

// --- PIN DEFINITIONS ---
// Target Board: Arduino Uno R3 (ATmega328P)
#define ETHERNET_CS_PIN 10
#define SD_CS_PIN 4

// --- NETWORK CONFIGURATION ---
// Assign a unique MAC address. If using multiple boards, change the last byte.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress staticIP(192, 168, 1, 177);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

EthernetServer server(80);

void setup() {
  Serial.begin(115200);
  while (!Serial) { ; } // Wait for serial port (Leonardo/Micro only)

  // Deselect SD card to prevent SPI bus contention
  pinMode(SD_CS_PIN, OUTPUT);
  digitalWrite(SD_CS_PIN, HIGH);

  // Explicitly initialize W5500 Chip Select pin
  Ethernet.init(ETHERNET_CS_PIN);
  
  Serial.println("Initializing W5500 Ethernet...");

  // Attempt DHCP configuration with a 10-second timeout
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    Serial.println("Falling back to static IP...");
    Ethernet.begin(mac, staticIP, gateway, subnet);
  }

  // Check for physical hardware presence
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("ERROR: Ethernet shield was not found. Check ICSP header seating.");
    while (true) { delay(1); } // Halt execution
  }

  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("WARNING: Ethernet cable is not plugged in.");
  }

  server.begin();
  Serial.print("Web server started at IP: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("New client connected");
    String currentLine = "";
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        
        if (c == '\n') {
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();
            
            // HTML Payload
            client.println("<!DOCTYPE html><html>");
            client.println("<head><title>Arduino W5500 Server</title></head>");
            client.println("<body><h1>W5500 Web Server Active</h1>");
            client.print("<p>Uptime: ");
            client.print(millis() / 1000);
            client.println(" seconds</p></body></html>");
            
            break; // Break out of the while loop
          } else {
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
      }
    }
    client.stop();
    Serial.println("Client disconnected");
  }
}

Debugging: "Failed to configure Ethernet using DHCP"

If your serial monitor outputs the exact string Failed to configure Ethernet using DHCP, do not immediately assume the shield is dead. This error simply means the W5500 sent a DHCP Discover packet and received no Offer in return.

The first three things to check when it fails:

  1. ICSP Header Seating: Unplug power and press down firmly on the ICSP header. A loose MISO connection will allow the MCU to send DHCP requests but prevent it from reading the router's response.
  2. Switch Port Security: If you are plugged into a corporate or university network switch, port security often blocks unknown MAC addresses from pulling an IP. Plug the shield directly into a home router or a dumb unmanaged switch to isolate the issue.
  3. Cable and Link Lights: Check the HanRun magjack LEDs. The left LED (usually green) should be solid (Link), and the right LED (usually yellow) should flicker (Activity). If the green LED is off, your cable is bad or the router port is dead.

Ranked Causes for Persistent DHCP Failures

  • Cause 1 (60%): Router DHCP pool exhaustion or MAC filtering.
  • Cause 2 (25%): ICSP header not fully seated, breaking the SPI MISO line.
  • Cause 3 (10%): Logic level mismatch. Some ultra-cheap W5500 clones omit the 74LVC245 level shifter, causing 5V Uno signals to brown out the 3.3V W5500 chip during high-load SPI transactions.
  • Cause 4 (5%): Defective Ethernet cable (specifically a broken Pair 2 or 3 used for 100BASE-TX).

Extending and Simplifying the Build

How to Simplify: If your node is deployed in a static location (like a greenhouse monitor), strip the DHCP logic entirely. Hardcode a static IP outside your router's DHCP pool. This eliminates the 3-to-5 second DHCP negotiation delay on boot and removes a point of failure if your router reboots.

How to Extend: To add data logging, wire an I2C sensor (like a BME280) to the A4/A5 pins. Because I2C uses a completely different bus than SPI, it will not interfere with the W5500. If you need to log to the onboard SD card, use the SD.h library, but remember to wrap your SD operations in digitalWrite(SD_CS_PIN, LOW) and digitalWrite(SD_CS_PIN, HIGH) blocks, ensuring the Ethernet CS pin is held HIGH during the write.

Frequently Asked Questions

Can I use an Arduino Ethernet shield with an ESP32?

Yes, but it requires manual wiring. The ESP32 does not have the same physical ICSP header layout as the Uno. You must wire the W5500's MOSI, MISO, SCK, and CS pins directly to the ESP32's VSPI pins (typically GPIO 23, 19, 18, and 5). However, unless you specifically need hardwired reliability for industrial environments, using the ESP32's native WiFi or an ESP32 with an Ethernet MAC (like the WT32-ETH01) is far more efficient.

Why does my W5500 Arduino Ethernet shield get hot to the touch?

The W5500 chip itself runs cool, but generic shields use a cheap linear LDO regulator to step the Arduino's 5V down to the 3.3V required by the chip and the magjack. Dropping 1.7V at ~150mA generates noticeable heat. It is normal for the LDO to reach 50°C (122°F). If it is too hot to keep your finger on, or if you are running the shield in an enclosed enclosure, stick a small 14x14mm aluminum heatsink on the LDO and ensure adequate ventilation.

How do I access my Arduino Ethernet web server from outside my local network?

The traditional method is setting up Port Forwarding on your router (forwarding external port 8080 to your Arduino's internal IP on port 80) and using a DDNS service. However, exposing raw HTTP ports to the public internet is a massive security risk in 2026. A much safer architecture is to have the Arduino act as an MQTT client, publishing its data to a cloud broker (like AWS IoT or HiveMQ), and then viewing that data via a secure web dashboard. This keeps your Arduino behind the NAT firewall while still allowing remote access.