DEV Community

Cover image for Modbus RTU con ESP32 y RS485: maestro y esclavo paso a paso
Steven Carvajal
Steven Carvajal

Posted on Originally published at iot.gripe

Modbus RTU con ESP32 y RS485: maestro y esclavo paso a paso

Publicado originalmente en iot.gripe.

Modbus RTU es un protocolo industrial de 1979 que sigue en uso en medidores de energía, variadores, sensores de temperatura y PLC. Funciona sobre una línea RS485 de dos hilos, con un maestro que pregunta y varios esclavos que responden.

Con un ESP32 puedes hacer de maestro (leer un medidor y subir los datos a la nube) o de esclavo (ofrecer tus sensores a un PLC). Necesitas un módulo RS485 y una librería.

Cómo funciona en 30 segundos

  • Hay un maestro y hasta 247 esclavos. Cada esclavo tiene una dirección (1 a 247).
  • El maestro envía una petición ("esclavo 1, dame los registros 0 a 1") y el esclavo responde.
  • Los datos viven en registros de 16 bits. Los más usados:
Función Código Para qué
Leer holding registers 03 Valores de lectura y escritura (configuración, setpoints)
Leer input registers 04 Valores de solo lectura (medidas)
Escribir un registro 06 Cambiar un valor
Escribir varios registros 16 (0x10) Cambiar varios valores
Leer / escribir bobinas 01 / 05 Salidas y entradas de un bit

Hardware: el módulo RS485

El ESP32 no habla RS485 directamente. Necesitas un transceptor que convierta el UART de 3,3 V en la señal diferencial A/B.

Módulo Voltaje Control de dirección Comentario
MAX3485 / SP3485 3,3 V Pines DE y RE La opción correcta para el ESP32
MAX485 5 V Pines DE y RE Pensado para 5 V: con un ESP32 necesita cuidado con los niveles; mejor MAX3485
Módulo TTL a RS485 con auto-dirección 3,3 V o 5 V Automática Sin pines DE/RE: lo más fácil
  • Módulo RS485 MAX3485 3,3 V

Cableado

Módulo RS485 ESP32
VCC 3V3
GND GND
RO (RX) GPIO16 (RX2)
DI (TX) GPIO17 (TX2)
DE + RE (unidos) GPIO4
A / B Línea RS485 (A con A, B con B)

DE (driver enable) y RE (receiver enable) se unen y se controlan con un solo pin: nivel alto para transmitir y bajo para recibir. Los pines elegidos no son de arranque. Para otros, consulta el pinout del ESP32 DevKit.

Una advertencia: la nomenclatura A/B varía por fabricante. Si no hay respuesta, cambia A con B: no daña nada.

Maestro: leer un esclavo

Instala la librería ModbusMaster (de 4-20ma) desde el gestor. Este código lee dos registros del esclavo 1 cada 2 segundos:

#include <ModbusMaster.h>

#define RX2 16
#define TX2 17
#define DE_RE 4

ModbusMaster nodo;

void preTransmision()  { digitalWrite(DE_RE, HIGH); }
void postTransmision() { digitalWrite(DE_RE, LOW);  }

void setup() {
  Serial.begin(115200);
  pinMode(DE_RE, OUTPUT);
  digitalWrite(DE_RE, LOW);

  Serial2.begin(9600, SERIAL_8N1, RX2, TX2);
  nodo.begin(1, Serial2);                 // dirección del esclavo
  nodo.preTransmission(preTransmision);
  nodo.postTransmission(postTransmision);
}

void loop() {
  uint8_t r = nodo.readHoldingRegisters(0, 2);   // desde el registro 0, 2 registros
  if (r == nodo.ku8MBSuccess) {
    Serial.printf("R0=%u  R1=%u\n", nodo.getResponseBuffer(0), nodo.getResponseBuffer(1));
  } else {
    Serial.printf("Error Modbus: 0x%02X\n", r);
  }
  delay(2000);
}
Enter fullscreen mode Exit fullscreen mode

Con un módulo de auto-dirección quita pinMode, preTransmission y postTransmission. Los parámetros de readHoldingRegisters(dirección, cantidad) son el primer registro y cuántos leer.

Parámetros que deben coincidir

El esclavo y el maestro deben usar exactamente lo mismo:

  • Velocidad (baudios): lo más habitual es 9600; también 19200 y 115200.
  • Formato: 8N1 (8 bits, sin paridad, 1 de parada) u 8E1 (paridad par). Medidores de energía suelen ser 8N1 u 8E1.
  • Dirección del esclavo.

Si el ESP32 tiene que hacer otras tareas mientras espera respuestas, usa millis() en lugar de delay() para no bloquear el programa.

Interpretar los datos: la parte difícil

  • Direcciones: la documentación de muchos equipos usa la numeración antigua "40001" para el primer holding register. En el código eso es la dirección 0. Si lees "30001", es el primer input register (función 04) y también es 0. Un desplazamiento de uno es el error más común.
  • Escala: muchos equipos guardan 23,5 °C como 235 (valor × 10). El manual lo indica.
  • Valores de 32 bits y decimales (float): ocupan dos registros. El orden de las palabras (word order) depende del fabricante: si el número sale disparatado, intercambia los dos registros.
uint32_t unir(uint16_t alto, uint16_t bajo) {
  return ((uint32_t)alto << 16) | bajo;
}
Enter fullscreen mode Exit fullscreen mode

ESP32 como esclavo

Para exponer tus sensores a un PLC o a otro maestro, usa la librería modbus-esp8266 (de emelianov), que también funciona con ESP32:

#include <ModbusRTU.h>

#define DE_RE 4
ModbusRTU mb;

void setup() {
  Serial2.begin(9600, SERIAL_8N1, 16, 17);
  mb.begin(&Serial2, DE_RE);     // segundo parámetro: pin DE/RE
  mb.slave(1);                   // dirección del esclavo
  mb.addHreg(0, 0, 4);           // 4 holding registers desde la dirección 0
}

void loop() {
  mb.Hreg(0, (uint16_t)(analogRead(34)));   // publica una lectura en el registro 0
  mb.task();                                // atiende las peticiones
  delay(10);
}
Enter fullscreen mode Exit fullscreen mode

mb.task() debe llamarse muy a menudo: evita delay() largos. Si el esclavo tarda en responder, el maestro dará timeout.

La línea RS485: terminación y distancia

  • Topología en bus: una línea con los dispositivos en fila, no en estrella.
  • Resistencia de terminación de 120 Ω entre A y B en los dos extremos del bus. Muchos módulos la traen con un puente o interruptor.
  • Cable de par trenzado. Hasta unos 1200 m a 9600 baudios.
  • Masa común: conecta GND entre dispositivos si no usan aislamiento, o usa módulos con aislamiento galvánico en entornos industriales.

Errores comunes

Síntoma Causa Solución
Siempre timeout (0xE2) Velocidad, paridad o dirección incorrectas Revisa el manual del esclavo
Sin respuesta, parece conectado A y B invertidos Cambia A con B
Funciona unos segundos y falla Falta de terminación o cable largo 120 Ω en los extremos
Respuestas cortadas DE/RE no vuelve a recibir a tiempo Más rápido el postTransmision; módulo auto-dirección
Valores raros en floats Orden de palabras Intercambia los dos registros
Registro equivocado Direcciones desplazadas en uno 40001 → 0
Se reinicia o se cuelga al transmitir Alimentación insuficiente Cable USB de calidad; ver alimentar un ESP32

Preguntas frecuentes

¿Cuál es la diferencia entre Modbus RTU y Modbus TCP?

RTU va por línea serie (RS485); TCP, por red Ethernet o Wi-Fi. Con un ESP32 puedes hacer de pasarela: leer por RS485 y publicar por MQTT.

¿Puedo usar el UART0 (el del USB)?

No es buena idea: lo usas para cargar programas y depurar. Usa Serial2 (o Serial1) en los pines que elijas.

¿Cuántos esclavos puedo conectar?

El estándar permite 247 direcciones y la línea RS485 aguanta 32 dispositivos con un transceptor estándar. Más requieren repetidores o transceptores de carga reducida.

¿Se puede conectar a la nube?

Sí: lee el esclavo cada cierto tiempo y publica por MQTT. Para elegir el protocolo y el broker, mira MQTT vs HTTP en IoT.

Top comments (0)