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);
}
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;
}
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);
}
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)