Un nœud ESP32 W5500 MQTT remplace le Wi-Fi par un câble réseau, ce qui fait souvent la différence entre « ça marche la plupart du temps » et « ça marche, point » dans une armoire électrique métallique ou dans un atelier. Dans ce tutoriel, vous allez relier un ESP32 à l'Ethernet filaire avec un module SPI W5500, ou avec un PHY LAN8720 sur des cartes comme la WT32-ETH01, gérer les événements de montée et de perte du lien, et publier des données machine sur broker.connectmq.com. Le code MQTT change à peine ; le travail intéressant se situe dans la couche réseau.
Pourquoi l'Ethernet filaire pour ESP32 MQTT
Le Wi-Fi est pratique mais fragile en environnement industriel. Les coffrets en acier font écran au signal, les moteurs et variateurs génèrent du bruit, les services informatiques restreignent les clients sans fil, et les points d'accès sont remplacés ou reconfigurés sans que personne ne prévienne l'équipe automatisme. L'Ethernet élimine la plupart de ces variables :
| Facteur | Wi-Fi | Ethernet filaire |
|---|---|---|
| Dans une armoire métallique | Signal faible ou absent | Aucun effet |
| Bruit électrique des variateurs | Peut perturber le lien | Généralement robuste avec un câble blindé |
| Identifiants sur l'appareil | SSID et mot de passe nécessaires | Aucun pour la couche liaison |
| Régularité de la latence | Varie selon la charge et les interférences | Stable |
| Alimentation | Alimentation séparée | PoE en option avec un module adapté |
| Mobilité | Oui | Non |
La contrepartie, c'est le câblage et une configuration matérielle un peu plus complexe. Pour un nœud fixe qui lit une machine, un compteur ou un équipement Modbus RS-485 et le relaie vers MQTT, l'Ethernet filaire est généralement le bon choix.
W5500 ou LAN8720 ?
Il existe deux façons courantes de doter un ESP32 d'un port Ethernet.
| W5500 | LAN8720 | |
|---|---|---|
| Interface | SPI, fonctionne avec toutes les variantes d'ESP32 | RMII, nécessite l'EMAC interne de l'ESP32 d'origine |
| Broches utilisées | 4 broches SPI plus interruption et reset | Environ 10 broches fixes |
| Matériel typique | Petit module W5500, nombreuses cartes Ethernet S3 | WT32-ETH01, Olimex ESP32-POE, LilyGO T-ETH |
| Débit | Largement suffisant pour MQTT | Plus élevé, également plus que ce dont MQTT a besoin |
| Prise en charge dans Arduino-ESP32 3.x | Intégré à ETH.h |
Intégré à ETH.h |
Les deux sont pris en charge nativement par la bibliothèque ETH d'Arduino-ESP32 3.x, et tous deux alimentent la même pile réseau lwIP. C'est le point essentiel : dès que le lien dispose d'une adresse IP, NetworkClient, PubSubClient, le DNS et le TLS fonctionnent exactement comme en Wi-Fi. Si vous êtes sur le core 2.x, mettez-le à jour ; la prise en charge du W5500 dans ETH.h est arrivée avec la 3.x, et les anciennes bibliothèques de contournement ne sont plus nécessaires. La documentation Arduino-ESP32 et les exemples ETH fournis avec le core listent les PHY pris en charge.
Câbler un module W5500
| Broche W5500 | Broche ESP32 | Remarque |
|---|---|---|
| MOSI | GPIO 23 | Sortie de données SPI |
| MISO | GPIO 19 | Entrée de données SPI |
| SCLK | GPIO 18 | Horloge SPI |
| SCS / CS | GPIO 5 | Chip select |
| INT | GPIO 4 | Interruption, recommandée |
| RST | GPIO 14 | Reset |
| 3.3V | 3V3 | Certains modules ont une entrée 5 V avec régulateur |
| GND | GND | Masse commune |
Gardez des fils SPI courts, moins d'environ 10 cm sur une breadboard. Le W5500 peut tirer un courant notable pendant l'émission : alimentez-le donc depuis un rail 3,3 V solide plutôt que depuis le régulateur faiblard d'une carte USB-série. La plupart des problèmes de lien sur breadboard viennent finalement de l'alimentation ou du câblage, pas du logiciel.
Le sketch ESP32 W5500 MQTT
Ce sketch utilise Arduino-ESP32 3.x et PubSubClient. Il suit l'état de l'Ethernet via les événements, ne connecte MQTT que lorsque le lien a une adresse IP, et publie toutes les cinq secondes une télémétrie qui inclut la vitesse du lien.
#include <ETH.h>
#include <SPI.h>
#include <NetworkClient.h>
#include <PubSubClient.h>
// Broches du W5500
#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");
}
// IP statique optionnelle pour les réseaux sans 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);
}
}
Utiliser plutôt une carte LAN8720
Sur une WT32-ETH01 ou une carte LAN8720 similaire, supprimez les lignes SPI et les defines du W5500, et démarrez l'Ethernet avec les paramètres RMII. Pour la WT32-ETH01, les valeurs habituelles sont :
// type, adresse PHY, MDC, MDIO, broche d'alimentation, mode d'horloge
ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN);
D'autres cartes diffèrent par l'adresse PHY, la broche d'alimentation et le mode d'horloge : consultez donc le schéma de la carte ou l'exemple du fabricant. Tout ce qui suit ETH.begin(), y compris les événements et le code MQTT, reste identique.
Tester le nœud
Branchez le câble, ouvrez le moniteur série et cherchez la ligne IP ... Mbps suivie de MQTT connected over Ethernet. Abonnez-vous ensuite depuis n'importe quel ordinateur :
mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-6b2d90 -v -t "connectmq/demo/eth-node-6b2d90/#"
Débranchez maintenant le câble pendant vingt secondes, puis rebranchez-le. Le journal série doit afficher link down, aucune tentative de connexion MQTT tant que le câble est retiré, puis link up, un nouvel événement IP et une reconnexion. Côté abonné, vous verrez status offline provenant du Last Will une fois le keep-alive expiré, puis online après le rétablissement. Ce « test de l'arrachage de câble » vaut la peine d'être fait sur chaque nouvelle conception matérielle ; il révèle des problèmes d'alimentation et de PHY qu'un test sur établi avec un lien stable ne montre jamais.
Le serveur MQTT public gratuit convient pour cet exercice, mais ses données sont lisibles par tout le monde. Les données machine doivent passer par des identifiants privés.
Structurer les données machine pour MQTT
La télémétrie du sketch est volontairement minimale. Sur une vraie machine, décidez tôt ce que contient chaque message et à quelle fréquence. Quelques règles qui tiennent bien en pratique :
- Séparez données rapides et données lentes. Les compteurs, températures et états qui changent chaque seconde vont sur un topic
telemetryà intervalle fixe. La configuration, la version du firmware et les numéros de série vont sur un topicinfo, publié une fois en retained message après chaque connexion. - Publiez les états sur changement. Un état machine comme
RUNNING,IDLEouFAULTest plus utile sous forme de retained message publié uniquement lorsqu'il change que sous forme de valeur répétée toutes les cinq secondes. - Incluez les unités et un horodatage.
{"spindleTempC":41.2,"ts":1760600000}se décrit tout seul ; un simple41.2, non. - Gardez des payloads compacts. L'Ethernet filaire offre largement assez de bande passante, mais le broker, vos tableaux de bord et toute base de données en aval paient le prix des messages verbeux.
Si vous publiez vers un broker ConnectMQ, ces conventions rendent aussi l'explorateur de topics en direct bien plus lisible lors de la mise en service, car chaque machine apparaît comme une branche bien rangée avec une poignée de topics pertinents.
Liste de contrôle pour un déploiement industriel
- Règles de pare-feu sortantes. Les réseaux d'usine bloquent souvent tout par défaut. Demandez l'ouverture du TCP 8883 sortant vers l'hôte de votre broker ; aucune règle entrante n'est nécessaire puisque c'est l'ESP32 qui initie la connexion.
- Utilisez le TLS sur 8883.
NetworkClientSecurefonctionne en Ethernet exactement comme en Wi-Fi ; suivez ESP32 MQTT SSL avec WiFiClientSecure et changez le nom de la classe. - IP statique ou réservation DHCP. Les équipes d'exploitation veulent pouvoir retrouver l'appareil. Une réservation DHCP est généralement plus simple à gérer qu'une adresse codée en dur.
- NTP pour les horodatages. Les réseaux industriels peuvent bloquer le NTP public ; utilisez le serveur de temps de l'usine.
- Watchdog. Combinez la conception pilotée par événements avec le backoff de la logique de reconnexion MQTT ESP32 et un watchdog matériel.
- Structure des topics. Adoptez dès le premier jour une hiérarchie de style ISA-95 comme
site/area/line/cell/device/telemetry; elle passe d'un seul nœud à une usine entière. - Alimentation et mise à la terre. Utilisez des alimentations sur rail DIN, du câble blindé là où se trouvent des variateurs, et envisagez des modules PoE pour éviter une ligne d'alimentation séparée.
Solution de secours : Ethernet avec backup cellulaire
Pour les sites distants, certaines conceptions associent l'Ethernet à un modem cellulaire en secours. La couche MQTT reste la même ; le firmware change le Client qu'il transmet à PubSubClient. Le guide ESP32 avec SIM7600 4G LTE MQTT présente le côté cellulaire.
D'un nœud à une usine
Dès que quelques nœuds publient, le broker devient une infrastructure partagée de l'usine. Un broker MQTT managé évite d'avoir à faire tourner et à patcher un serveur sur le réseau OT. ConnectMQ détecte automatiquement les structures de topics ISA-95 et Unified Namespace : lorsque vos topics suivent cette structure, la vue des appareils du portail regroupe vos nœuds Ethernet par site, zone et ligne, et des règles d'alerte à seuil peuvent signaler une valeur qui sort de sa plage normale. Utiliser un broker MQTT dans le cloud permet aussi à l'ingénierie et au support à distance de voir les mêmes données en direct sans accès VPN à l'usine. Pour le parcours ESP32 complet, consultez le tutoriel IoT ESP32.
Démarrez avec ConnectMQ
Créez gratuitement un broker Serverless sur app.connectmq.com, sans carte bancaire. Donnez à chaque nœud Ethernet ses propres identifiants et regardez vos données machine apparaître dans l'explorateur de topics en direct en quelques minutes.
Questions fréquentes
PubSubClient fonctionne-t-il en Ethernet sur l'ESP32 ?
Oui. PubSubClient accepte n'importe quel Client Arduino, et sur Arduino-ESP32 3.x, NetworkClient fonctionne aussi bien en Wi-Fi qu'en Ethernet grâce à la même pile réseau.
Puis-je utiliser un W5500 avec un ESP32-S3 ou un ESP32-C3 ?
Oui. Le W5500 se connecte en SPI : il fonctionne donc sur toute variante d'ESP32 disposant de broches SPI libres. Le LAN8720 nécessite l'EMAC interne, que seul l'ESP32 d'origine possède parmi ces puces.
Ai-je besoin de la bibliothèque Arduino Ethernet pour un W5500 ?
Pas avec Arduino-ESP32 3.x. La bibliothèque ETH intégrée prend directement en charge le W5500 et s'intègre à lwIP, si bien que le DNS, le TLS et NetworkClient se comportent comme en Wi-Fi.
L'ESP32 peut-il utiliser le Wi-Fi et l'Ethernet en même temps ?
Oui, les deux interfaces peuvent être actives. Assurez-vous que votre firmware sait laquelle porte la connexion MQTT et qu'il gère les événements des deux.



