MQTT is the cheapest way to get robot telemetry off the machine and onto a dashboard. One broker, a few topics, and an ESP32 publishing battery, speed and fault data over Wi-Fi.
This guide covers the topic design, the QoS choices, a working ESP32 publisher, a subscriber that logs to a database, and the Wi-Fi and memory traps that break telemetry in the field.
Why MQTT suits a robot
- Small messages over a small bandwidth link.
- Publish and subscribe, so many dashboards can read one robot.
- A broker decouples the robot from whoever is watching it.
- Last Will and Testament tells you when a robot drops off.
- Retained messages mean a new subscriber sees the last known state immediately.
- Runs comfortably on an ESP32 with a few KB of RAM per connection.
Design the topic tree first
robots/<robot_id>/status
robots/<robot_id>/battery
robots/<robot_id>/velocity
robots/<robot_id>/fault
robots/<robot_id>/cmd/velocity
robots/<robot_id>/cmd/estop| Topic | Direction | QoS | Retained |
|---|---|---|---|
| status | Robot to broker | 1 | Yes |
| battery | Robot to broker | 0 | Yes |
| velocity | Robot to broker | 0 | No |
| fault | Robot to broker | 1 | Yes |
| cmd/velocity | Operator to robot | 1 | No |
| cmd/estop | Operator to robot | 1 | No |
Keep commands and telemetry in separate subtrees. It makes broker access control simple: the dashboard can read everything under the robot, but write only under cmd/.
QoS without overthinking it
| QoS | Guarantee | Use for |
|---|---|---|
| 0 | At most once, fire and forget | Fast telemetry, velocity, battery |
| 1 | At least once, may duplicate | Commands, faults, status |
| 2 | Exactly once | Billing or records, rarely a robot |
QoS 1 can deliver duplicates, so make the receiving handler idempotent. A command with a sequence number that ignores repeats is safer than one that executes twice.
A working ESP32 publisher
The PubSubClient library is the common choice. Connect, publish on a timer, and use a Last Will so the broker marks the robot offline when the link dies.
#include <WiFi.h>
#include <PubSubClient.h>
WiFiClient net;
PubSubClient mqtt(net);
const char* robot = "robot-01";
void connect() {
while (!mqtt.connected()) {
if (mqtt.connect(robot, nullptr, nullptr,
"robots/robot-01/status", 1, true, "offline")) {
mqtt.publish("robots/robot-01/status", "online", true);
} else {
delay(2000);
}
}
}
void setup() {
WiFi.begin("SSID", "PASSWORD");
mqtt.setServer("192.168.1.50", 1883);
mqtt.setBufferSize(512);
}
void loop() {
if (!mqtt.connected()) connect();
mqtt.loop();
static unsigned long last = 0;
if (millis() - last > 2000) {
last = millis();
char buf[96];
snprintf(buf, sizeof(buf),
"{\"v\":%.1f,\"b\":%d}", 0.42, 87);
mqtt.publish("robots/robot-01/telemetry", buf);
}
}Note the explicit buffer size. The default 256-byte packet limit is the most common reason a JSON payload silently fails to publish.
The broker
Mosquitto on a small VPS or a Raspberry Pi handles a workshop full of robots. Open 1883 only inside your network, and 8883 with TLS if anything crosses the internet.
sudo apt install mosquitto mosquitto-clients
mosquitto_sub -h localhost -t 'robots/#' -vCreate a username and password per robot, and give the dashboard a separate read-only account. An open broker on a factory network is a remote-control hole.
From broker to dashboard
- Node-RED: fastest path to charts and alerts, runs on the same Pi.
- InfluxDB plus Grafana: better for history and long-term trends.
- Home Assistant: useful for small service robots and lab setups.
- A Python subscriber: writes to Postgres when you need custom logic.
A simple Python subscriber that stores every message with a timestamp is often all a first deployment needs. Build the dashboard after the data is reliable.
Field problems and what causes them
| Symptom | Likely cause |
|---|---|
| Messages stop after a few minutes | Keepalive too short for Wi-Fi latency |
| Publish returns false | Payload larger than the buffer |
| Reconnect loop | Duplicate client ID from a cloned device |
| Dashboard shows stale data | Retained message never updated, or LWT not set |
| Commands arrive twice | QoS 1 duplicate without an idempotency check |
| Robot busy or slow | Publishing too often from the main control loop |
What not to put on MQTT
- Safety stop commands over Wi-Fi. Hardwire the E-stop.
- High-rate control loops. Use a local bus or micro-ROS.
- Large images or point clouds. Send a link or a summary.
- Credentials in plain text on port 1883 across the internet.
- Anything you cannot afford to lose without an acknowledgement path.
Related: ESP32 pinout for robotics, micro-ROS tutorial, Raspberry Pi 5 robot guide, robot battery guide, mobile robot charging and docking.
Is MQTT good for robot telemetry?
Yes for low-rate telemetry such as battery, status, faults and position. It is not suitable for safety stops or high-rate control loops, which should stay on hardware or a local bus.
Which QoS should I use for robot data?
QoS 0 for fast telemetry like velocity and battery, QoS 1 for commands and faults. QoS 2 is rarely worth the overhead on a robot.
Why does my ESP32 stop publishing to MQTT?
The usual causes are a payload bigger than the 256-byte default buffer, a keepalive too short for Wi-Fi latency, or a duplicate client ID after cloning a device.
Can I send emergency stop over MQTT?
No. A safety stop must be hardwired and independent of Wi-Fi, the broker and the network. MQTT can notify people that a stop happened, not perform it.
Do I need TLS for MQTT on a robot?
If traffic crosses the internet, yes, use port 8883 with certificates. Inside an isolated workshop network, 1883 with per-device credentials is common but still needs access control.
For driving rather than telemetry, a phone app over WebSocket is simpler.
Streaming attitude data is easier once the MPU6050 angle estimation loop is stable and calibrated.
Telemetry should never block the motor loop, which is why the task and queue design separates comms from control.
For telemetry rather than driving, the same network foundation is covered in this control guide.
MQTT is one of the transport options in a factory deployment, described alongside OPC UA in the IIoT monitoring guide.
Sources and further reading
- MQTT.org — protocol specification and overview.
- Eclipse Mosquitto — broker documentation and configuration.
- PubSubClient — Arduino client library reference.
- Node-RED — dashboards and flows for MQTT data.


