No es un duelo, es un reparto de tareas
La pregunta “¿MQTT o Modbus?” está mal planteada casi siempre. Suena a que hay que elegir bando, y no lo hay. Modbus lee un registro de un PLC que lleva ahí desde 2009. MQTT mueve ese dato hasta un dashboard en la nube sin que la red se ahogue. En una planta real conviven, y el error caro es usar uno donde tocaba el otro.
Voy a separar los dos mundos, porque mezclarlos es la fuente de la mitad de los problemas de integración que me he encontrado.
Los dos hablan de cosas distintas
Modbus es un protocolo de acceso a datos. Modelo maestro-esclavo: el maestro pregunta, el esclavo responde, y nada se mueve si nadie pregunta. Lees un holding register, escribes una consigna, y punto. Es síncrono, predecible y viejo en el buen sentido: lleva desde 1979 y funciona en equipos que cuestan cuatro duros.
MQTT es un protocolo de transporte de mensajes. Modelo publicador/suscriptor con un broker en medio. Un dispositivo publica en un topic, cualquiera suscrito lo recibe, y nadie tiene que preguntar por nada. Es asíncrono y orientado a eventos: el dato viaja cuando cambia, no cuando alguien lo reclama.
Esa diferencia —preguntar frente a avisar— lo explica casi todo.
La tabla que resuelve el 90 % de las decisiones
| Criterio | Modbus | MQTT |
|---|---|---|
| Modelo | Maestro / esclavo (pregunta-respuesta) | Publicador / suscriptor (broker) |
| Comunicación | Síncrona, bajo demanda | Asíncrona, orientada a eventos |
| Dónde vive | Bus de campo, PLC, sensores | Red IP, IoT, enlace a la nube |
| Latencia | Baja y determinista en RTU | Depende de la red y del QoS |
| Escala | Decenas de esclavos por bus | Miles de clientes por broker |
| Si se cae el enlace | El maestro reintenta o falla | El broker retiene con QoS 1/2 |
| Descubrimiento | No: direcciones fijas | Topics dinámicos |
| Coste de entrada | Muy bajo | Bajo, pero necesita broker |
Si el dato está dentro de la planta y lo pide un autómata, Modbus. Si el dato tiene que salir de la planta o alimentar a muchos consumidores a la vez, MQTT.
Modbus: cuando mandas tú y el tiempo importa
Modbus brilla en el bus de campo. Control determinista, un maestro que marca el ritmo, esclavos que responden en milisegundos. Aquí no quieres eventos sueltos: quieres saber el valor de la temperatura ahora, en el ciclo de scan, y actuar en consecuencia.
Un ejemplo de lectura con Modbus TCP desde Python, que es como la mayoría de integraciones empiezan:
from pymodbus.client import ModbusTcpClient
# El PLC es el esclavo; nosotros somos el maestro que pregunta.
client = ModbusTcpClient("192.168.1.50", port=502)
client.connect()
# Leer 2 holding registers desde la dirección 40001 (offset 0), unit=1.
# Dos registros de 16 bits = un REAL de 32 bits (IEEE 754).
resp = client.read_holding_registers(address=0, count=2, slave=1)
if resp.isError():
# Timeout, CRC o excepción del esclavo: aquí se reintenta, no se ignora.
raise ConnectionError("El esclavo no respondió correctamente")
registros = resp.registers # p. ej. [17056, 0]
client.close()
Nada de suscripciones ni brokers. Preguntas, te responden, gestionas el error. Si el esclavo no contesta, reintentas o fallas: no hay una capa mágica que guarde el dato por ti. Esa honestidad es justo lo que quieres en control de proceso.
Donde Modbus se queda corto es en la escala y en la distancia. Sondear 500 puntos cada segundo satura el bus, y llevar Modbus TCP a través de internet es pedir problemas de latencia y seguridad.
MQTT: cuando el dato tiene que viajar y multiplicarse
MQTT resuelve exactamente eso. Un dispositivo publica el valor una vez y el broker lo reparte a todos los suscritos: el histórico, la alarma, el dashboard, el modelo de mantenimiento predictivo. Uno publica, muchos leen, y nadie sondea a nadie.
El mismo dato de antes, ahora publicado en un topic:
import json
import paho.mqtt.client as mqtt
client = mqtt.Client()
# QoS 1: "al menos una vez". El broker reintenta hasta confirmar la entrega.
client.connect("broker.planta.local", 1883)
payload = json.dumps({
"sensor": "temp_caldera_3",
"valor": 87.4,
"unidad": "C",
"ts": "2026-07-05T10:00:00Z",
})
# Retain=True: quien se suscriba después recibe el último valor conocido.
client.publish("planta/caldera/3/temperatura", payload, qos=1, retain=True)
Fíjate en lo que MQTT te da gratis y Modbus no: si el enlace se cae, QoS 1 o 2 retiene el mensaje; con retain=True, un consumidor que arranca más tarde recibe el último valor sin preguntar. Es el patrón natural para telemetría, IoT industrial y todo lo que tenga que subir a la nube.
El precio: MQTT no es determinista. No lo pongas en un lazo de control donde un retardo de 200 ms rompe el proceso. Ahí sigue mandando Modbus.
El patrón que uso: los dos juntos con un gateway en medio
En la práctica casi nunca eliges. El montaje que mejor me ha funcionado es un gateway que habla los dos idiomas: sondea los PLC por Modbus en el bus de campo y publica por MQTT hacia arriba.
[PLC / sensores] --Modbus RTU/TCP--> [Gateway] --MQTT--> [Broker] --> nube, dashboards, alarmas
El gateway hace de traductor y de amortiguador. Abajo, el determinismo de Modbus para leer la planta. Arriba, la escala y la resiliencia de MQTT para distribuir el dato. Si un frame de Modbus falla, el gateway reintenta sin que la nube se entere; si el enlace a la nube se cae, el broker retiene y no se pierde telemetría. Cada protocolo hace lo que sabe hacer.
Cómo decidir en dos preguntas
Antes de escribir una línea, respóndete esto:
¿El dato se queda dentro de la planta y lo consume un autómata en tiempo de ciclo? Modbus. Determinista, barato y probado.
¿El dato tiene que salir de la planta, o lo necesitan varios consumidores a la vez? MQTT. Desacopla, escala y sobrevive a los cortes de red.
Y si la respuesta es “las dos cosas” —que es lo habitual— pon un gateway y deja que cada protocolo trabaje en su terreno. La elegancia no está en elegir uno, sino en no forzar a ninguno a hacer el trabajo del otro.