Ir al contenido

Introducción a Modbus y Raspberry PLC. Parte 1

Escribe y lee un coil por Modbus RTU en Node-RED con node-red-contrib-modbus
21 de febrero de 2024 por
Introducción a Modbus y Raspberry PLC. Parte 1
Boot & Work Corp. S.L, Bernat Brunet Pedra

Guía completa: Modbus RTU y TCP con Python y Node-RED

Para escribir y leer un coil por Modbus RTU desde un Raspberry PLC en Node-RED, instala los nodos node-red-contrib-modbus y crea un Modbus-Client con Type Serial, el puerto RS-485 de tu PLC (/dev/ttySC0 o /dev/ttySC2), Serial type RTU y los parámetros serie del esclavo. Después usa un nodo Modbus Write con FC 5 y un nodo Modbus Read con FC 1, los dos con el Unit-Id del esclavo. El flujo de este post se ha probado con Node-RED 4.1 y node-red-contrib-modbus 5 contra un esclavo simulado.

Esta es la parte 1 de la serie Modbus y Raspberry PLC. Las partes 1 y 2 usan Node-RED, y las partes 3 y 4 usan Python. Todos los detalles, como timeouts, direccionamiento, valores de 32 bits y diagnóstico de fallos, están en la guía de Modbus para PLC con Raspberry Pi.

ParteProtocoloHerramienta
Parte 1 (este post)Modbus RTUNode-RED
Parte 2Modbus TCPNode-RED
Parte 3Modbus RTUPython
Parte 4Modbus TCPPython

Qué necesitas

  • Un Raspberry PLC con Node-RED. Es el maestro Modbus RTU. Si todavía no tienes Node-RED instalado, consulta cómo instalar Node-RED en un Raspberry PLC.
  • Un esclavo Modbus RTU: cualquier equipo con RS-485, u otro PLC de Industrial Shields que trabaje como esclavo, por ejemplo un PLC basado en Arduino o ESP32 como en Modbus RTU con PLC basados en Arduino y ESP32.
  • Cableado RS-485: A+ con A+ y B- con B-, con terminación en los extremos del bus.
  • Los parámetros serie del esclavo: dirección (Unit-Id), velocidad, paridad y bits de parada. Este post usa el Unit-Id 31 a 38400 bit/s, 8N1. Cámbialos para que coincidan con tu esclavo.

Arranca Node-RED e instala los nodos Modbus

Arranca Node-RED en un terminal del PLC:

node-red-start

Abre el editor en un navegador. Desde otro ordenador, usa http://PLC_IP_ADDRESS:1880. En el propio PLC, con una pantalla conectada, usa http://127.0.0.1:1880.

Abre Menu, Manage palette (o pulsa Alt+Mayús+P), ve a la pestaña Install, busca node-red-contrib-modbus e instálalo. La versión 5.62 de estos nodos necesita Node-RED 4 o posterior y Node.js 22 o posterior, así que comprueba antes node -v.

Configura el Modbus-Client para RS-485

Arrastra un nodo Modbus Write al flujo, haz doble clic y pulsa el icono del lápiz junto a Server. Se abre el Modbus-Client: la conexión que comparten todos los nodos Modbus del flujo.

CampoValorNota
TypeSerialModbus RTU va por el puerto serie
Serial port/dev/ttySC0 o /dev/ttySC2v3, y v4 sin expansión: /dev/ttySC0 y /dev/ttySC1. v6, y v4 con expansión: /dev/ttySC2 y /dev/ttySC3. Compruébalo con ls /dev/ttySC*
Serial typeRTU
Baud rate38400Igual que en el esclavo
Bits de datos, paridad, bits de parada8, None, 1Igual que en el esclavo
Unit-Id1Unit-Id por defecto para los nodos que dejan vacío su propio Unit-Id. No es la dirección del maestro: en Modbus RTU el maestro no tiene dirección

Pon un nombre a la configuración y pulsa Update. Si el flujo usa varios puertos RS-485, crea un Modbus-Client para cada puerto y comprueba que cada nodo usa el correcto.

Escribe un coil con Modbus Write (FC 5)

Configura el nodo Modbus Write:

  • Unit-Id: 31, la dirección del esclavo.
  • FC: FC 5: Force Single Coil.
  • Address: 0. El coil 00001 del manual del equipo es la dirección 0.
  • Quantity: 1.
  • Server: el Modbus-Client del paso anterior.

Añade un nodo Inject, pon en msg.payload el booleano true y conéctalo a Modbus Write. Añade un segundo nodo Inject con el booleano false. Cada clic en un nodo Inject envía una petición de escritura: true activa el coil y false lo desactiva.

Flujo de Node-RED: un nodo Inject con el valor true conectado a un nodo Modbus Write con el estado active
Un nodo Inject con el valor true conectado a Modbus Write.

Lee el coil con Modbus Read (FC 1)

Añade un nodo Modbus Read con el mismo Modbus-Client:

  • Unit-Id: 31, el mismo esclavo.
  • FC: FC 1: Read Coil Status.
  • Address: 0. Quantity: 1.
  • Poll Rate: 1 segundo.

Conecta un nodo Debug a la primera salida de Modbus Read, que da el array de datos. La segunda salida da la respuesta Modbus en bruto. Pulsa Deploy. El panel Debug muestra un mensaje nuevo cada segundo. La respuesta lleva los coils en bytes completos, así que el array tiene 8 valores aunque leas un solo coil. El primer valor es el coil 0.

En nuestra prueba, después de un clic en el nodo Inject true, las lecturas siguientes mostraron un array que empieza por true, y después de un clic en false, un array que empieza por false.

Flujo completo de Node-RED: nodos Inject true y false conectados a Modbus Write, y Modbus Read conectado a un nodo debug
El flujo completo: dos nodos Inject (true y false) alimentan Modbus Write, y Modbus Read consulta el coil cada segundo y lo envía a un nodo Debug.

Importa el flujo completo

Para saltarte los pasos manuales, abre Menu, Import, pega este flujo y pulsa Import. Después cambia el puerto serie y el Unit-Id por los valores de tu PLC y de tu esclavo.

[{"id":"5e1ff7e5bdc20aad","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"bf0737313ed47579","type":"modbus-write","z":"5e1ff7e5bdc20aad","name":"","showStatusActivities":true,"showErrors":true,"showWarnings":true,"unitid":"31","dataType":"Coil","adr":"0","quantity":"1","server":"d71fcab96da43404","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":660,"y":300,"wires":[[],[]]},{"id":"ecf9141ee03c86bc","type":"inject","z":"5e1ff7e5bdc20aad","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":510,"y":280,"wires":[["bf0737313ed47579"]]},{"id":"d3759149be3b0b7e","type":"inject","z":"5e1ff7e5bdc20aad","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":510,"y":320,"wires":[["bf0737313ed47579"]]},{"id":"8f43e9aa567f6f3c","type":"modbus-read","z":"5e1ff7e5bdc20aad","name":"","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"31","dataType":"Coil","adr":"0","quantity":"1","rate":"1","rateUnit":"s","delayOnStart":false,"startDelayTime":"","server":"d71fcab96da43404","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":530,"y":400,"wires":[["d2d923f66ea77a31"],[]]},{"id":"d2d923f66ea77a31","type":"debug","z":"5e1ff7e5bdc20aad","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":680,"y":400,"wires":[]},{"id":"d71fcab96da43404","type":"modbus-client","name":"ModbusRTU","clienttype":"simpleser","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttySC0","serialType":"RTU","serialBaudrate":"38400","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

Cuando el esclavo no responde

SíntomaQué comprobar
No llegan mensajes al panel Debug, Modbus Read muestra un timeoutUnit-Id del esclavo, velocidad, paridad y bits de parada, A+ y B- invertidos, terminación en los extremos del bus
El Modbus-Client no puede abrir el puertoEl nombre del puerto para tu versión de PLC, con ls /dev/ttySC*
Algunas lecturas fallan y otras funcionanDos programas en el mismo puerto. Solo un programa puede usar un puerto serie: para los scripts de Python u otros flujos que lo usen
Código de excepción 02 (dirección de datos no válida)La dirección del coil no existe en el esclavo. Consulta la tabla de coils en el manual del esclavo
Los nodos Modbus no se instalan o no aparecenVersiones de Node-RED y Node.js: node-red-contrib-modbus 5.62 necesita Node-RED 4 y Node.js 22 o posterior

Para ver los errores en el panel Debug, activa Show Errors en los nodos Modbus Read y Modbus Write.

Qué hemos probado. Node-RED 4.1.17 sobre Node.js 22 (Linux) con node-red-contrib-modbus 5.62.1 y 5.23.3. La versión 5.62.1 se ejecutó con la librería modbus-serial 8.0.25 de npm en lugar de su propia versión modificada de esa librería. El flujo de este post, cambiando solo el puerto serie por un enlace serie virtual, se ejecutó contra un esclavo Modbus RTU simulado (pymodbus 3.16.1, Unit-Id 31, 38400 8N1). Los nodos Inject true y false activaron y desactivaron el coil 0, y Modbus Read mostró el nuevo valor en menos de un segundo. No hemos ejecutado esta actualización en un Raspberry PLC real: las dos capturas son de la primera versión del post.

¿Qué controlador para tu proyecto Modbus? Un Raspberry PLC ejecuta Node-RED y Python sobre Linux. Un PLC basado en Arduino o ESP32, un PLC clásico, un PC industrial o un gateway también pueden ser el maestro Modbus. La guía comparativa da los criterios para elegir.

Compara controladores industrialesAbre la guía completa de Modbus

Llévalo a la práctica

Tras los primeros pasos de Modbus en un Raspberry PLC: una red real, un simulador para romperla y un ejemplo de Modbus TCP.

Preguntas frecuentes sobre Modbus RTU en Node-RED

¿Qué es el Unit-Id de la configuración del Modbus-Client?

Es el Unit-Id por defecto para los nodos Modbus que dejan vacío su propio Unit-Id. Un nodo con su propio Unit-Id usa ese valor. El maestro Modbus RTU no tiene dirección, así que este campo nunca identifica al Raspberry PLC.

¿Qué puerto RS-485 selecciono en un Raspberry PLC?

/dev/ttySC0 o /dev/ttySC1 en el v3, y en el v4 sin expansión. /dev/ttySC2 o /dev/ttySC3 en el v6, y en el v4 con expansión. ls /dev/ttySC* lista los puertos de tu PLC.

¿Por qué el panel Debug muestra 8 valores para un solo coil?

Porque la respuesta Modbus lleva los coils en bytes completos, y el nodo da todos los bits de esos bytes. Usa solo el primer valor.

¿Pueden un flujo de Node-RED y un script de Python usar el mismo puerto RS-485?

No a la vez. Dos programas en un mismo puerto serie se quitan bytes el uno al otro, y aparecen timeouts y errores de CRC. Para el flujo antes de ejecutar el script de la parte 3.

¿Cómo hago lo mismo por Ethernet?

Con un Modbus-Client de Type TCP y la dirección IP del esclavo. Consulta la parte 2: Modbus TCP y Node-RED.

Buscar en nuestro blog

Introducción a Modbus y Raspberry PLC. Parte 1
Boot & Work Corp. S.L, Bernat Brunet Pedra 21 de febrero de 2024
Compartir esta publicación

¿Estás buscando tu Controlador Lógico Programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.

Comparativa de PLCs