Ein ESP32-W5500-MQTT-Knoten ersetzt das WLAN durch ein Netzwerkkabel, und das ist in einem Metallschaltschrank oder in der Fertigungshalle oft der Unterschied zwischen „funktioniert meistens" und „funktioniert einfach". In diesem Tutorial verbinden Sie einen ESP32 über ein W5500-SPI-Modul oder über einen LAN8720-PHY auf Boards wie dem WT32-ETH01 mit kabelgebundenem Ethernet, behandeln Link-up- und Link-down-Events und veröffentlichen Maschinendaten an broker.connectmq.com. Der MQTT-Code ändert sich kaum; die interessante Arbeit steckt in der Netzwerkschicht.
Warum kabelgebundenes Ethernet für ESP32 MQTT
WLAN ist bequem, in Industrieumgebungen aber anfällig. Stahlgehäuse schirmen das Signal ab, Motoren und Antriebe erzeugen Störungen, IT-Abteilungen schränken drahtlose Clients ein, und Access Points werden ausgetauscht oder umkonfiguriert, ohne dass das Automatisierungsteam davon erfährt. Ethernet beseitigt die meisten dieser Variablen:
| Faktor | WLAN | Kabelgebundenes Ethernet |
|---|---|---|
| Im Metallschaltschrank | Schwaches oder kein Signal | Unbeeinflusst |
| Elektrische Störungen durch Antriebe | Können die Verbindung stören | Mit geschirmtem Kabel meist robust |
| Zugangsdaten auf dem Gerät | SSID und Passwort nötig | Keine für die Verbindungsschicht |
| Gleichmäßige Latenz | Schwankt mit Last und Störungen | Stabil |
| Stromversorgung | Separates Netzteil | Optional PoE mit passendem Modul |
| Mobilität | Ja | Nein |
Der Preis dafür sind Verkabelung und ein etwas aufwendigerer Hardwareaufbau. Für einen fest installierten Knoten, der eine Maschine, einen Zähler oder ein Modbus-RS-485-Gerät ausliest und an MQTT weiterleitet, ist kabelgebundenes Ethernet meist die richtige Wahl.
W5500 oder LAN8720?
Es gibt zwei gängige Wege, einem ESP32 einen Ethernet-Port zu geben.
| W5500 | LAN8720 | |
|---|---|---|
| Schnittstelle | SPI, funktioniert mit jeder ESP32-Variante | RMII, benötigt den internen EMAC des originalen ESP32 |
| Belegte Pins | 4 SPI-Pins plus Interrupt und Reset | Etwa 10 feste Pins |
| Typische Hardware | Kleines W5500-Modul, viele S3-Ethernet-Boards | WT32-ETH01, Olimex ESP32-POE, LilyGO T-ETH |
| Durchsatz | Mehr als genug für MQTT | Höher, ebenfalls mehr als MQTT braucht |
| Unterstützung in Arduino-ESP32 3.x | In ETH.h integriert |
In ETH.h integriert |
Beide werden von der ETH-Bibliothek in Arduino-ESP32 3.x nativ unterstützt, und beide speisen denselben lwIP-Netzwerkstack. Das ist der entscheidende Punkt: Sobald der Link eine IP-Adresse hat, funktionieren NetworkClient, PubSubClient, DNS und TLS genauso wie über WLAN. Wenn Sie noch Core 2.x verwenden, aktualisieren Sie; die W5500-Unterstützung in ETH.h kam mit 3.x, und die älteren Workaround-Bibliotheken werden nicht mehr benötigt. Die Arduino-ESP32-Dokumentation und die ETH-Beispiele, die mit dem Core ausgeliefert werden, listen die unterstützten PHYs auf.
Ein W5500-Modul verdrahten
| W5500-Pin | ESP32-Pin | Hinweis |
|---|---|---|
| MOSI | GPIO 23 | SPI-Daten aus |
| MISO | GPIO 19 | SPI-Daten ein |
| SCLK | GPIO 18 | SPI-Takt |
| SCS / CS | GPIO 5 | Chip Select |
| INT | GPIO 4 | Interrupt, empfohlen |
| RST | GPIO 14 | Reset |
| 3.3V | 3V3 | Manche Module haben einen 5-V-Eingang mit Regler |
| GND | GND | Gemeinsame Masse |
Halten Sie die SPI-Leitungen kurz, auf einem Steckbrett unter etwa 10 cm. Der W5500 kann beim Senden spürbar Strom ziehen, versorgen Sie ihn daher über eine stabile 3,3-V-Schiene statt über den schwachen Regler eines USB-Seriell-Boards. Die meisten Link-Probleme auf dem Steckbrett entpuppen sich als Stromversorgungs- oder Verdrahtungsfehler, nicht als Softwareproblem.
Der ESP32-W5500-MQTT-Sketch
Dieser Sketch verwendet Arduino-ESP32 3.x und PubSubClient. Er verfolgt den Ethernet-Zustand über Events, verbindet MQTT nur, wenn der Link eine IP-Adresse hat, und veröffentlicht alle fünf Sekunden Telemetrie einschließlich der Link-Geschwindigkeit.
#include <ETH.h>
#include <SPI.h>
#include <NetworkClient.h>
#include <PubSubClient.h>
// W5500-Pins
#define ETH_PHY_TYPE ETH_PHY_W5500
#define ETH_PHY_ADDR 1
#define ETH_PHY_CS 5
#define ETH_PHY_IRQ 4
#define ETH_PHY_RST 14
#define ETH_SPI_SCK 18
#define ETH_SPI_MISO 19
#define ETH_SPI_MOSI 23
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* CLIENT_ID = "eth-node-6b2d90";
const char* BASE = "connectmq/demo/eth-node-6b2d90";
NetworkClient net;
PubSubClient mqtt(net);
volatile bool ethReady = false;
unsigned long lastAttempt = 0, lastPublish = 0;
void onNetworkEvent(arduino_event_id_t event) {
switch (event) {
case ARDUINO_EVENT_ETH_START:
ETH.setHostname("eth-node-6b2d90");
break;
case ARDUINO_EVENT_ETH_CONNECTED:
Serial.println("Ethernet link up");
break;
case ARDUINO_EVENT_ETH_GOT_IP:
Serial.printf("IP %s, %u Mbps, %s duplex\n", ETH.localIP().toString().c_str(),
ETH.linkSpeed(), ETH.fullDuplex() ? "full" : "half");
ethReady = true;
break;
case ARDUINO_EVENT_ETH_LOST_IP:
case ARDUINO_EVENT_ETH_DISCONNECTED:
Serial.println("Ethernet link down");
ethReady = false;
break;
case ARDUINO_EVENT_ETH_STOP:
ethReady = false;
break;
default:
break;
}
}
void onMessage(char* topic, byte* payload, unsigned int length) {
Serial.printf("Command %s: %.*s\n", topic, (int)length, (const char*)payload);
}
bool connectMqtt() {
String status = String(BASE) + "/status";
if (!mqtt.connect(CLIENT_ID, nullptr, nullptr, status.c_str(), 1, true, "offline")) {
Serial.printf("MQTT failed, state=%d\n", mqtt.state());
return false;
}
mqtt.publish(status.c_str(), "online", true);
mqtt.subscribe((String(BASE) + "/cmd/#").c_str(), 1);
Serial.println("MQTT connected over Ethernet");
return true;
}
void setup() {
Serial.begin(115200);
Network.onEvent(onNetworkEvent);
SPI.begin(ETH_SPI_SCK, ETH_SPI_MISO, ETH_SPI_MOSI);
if (!ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, SPI)) {
Serial.println("W5500 not detected, check wiring");
}
// Optionale statische IP für Netzwerke ohne DHCP:
// ETH.config(IPAddress(192,168,10,50), IPAddress(192,168,10,1),
// IPAddress(255,255,255,0), IPAddress(192,168,10,1));
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setCallback(onMessage);
mqtt.setKeepAlive(30);
mqtt.setSocketTimeout(5);
}
void loop() {
if (!ethReady) {
if (mqtt.connected()) mqtt.disconnect();
return;
}
if (!mqtt.connected()) {
if (millis() - lastAttempt > 5000) { lastAttempt = millis(); connectMqtt(); }
return;
}
mqtt.loop();
if (millis() - lastPublish > 5000) {
lastPublish = millis();
char json[128];
snprintf(json, sizeof(json), "{\"uptime\":%lu,\"link\":%u,\"heap\":%u}",
millis() / 1000, ETH.linkSpeed(), ESP.getFreeHeap());
mqtt.publish((String(BASE) + "/telemetry").c_str(), json);
}
}
Stattdessen ein LAN8720-Board verwenden
Auf einem WT32-ETH01 oder einem ähnlichen LAN8720-Board entfernen Sie die SPI-Zeilen und die W5500-Defines und starten Ethernet mit den RMII-Parametern. Für das WT32-ETH01 sind die üblichen Werte:
// Typ, PHY-Adresse, MDC, MDIO, Power-Pin, Taktmodus
ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN);
Andere Boards unterscheiden sich in PHY-Adresse, Power-Pin und Taktmodus, prüfen Sie daher den Schaltplan oder das Herstellerbeispiel des Boards. Alles nach ETH.begin(), einschließlich der Events und des MQTT-Codes, bleibt identisch.
Den Knoten testen
Stecken Sie das Kabel ein, öffnen Sie den seriellen Monitor und achten Sie auf die Zeile IP ... Mbps, gefolgt von MQTT connected over Ethernet. Abonnieren Sie dann von einem beliebigen Rechner aus:
mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-6b2d90 -v -t "connectmq/demo/eth-node-6b2d90/#"
Ziehen Sie nun das Kabel für zwanzig Sekunden ab und stecken Sie es wieder ein. Das serielle Log sollte link down zeigen, keine MQTT-Verbindungsversuche, solange das Kabel fehlt, dann link up, ein neues IP-Event und einen Reconnect. Beim Subscriber sehen Sie nach Ablauf des Keep-Alive status offline aus dem Last Will, gefolgt von online nach der Wiederherstellung. Dieser „Kabelzieh-Test" lohnt sich bei jedem neuen Hardwaredesign; er deckt Stromversorgungs- und PHY-Probleme auf, die ein Labortest mit stabilem Link nie zeigt.
Der öffentliche MQTT-Broker eignet sich für diese Übung, seine Daten sind aber weltweit lesbar. Er ist für Tests und Prototypen gedacht; Maschinendaten aus der Produktion gehören hinter private Zugangsdaten.
Maschinendaten für MQTT aufbereiten
Die Telemetrie im Sketch ist bewusst minimal. An einer echten Maschine sollten Sie früh festlegen, was in jede Nachricht kommt und wie oft. Einige Regeln, die sich in der Praxis bewähren:
- Schnelle und langsame Daten trennen. Zähler, Temperaturen und Zustände, die sich jede Sekunde ändern, gehören in festem Intervall auf ein
telemetry-Topic. Konfiguration, Firmware-Version und Seriennummern gehören auf eininfo-Topic, das nach jedem Connect einmal retained veröffentlicht wird. - Zustände bei Änderung veröffentlichen. Ein Maschinenzustand wie
RUNNING,IDLEoderFAULTist als retained message, die nur bei einer Änderung veröffentlicht wird, nützlicher als ein Wert, der alle fünf Sekunden wiederholt wird. - Einheiten und Zeitstempel mitsenden.
{"spindleTempC":41.2,"ts":1760600000}beschreibt sich selbst; ein nacktes41.2nicht. - Payloads klein halten. Kabelgebundenes Ethernet hat reichlich Bandbreite, aber der Broker, Ihre Dashboards und jede nachgelagerte Datenbank zahlen für ausschweifende Nachrichten.
Wenn Sie in einen ConnectMQ-Broker veröffentlichen, machen diese Konventionen auch den Live-Topic-Explorer bei der Inbetriebnahme deutlich übersichtlicher, weil jede Maschine als aufgeräumter Zweig mit einer Handvoll aussagekräftiger Topics erscheint.
Checkliste für den industriellen Einsatz
- Ausgehende Firewall-Regeln. Werksnetze blockieren oft standardmäßig alles. Beantragen Sie ausgehendes TCP 8883 zu Ihrem Broker-Host; eingehende Regeln brauchen Sie nicht, weil der ESP32 die Verbindung aufbaut.
- TLS auf 8883 verwenden.
NetworkClientSecurefunktioniert über Ethernet genauso wie über WLAN; folgen Sie ESP32 MQTT SSL mit WiFiClientSecure und tauschen Sie den Klassennamen aus. - Statische IP oder DHCP-Reservierung. Das Betriebsteam will das Gerät finden können. Eine DHCP-Reservierung ist meist einfacher zu verwalten als eine fest codierte Adresse.
- NTP für Zeitstempel. Industrienetze blockieren unter Umständen öffentliches NTP; verwenden Sie den Zeitserver des Werks.
- Watchdog. Kombinieren Sie das ereignisgesteuerte Design mit dem Backoff aus ESP32-MQTT-Reconnect-Logik und einem Hardware-Watchdog.
- Topic-Struktur. Verwenden Sie von Anfang an eine Hierarchie im ISA-95-Stil wie
site/area/line/cell/device/telemetry; sie skaliert von einem Knoten bis zum ganzen Werk und bildet die Grundlage eines Unified Namespace (UNS). - Stromversorgung und Erdung. Verwenden Sie Hutschienennetzteile, geschirmte Kabel in der Nähe von Antrieben, und erwägen Sie PoE-Module, um eine separate Stromleitung einzusparen.
Rückfallebene: Ethernet mit Mobilfunk-Backup
Für abgelegene Standorte kombinieren manche Designs Ethernet mit einem Mobilfunkmodem als Backup. Die MQTT-Schicht bleibt gleich; die Firmware wechselt den Client, den sie an PubSubClient übergibt. Die Mobilfunkseite zeigt der Leitfaden ESP32 mit SIM7600 4G LTE MQTT.
Vom einzelnen Knoten zum ganzen Werk
Sobald einige Knoten veröffentlichen, wird der Broker zur gemeinsamen Infrastruktur des Werks und zum Kern des UNS. Die ISA-95-Gerätehierarchie (Enterprise → Site → Area → Line → Cell) wird dabei zur Topic-Struktur auf dem Broker, etwa acme/werk-stuttgart/montage/linie-1/zelle-3/temperatur. So finden MES, SCADA, Energiemonitoring und OEE-Auswertungen jeden Datenpunkt an einer vorhersehbaren Stelle, statt Punkt-zu-Punkt-Schnittstellen zu jedem Knoten zu pflegen. Wie Sparkplug B in dieses Bild passt, erklärt der Beitrag zu Sparkplug B und Unified Namespace. Ein verwalteter MQTT-Broker erspart Ihnen, einen Server im OT-Netz zu betreiben und zu patchen. ConnectMQ erkennt ISA-95- und UNS-Topic-Strukturen automatisch, sodass die Geräteansicht des Portals Ihre Ethernet-Knoten nach Standort, Bereich und Linie gruppiert, wenn Ihre Topics dieser Struktur folgen, und Schwellenwert-Alarmregeln einen Wert melden können, der seinen normalen Bereich verlässt. Ein MQTT-Broker in der Cloud ermöglicht es außerdem Engineering und Fernsupport, dieselben Live-Daten ohne VPN-Zugang ins Werk zu sehen. Den vollständigen ESP32-Lernpfad finden Sie im ESP32-IoT-Tutorial.
Starten Sie mit ConnectMQ
Erstellen Sie einen kostenlosen Serverless Broker unter app.connectmq.com, ohne Kreditkarte. Geben Sie jedem Ethernet-Knoten eigene Zugangsdaten und sehen Sie Ihre Maschinendaten innerhalb von Minuten im Live-Topic-Explorer.
Häufig gestellte Fragen
Funktioniert PubSubClient über Ethernet auf dem ESP32?
Ja. PubSubClient akzeptiert jeden Arduino-Client, und unter Arduino-ESP32 3.x funktioniert NetworkClient über denselben Netzwerkstack sowohl mit WLAN als auch mit Ethernet.
Kann ich einen W5500 mit einem ESP32-S3 oder ESP32-C3 verwenden?
Ja. Der W5500 wird über SPI angebunden und funktioniert daher auf jeder ESP32-Variante mit freien SPI-Pins. Der LAN8720 benötigt den internen EMAC, den unter diesen nur der originale ESP32 besitzt.
Brauche ich die Arduino-Ethernet-Bibliothek für einen W5500?
Unter Arduino-ESP32 3.x nicht. Die integrierte ETH-Bibliothek unterstützt den W5500 direkt und ist in lwIP eingebunden, sodass sich DNS, TLS und NetworkClient wie im WLAN verhalten.
Kann der ESP32 WLAN und Ethernet gleichzeitig nutzen?
Ja, beide Schnittstellen können aktiv sein. Stellen Sie sicher, dass Ihre Firmware weiß, welche die MQTT-Verbindung trägt, und Events von beiden verarbeitet.



