ESP32-MQTT-Weight-Modul
https://github.com/MojitoShader/ESP32-MQTT-Weight-Modul
Wired Ethernet-Based Industrial Weight Measurement Module with W5500 — A Cocktail Bar Automation Case Study
Introduction: Why Weight Measurement Is Challenging in Automation Systems
In precision-critical environments like automated beverage dispensing systems, wireless communication turns out to be a less reliable choice than it might seem. Wi-Fi carries inherent weaknesses for real-time measurement loops — 2.4 GHz band congestion, intermittent packet loss, and reconnection delays can all disrupt closed-loop control. This project addresses that problem directly. Designed as a distributed weight measurement node for a cocktail bar automation robot, it leverages the WIZnet W5500 Ethernet controller to achieve reliable, real-time data communication over wired LAN.
The Role of the WIZnet W5500: Why Wired, and Why W5500?
In this project, the W5500 connects to the ESP32-S3 via SPI (MOSI/MISO/SCK/CS) and handles the Ethernet MAC/PHY layer. In the ESP32 Arduino environment, TCP/IP processing is handled by the lwIP stack running on the ESP32 itself, while the W5500 is dedicated to the wired physical layer (MAC + PHY) beneath it — a clean separation of responsibilities. The key advantage over Wi-Fi is that using a wired physical layer with lower software driver dependency significantly improves connection stability and latency predictability.
Key reasons W5500 was chosen:
- Deterministic Latency: The dispensing control loop requires 100 ms precision. Wired Ethernet produces far lower jitter than a software Wi-Fi stack.
- Multi-Node Scaling with Static IP: Each module is assigned a fixed IP (e.g.,
10.0.0.20for module 1,10.0.0.21for module 2), making multiple weight sensor nodes predictable and easy to manage. - MAC Address Generation from ESP32 eFuse: A unique hardware identifier is automatically generated per module, allowing multiple nodes to coexist on the same network without MAC conflicts.
- Link Status Monitoring: Cable connect/disconnect events are detected via
Ethernet.linkStatus()polling, with automatic MQTT session recovery on reconnection.
The initialization sequence proceeds as follows: W5500 hardware reset via GPIO 9 RST pin → SPI initialization (~1 MHz) → Ethernet configuration → MQTT broker connection. If a link is not detected within 30 seconds, the system continues to the next step and attempts self-recovery.
How It Works: Sensor → Filtering → MQTT Publish
The core of the system is a 10 Hz internal sensor loop combined with an adaptive MQTT publish strategy.
Sensor Layer
- HX711 Load Cell Amplifier (GPIO 35/36): Reads weight at 10 Hz with approximately 1 g resolution. Calibration offset and scale factor are stored in the ESP32's NVS (Non-Volatile Storage) and persist across power cycles.
- HC-SR04 Ultrasonic Sensor (GPIO 37/38): Measures distance in millimeters to detect the presence of a cup or glass. A stability filter requires 3 consecutive consistent readings before the
glass_presentstate is toggled — preventing false transitions from a single noisy reading.
Adaptive Publish Strategy
The system minimizes network load while delivering high-frequency data precisely when needed.
- No glass (idle): Publish at 1 Hz — suppresses unnecessary traffic during standby
- Glass detected (dispensing): Publish at 10 Hz — precise weight tracking at 100 ms intervals
In maintenance mode (sys/mode = MAINTENANCE), the rate is capped at 1 Hz regardless of glass state. When an emergency stop is received (sys/estop = ASSERTED), telemetry publishing halts immediately.
MQTT Communication Structure
Structured messages flow between the main controller and each weight module through an MQTT broker (default 10.0.0.10:1883).
[Main Controller]
│
├── PUBLISH → cell/bar1/mod/scale_1/cmd
│ { "req_id": "...", "cmd": "TARE", "timeout_ms": 5000 }
│
└── SUBSCRIBE ← cell/bar1/mod/scale_1/status (retained, QoS 1)
← cell/bar1/mod/scale_1/telemetry (10 Hz, QoS 0)
Every command carries a unique req_id (UUID). The module immediately acknowledges with state=BUSY, then publishes state=IDLE upon completion. If execution fails or a timeout occurs, state=ERROR is published along with an error message. If the MQTT connection drops, the LWT (Last Will Testament) mechanism automatically propagates state=OFFLINE through the broker.
Reconnection is handled with exponential backoff (1s → 2s → 4s → 8s → max 30s). On reconnection, up to 100 buffered telemetry samples are flushed in order, each with accurate timestamps.
Serial Interface (Secondary)
Commands such as SET_HX711_OFFSET, TARE, CALIBRATE_REFERENCE, and SAVE_CONFIG can be entered directly via USB/UART (115200 baud). The serial interface operates independently of MQTT, making it useful for field diagnostics and initial calibration.
Development Environment
The project is built on PlatformIO + Arduino Framework, with dependencies on PubSubClient 2.8.0, ArduinoJson 6.21.3, and a custom Ethernet driver (ETH-ESP3-W5500) forked by the author to support the ESP32-S3 + W5500 combination. The build target is esp32-s3-devkitc-1 (240 MHz, 8 MB Flash).
Scalability: Why This Architecture Generalizes
This project was designed for a cocktail dispensing robot, but the underlying system architecture is not tied to that specific application.
Scenarios where the same architecture applies:
- Food & Beverage Manufacturing Lines: Weight measurement nodes connected to a main PLC/controller via MQTT for precision filling processes
- Logistics & Warehouse Automation: Multiple weight sensor nodes deployed on the same LAN, with a controller aggregating all data using MQTT wildcards (
cell/+/mod/+/telemetry) - Chemical & Pharmaceutical Dispensing: High-frequency weight tracking for sub-dispensing processes where wired Ethernet stability is especially critical
- Smart Factory MES Integration: The node slots directly into an MQTT → middleware → ERP/MES pipeline as an edge data source
Adding a new node requires nothing more than assigning a different IP address and role_id string. The component set — W5500 module, HX711, HC-SR04 — is simple and cost-transparent, keeping the barrier low for scaling from prototype to repeated production deployments, including ODM/OEM contexts.
Tech Stack Summary
| Item | Details |
|---|---|
| MCU | ESP32-S3 (Espressif, 240 MHz, dual-core) |
| Ethernet Controller | WIZnet W5500 (MAC/PHY via SPI) |
| Weight Sensor Interface | HX711 Load Cell Amplifier (24-bit ADC, ~1 g resolution) |
| Distance Sensor | HC-SR04 Ultrasonic Sensor (mm resolution, cup detection) |
| Communication Protocol | MQTT (PubSubClient 2.8.0), QoS 0/1, LWT support |
| Payload Format | JSON (ArduinoJson 6.21.3) |
| Publish Rate | Adaptive: 1 Hz (idle) / 10 Hz (dispensing) |
| Configuration Storage | ESP32 NVS (persists across power cycles) |
| Secondary Interface | USB/UART Serial (115200 baud, calibration & diagnostics) |
| Development Environment | PlatformIO + Arduino Framework (ESP32-S3 DevKitC-1) |
| Network Configuration | Static IP, 10/100 Mbps wired Ethernet (RJ45) |
Project Repository: github.com/MojitoShader/ESP32-MQTT-Weight-Modul
