If you are pairing an Arduino and Ethernet shield for a hardwired IoT node, data logger, or local web server, the first rule of the bench in 2026 is to ditch the ancient W5100 chips. The W5100 runs hot, supports only four hardware sockets, and struggles with modern network traffic. The current standard is the Wiznet W5500, which offloads TCP/IP processing in hardware, supports eight simultaneous sockets, and runs cool under continuous load.

This guide provides the exact pin mapping, a production-ready HTTP server sketch with DHCP-to-Static fallback, and a debugging matrix for the most common SPI and network failures.

Hardware Spec Sheet & Parts List

Target Board Variant: This code and wiring guide specifically targets the Arduino Uno R3 (ATmega328P) or Uno R4 Minima. If you are using a Mega 2560, the SPI pins are routed differently (50-52), and the ICSP header seating changes.
Component Exact Variant / Model Notes & Bench Reality
Microcontroller Arduino Uno R3 (or R4 Minima) R3 is 5V logic; W5500 is 3.3V but most shields include level shifters.
Ethernet Shield Wiznet W5500 Shield (ioShield or Seeed Studio) Ensure it says W5500 on the main IC. Avoid unmarked clone boards with counterfeit silicon.
Power Supply 5V 2A DC Barrel Jack Adapter USB power (500mA) is insufficient when the W5500 is transmitting and the SD card is writing.
Cabling CAT5e or CAT6 Patch Cable Straight-through for router/switch connections. Auto-MDIX handles crossover on modern switches.

Pin Mapping and Physical Wiring

The W5500 communicates via the SPI bus. On the Uno R3, the SPI pins are broken out on both the digital header and the 2x3 ICSP (In-Circuit Serial Programming) header. High-quality Ethernet shields route the W5500 SPI lines directly to the ICSP header for cross-compatibility with the Mega, but they still require a dedicated Chip Select (CS) pin on the digital header.

W5500 Function Arduino Uno R3 Pin Configuration Requirement
MOSI (Master Out Slave In) Pin 11 (or ICSP 4) Managed automatically by SPI.h
MISO (Master In Slave Out) Pin 12 (or ICSP 1) Managed automatically by SPI.h
SCK (Serial Clock) Pin 13 (or ICSP 3) Managed automatically by SPI.h
W5500 CS (Chip Select) Pin 10 Must be set as OUTPUT and held HIGH when not in use.
SD Card CS (if populated) Pin 4 Must be set as OUTPUT and held HIGH to prevent SD SPI collisions.
W5500 Hardware Reset Pin 9 (on some shields) Optional; library handles software reset if unconnected.
Bench Tip: The most common physical failure is an unseated ICSP header. If your shield stacks loosely, the 2x3 ICSP pins might not make contact. Solder a set of stacking headers with long pins, or apply a small piece of Kapton tape to the back of the shield to prevent the USB port casing from shorting against the shield's bottom solder joints.

Compilable HTTP Server Code (W5500)

This sketch uses the official Arduino Ethernet library (ensure you have version 2.0.0 or higher installed via Library Manager, as v1.x lacks native W5500 support). It includes a critical DHCP-to-Static IP fallback mechanism and proper SPI bus management for the onboard SD card slot.

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

// --- HARDWARE PIN DEFINITIONS ---
#define W5500_CS_PIN 10
#define SD_CS_PIN    4
#define RESET_PIN    9  // Set to -1 if your shield lacks a hardware reset pin

// --- NETWORK CONFIGURATION ---
// MAC Address (Use a unique locally administered MAC, e.g., starting with 0x02)
byte mac[] = { 0x02, 0xDE, 0xAD, 0xBE, 0xEF, 0x01 };

// Fallback Static IP (Used if DHCP fails)
IPAddress staticIP(192, 168, 1, 177);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

// Initialize the Ethernet server library on port 80
EthernetServer server(80);

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

  // --- CRITICAL SPI BUS MANAGEMENT ---
  // Disable SD card SPI to prevent bus collisions with the W5500
  pinMode(SD_CS_PIN, OUTPUT);
  digitalWrite(SD_CS_PIN, HIGH);
  
  // Disable W5500 SPI initially
  pinMode(W5500_CS_PIN, OUTPUT);
  digitalWrite(W5500_CS_PIN, HIGH);

  // Hardware reset sequence (if supported by shield)
  if (RESET_PIN > 0) {
    pinMode(RESET_PIN, OUTPUT);
    digitalWrite(RESET_PIN, LOW);
    delay(50);
    digitalWrite(RESET_PIN, HIGH);
    delay(200);
  }

  Serial.println("Initializing W5500 Ethernet Shield...");
  
  // Start Ethernet with DHCP (Timeout is handled internally, but we check return)
  if (Ethernet.begin(mac) == 0) {
    Serial.println("[ERROR] Failed to configure Ethernet using DHCP.");
    Serial.println("[INFO] Falling back to Static IP configuration...");
    
    // Fallback to static IP
    Ethernet.begin(mac, staticIP, gateway, gateway, subnet);
  }
  
  // Check for hardware presence
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("[FATAL] Ethernet shield was not found. Check SPI wiring and CS pins.");
    while (true) { delay(1); } // Halt execution
  }
  
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("[WARNING] Ethernet cable is not connected.");
  }

  // Start the web server
  server.begin();
  Serial.print("Server online at IP: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // Listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("New client connected.");
    boolean currentLineIsBlank = true;
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        
        // If end of line (newline character) and the line is blank,
        // the HTTP request has ended, so we can send a reply.
        if (c == '\n' && currentLineIsBlank) {
          // Send standard HTTP headers
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.println();
          
          // Send HTML payload
          client.println("<!DOCTYPE HTML><html>");
          client.println("<h1>Arduino W5500 Web Server</h1>");
          client.print("<p>Uptime (ms): ");
          client.print(millis());
          client.println("</p></html>");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1); // Give the web browser time to receive data
    client.stop();
    Serial.println("Client disconnected.");
  }
}

Debugging: First 3 Things to Check When It Fails

When your serial monitor spits out an error, do not immediately rewrite your code. 90% of Ethernet shield failures on the bench are physical or network-layer issues. Here is the exact decision path for the two most common errors.

Error 1: "Ethernet shield was not found."

This exact string triggers when Ethernet.hardwareStatus() == EthernetNoHardware. The ATmega328P cannot see the W5500 chip over the SPI bus.

  1. Check the Library Version: Open the Library Manager. If you are using the default Arduino Ethernet library v1.0.x, it only supports the W5100. You must update to v2.0.0+ to enable W5500 auto-detection.
  2. Check the ICSP Header Seating: Unplug the shield and inspect the 2x3 plastic ICSP header. If it is pushed up and not making flush contact with the Uno's male pins, the SPI clock and data lines are floating.
  3. Verify the CS Pin: Some third-party "W5500 Mini" modules use Pin 8 or Pin 9 for Chip Select instead of the standard Pin 10. Check the silkscreen on your specific PCB and update #define W5500_CS_PIN accordingly.

Error 2: "Failed to configure Ethernet using DHCP."

The chip is detected, but the router refused to hand out an IP address.

  1. MAC Address Collision or Filtering: Enterprise networks and some modern mesh routers (like Eero or Orbi) block devices with unrecognized or duplicated MAC addresses. Ensure your MAC array starts with 0x02 (Locally Administered) and is unique on your LAN.
  2. VLAN or Switch Port Isolation: If you are plugged into a managed switch, ensure the port is configured as an Access port on the correct VLAN, and that 802.1X port security isn't blocking the unauthenticated MAC.
  3. Power Brownout: The W5500 draws up to 150mA during heavy TX bursts. If powered solely via a weak laptop USB port, the voltage drops below 4.5V, causing the W5500 internal PLL to lose lock and drop DHCP packets. Use a dedicated 5V 2A wall adapter.

Extending and Simplifying the Build

To Simplify: If this node is going into a permanent installation (like a greenhouse monitor or a basement sump pump alert), strip out the DHCP logic entirely. DHCP adds a 3-5 second delay to boot time and introduces a point of failure if the router reboots. Hardcode the Ethernet.begin(mac, ip, dns, gateway, subnet) function with a static IP outside your router's DHCP pool.

To Extend: The W5500's 8-socket architecture allows you to run an HTTP server and an MQTT client simultaneously. To add MQTT, include the PubSubClient library. Initialize it with your EthernetClient instance. Just remember that each active connection consumes one hardware socket; if you try to open a 9th concurrent connection, the W5500 will silently drop it or throw a socket allocation error.

Frequently Asked Questions

Can I use an Arduino and Ethernet shield without a router?

Yes, but you cannot use DHCP. You must connect the Arduino directly to your PC's Ethernet port (or via a simple unmanaged switch) and assign a Static IP to both the Arduino and your PC's Ethernet adapter. For example, set the Arduino to 192.168.1.10 and your PC to 192.168.1.11 with a subnet mask of 255.255.255.0. Modern PC NICs feature Auto-MDIX, so a standard patch cable will work without needing a physical crossover cable.

Why is my Arduino and Ethernet shield getting hot?

If your shield is too hot to touch, you are likely using an older W5100 shield. The W5100 is fabricated on an older process node and dissipates significant heat as waste, often requiring a small heatsink on the IC. The W5500 runs vastly cooler. Additionally, check your input voltage; if you feed 12V into the Arduino's barrel jack while using an Ethernet shield, the onboard 5V linear regulator (NCP1117) has to burn off 7V as heat, which can trigger thermal shutdown. Always power Ethernet shield setups via 5V directly into the 5V pin or USB, bypassing the linear regulator.

How do I use the SD card and Arduino Ethernet shield at the same time?

Both the W5500 and the SD card slot share the same hardware SPI bus (Pins 11, 12, 13). To use them simultaneously, you must manage the Chip Select (CS) pins manually. Before initializing the SD card via SD.begin(4), ensure Pin 10 (W5500 CS) is set HIGH. Before making an Ethernet call, ensure Pin 4 (SD CS) is set HIGH. Never leave both CS pins LOW at the same time, or the MISO line will experience bus contention, corrupting your data and potentially damaging the output buffers on the ICs.

References: Wiznet W5500 Official Documentation, Arduino Ethernet Library Reference.