Documentation

W5500 SPI Ethernet Network Module for Arduino & ESP32 | ShillehTek Product Manual
Documentation / W5500 SPI Ethernet Network Module for Arduino & ESP32 | ShillehTek Product Manual

W5500 SPI Ethernet Network Module for Arduino & ESP32 | ShillehTek Product Manual

Overview

The W5500 module gives your microcontroller a wired Ethernet port — and with it, the reliability WiFi can't promise. The WIZnet W5500 chip is a "hardwired TCP/IP" controller: the entire TCP/IP stack (TCP, UDP, IPv4, ICMP, ARP, DHCP-capable sockets) runs in silicon, your microcontroller just talks to it over SPI. That means an Arduino Uno with 2KB of RAM can hold eight simultaneous network sockets, and your code never fights the radio-noise, reconnect, and latency gremlins of wireless.

The board carries the W5500, a magjack RJ45 with link/activity LEDs, a 3.3V regulator, and a 2x5 SPI header (plus the same signals on breakout rows). Wire four SPI lines and power, plug in any Ethernet cable to your router or switch, and DHCP hands you an IP address seconds later. 10/100 Mbps auto-negotiation, auto-MDIX on most boards, and support in every major ecosystem: the Arduino Ethernet library treats it as the default hardware, and CircuitPython/MicroPython drivers cover the Pi Pico world.

Reach for wired Ethernet where dropouts are unacceptable or WiFi can't go: home-automation hubs and MQTT brokers' clients, industrial monitoring, PoE-powered installs (with a PoE splitter), metal enclosures and basements that kill RF, and anything that must survive a router reboot unattended. It's also the easy path to networking for boards with no radio at all — like the standard Pico.

At a Glance

Controller
WIZnet W5500
Stack
Hardwired TCP/IP, 8 sockets
Speed
10/100 Mbps RJ45
Interface
SPI up to 80 MHz
Supply
5V or 3.3V pin
Logic Level
3.3V (5V-tolerant inputs)

Specifications

Parameter Value
Chipset WIZnet W5500 hardwired TCP/IP controller
Protocols in Hardware TCP, UDP, IPv4, ICMP, ARP, IGMP, PPPoE
Simultaneous Sockets 8 independent hardware sockets
Buffer Memory 32 KB internal TX/RX buffers
PHY 10BASE-T / 100BASE-TX, auto-negotiation
Host Interface SPI Mode 0/3, up to 80 MHz
Supply 5V pin (onboard regulator) or direct 3.3V pin
Current Draw ~130-180 mA active with link
SPI Header (2x5) 1 NC · 2 INT · 3 RST · 4 GND · 5 5V · 6 SCLK · 7 SCS · 8 MOSI · 9 MISO · 10 3.3V
Connector RJ45 magjack with link/activity LEDs
MAC Address Not pre-assigned — set one in code

Pinout Diagram

The 2x5 header carries everything: SCLK, SCS (chip select), MOSI, and MISO are the SPI bus; RST is an optional hardware reset; INT signals socket events if you want interrupt-driven code (most libraries poll instead and leave it unwired). Power enters on pin 5 (5V, through the onboard regulator) or pin 10 (regulated 3.3V directly) — use one, not both.

W5500 SPI Ethernet module pinout diagram showing the 2x5 SPI interface header with SCLK SCS MOSI MISO pins and RJ45 port

Wiring Guide

Arduino Wiring

W5500 Pin Arduino Pin Details
5V / GND 5V / GND Onboard regulator makes 3.3V
SCLK D13 SPI clock
MISO D12
MOSI D11
SCS D10 Ethernet.init(10) in code
Tip: The W5500's inputs are 5V-tolerant, so the Uno connects directly — no level shifter. If your board also hosts an SD card or other SPI device, give each its own CS pin and the bus is shared happily.

ESP32 Wiring

W5500 Pin ESP32 Pin Details
3.3V / GND 3V3 / GND Direct 3.3V feed (skip the 5V pin)
SCLK GPIO 18 VSPI
MISO GPIO 19
MOSI GPIO 23
SCS GPIO 5 Ethernet.init(5)
Note: An ESP32 with W5500 gets rock-solid wired networking and can keep WiFi as a fallback — handy for gateways that bridge wired sensors to wireless dashboards.

Raspberry Pi Pico Wiring

W5500 Pin Pico Pin Details
3.3V / GND 3V3(OUT) / GND
SCLK GP18 (SPI0 SCK)
MISO GP16 (SPI0 RX)
MOSI GP19 (SPI0 TX)
SCS GP17 Chip select
RST GP20 (optional) Hardware reset

Raspberry Pi (single-board) — Do You Need It?

A full Raspberry Pi already has native Ethernet, so this module isn't wired to a Pi 4/5 in practice. Where it shines in the Pi family is the microcontroller side — the Pico — or as a second isolated network path on unusual builds.

Scenario Recommendation
Raspberry Pi 4/5 project needs Ethernet Use the built-in port
Pico project needs networking This module + CircuitPython WIZNET5K (see Pico tab/code)
Pi Zero (no Ethernet) needs wired LAN A USB-Ethernet adapter is simpler than SPI

Code Examples

The Arduino/ESP32 sketches use the standard Ethernet library: one fetches a web page (DHCP client), one serves a live status page. The Pico examples use CircuitPython's WIZNET5K driver — install Adafruit's library bundle, or the equivalent MicroPython W5500 driver.

Arduino — DHCP + web fetch

w5500_webclient.ino
// W5500 Ethernet - Arduino Web Client (DHCP)
// SCLK->13, MISO->12, MOSI->11, SCS->10, 5V, GND
// Library: "Ethernet" (built into the IDE)

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x01 };  // pick any unique MAC
EthernetClient client;

void setup() {
  Serial.begin(115200);
  Ethernet.init(10);                       // CS pin

  Serial.println("Requesting IP via DHCP...");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("DHCP failed - check cable/router");
    while (1);
  }
  Serial.print("IP address: ");
  Serial.println(Ethernet.localIP());

  if (client.connect("example.com", 80)) {
    client.println("GET / HTTP/1.1");
    client.println("Host: example.com");
    client.println("Connection: close");
    client.println();
  }
}

void loop() {
  while (client.available()) {
    Serial.write(client.read());           // stream the response
  }
  if (!client.connected()) {
    client.stop();
    Serial.println("\n-- done --");
    while (1);
  }
}

ESP32 — Ethernet web server (Arduino IDE)

w5500_esp32_server.ino
// W5500 Ethernet - ESP32 Web Server
// SCLK->18, MISO->19, MOSI->23, SCS->5, 3.3V, GND

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x02 };
EthernetServer server(80);
unsigned long hits = 0;

void setup() {
  Serial.begin(115200);
  Ethernet.init(5);

  if (Ethernet.begin(mac) == 0) {
    Serial.println("DHCP failed");
    while (1) delay(10);
  }
  server.begin();
  Serial.print("Open http://");
  Serial.println(Ethernet.localIP());
}

void loop() {
  EthernetClient client = server.available();
  if (!client) return;

  // skip request headers
  while (client.connected() && client.available()) client.read();

  hits++;
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("Connection: close");
  client.println();
  client.println("<html><body style='font-family:sans-serif'>");
  client.println("<h1>ESP32 + W5500</h1>");
  client.print("<p>Wired and reliable. Page hits: ");
  client.print(hits);
  client.print(" | Uptime: ");
  client.print(millis() / 1000);
  client.println(" s</p></body></html>");
  delay(1);
  client.stop();
}

Raspberry Pi Pico (CircuitPython) — DHCP + fetch

w5500_pico_circuitpython.py
# W5500 Ethernet - Pico CircuitPython Example
# SCLK->GP18, MISO->GP16, MOSI->GP19, SCS->GP17, RST->GP20
# Libraries (from the Adafruit bundle, copy to /lib):
#   adafruit_wiznet5k, adafruit_requests, adafruit_connection_manager

import board
import busio
import digitalio
import adafruit_connection_manager
import adafruit_requests
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K

spi = busio.SPI(board.GP18, MOSI=board.GP19, MISO=board.GP16)
cs = digitalio.DigitalInOut(board.GP17)
rst = digitalio.DigitalInOut(board.GP20)

eth = WIZNET5K(spi, cs, reset=rst, is_dhcp=True)
print("IP address:", eth.pretty_ip(eth.ip_address))
print("Link up:", eth.link_status)

pool = adafruit_connection_manager.get_radio_socketpool(eth)
ssl = adafruit_connection_manager.get_radio_ssl_context(eth)
requests = adafruit_requests.Session(pool, ssl)

print("Fetching http://wifitest.adafruit.com/testwifi/index.html ...")
resp = requests.get("http://wifitest.adafruit.com/testwifi/index.html")
print("Response:", resp.text)
resp.close()

Raspberry Pi Pico — tiny status server (CircuitPython)

w5500_pico_server.py
# W5500 Ethernet - Pico CircuitPython web server
# Same wiring/libraries as the client example.

import time
import board, busio, digitalio
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
import adafruit_wiznet5k.adafruit_wiznet5k_socketpool as socketpool

spi = busio.SPI(board.GP18, MOSI=board.GP19, MISO=board.GP16)
cs = digitalio.DigitalInOut(board.GP17)
rst = digitalio.DigitalInOut(board.GP20)

eth = WIZNET5K(spi, cs, reset=rst, is_dhcp=True)
print("Serving on http://{}".format(eth.pretty_ip(eth.ip_address)))

pool = socketpool.SocketPool(eth)
server = pool.socket()
server.bind((eth.pretty_ip(eth.ip_address), 80))
server.listen(1)

hits = 0
while True:
    conn, addr = server.accept()
    hits += 1
    conn.recv(1024)                     # discard request
    body = ("<html><body><h1>Pico + W5500</h1>"
            "<p>Hits: {} | Uptime: {:.0f} s</p>"
            "</body></html>").format(hits, time.monotonic())
    conn.send(b"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"
              + body.encode())
    conn.close()

Frequently Asked Questions

DHCP fails every time. What's the checklist?
Confirm the link LED on the RJ45 lights when the cable is plugged into a live switch port (no light = cable/port/power problem). Verify CS matches Ethernet.init() and the SPI pins match your board's hardware SPI. Give the module solid power — it wants ~150 mA, and long thin jumpers on the 3.3V pin cause exactly this symptom. Finally, some routers take a few seconds: retry Ethernet.begin() once before giving up.
Why do I have to invent a MAC address?
The W5500 ships without a factory-burned MAC, so your sketch supplies one. Any locally-administered address works (set the second-lowest bit of the first byte — 0xDE 0xAD... in the examples qualifies). The only rule: keep it unique on your LAN. Running two modules? Change the last byte on the second one, or the switch will lose its mind.
W5500 vs the older W5100 shield — what changed?
The W5500 is the modern replacement: 8 sockets instead of 4, 32KB of buffer instead of 16KB, a much faster SPI interface, lower power, and a smaller footprint. The Arduino Ethernet library auto-detects both, so tutorials written for W5100 shields run unchanged. There's no reason to choose a W5100 today.
Can it do HTTPS / TLS?
The chip handles TCP; encryption is your microcontroller's job. On an Uno, that's a hard no — use HTTP to a local broker/bridge, or an ESP32 which has the muscle for TLS in software (the SSLClient library works over W5500, and CircuitPython's connection manager on the Pico supports TLS sessions). A common pattern: W5500 node speaks plain MQTT/HTTP to a LAN server, which handles the secure internet leg.
Does it support PoE so I can run one cable?
Not natively — the magjack doesn't extract power. The practical route is a passive PoE splitter (or 802.3af splitter) at the device end: Ethernet data continues to the W5500's RJ45 while the splitter's 5V output feeds your board. That combination is superb for outdoor sensors and camera-adjacent installs — one cable, no batteries, no WiFi.
How fast is it really through a microcontroller?
The PHY negotiates 100 Mbps, but throughput is set by your MCU's SPI speed and processing: an Uno manages a few hundred KB/s, an ESP32 or Pico several MB/s bursts. For sensor telemetry, MQTT, web dashboards, and firmware-sized downloads that's far more than needed. It is not a NAS — it's a bulletproof network pipe for control traffic.
Can I use it and an SD card (or other SPI devices) together?
Yes — SPI is a shared bus. All devices share SCLK/MOSI/MISO; each gets its own chip-select pin, and the libraries take care of asserting the right CS. The classic Arduino Ethernet+SD shield works exactly this way (Ethernet CS=10, SD CS=4). Just initialize each library with its own CS and never wire two devices to one select line.

Related Tutorials