|
El protocolo MODBUS
Jordi Bartolomé 1-2024
-Introducción
-Descripción general -Tramas MODBUS: ADU y PDU -Campos de los ADU MODBUS -Campos de los PDU MODBUS -Direcciones MODBUS -Códigos de operación o función más frecuentes
El protocolo de comunicaciones industriales MODBUS fue desarrollado en 1979 por la empresa norteamericana MODICON y debido a que es público, relativamente sencillo de implementar y flexible se ha convertido en uno de los protocolos de comunicaciones más populares en sistemas de automatización y control. A parte de que muchos fabricantes utilizan este protocolo en sus dispositivos, existen también versiones con pequeñas modificaciones o adaptadas para otros entornos (como p.ej JBUS o MODBUS II)
MODBUS especifica el procedimiento que el cliente y el servidor utilizan para intercambiar datos, el formato de estos datos, como se tratan los errores etc. No especifica estrictamente el tipo de red de comunicaciones a utilizar, por lo que se puede implementar sobre redes basadas en Ethernet, RS-485, RS-232 etc. Este documento explica la especificación MODBUS de forma general, sin entrar en mucho detalle en algunas de sus particularidades, no obstante su contenido ha de ser más que suficiente para aquellos que deseen comprender el funcionamiento general de este estándar. Por otro lado, quien desee realizar una implementación precisa de MODBUS deberá recurrir a la documentación disponible en modbus.org o a la documentación especifica del fabricante de los equipos con los que va a comunicar.
Las comunicaciones MODBUS funcionan siempre en modo cliente - servidor (maestro - esclavo), siendo el cliente (maestro) quien controla (quien inicia) en todo momento las comunicaciones con los servidores (esclavos) los cuales pueden ser hasta 247. Cada servidor se identifica mediante un número comprendido entre @1d y @247d. Los clientes se mantienen enviando consultas MODBUS y procesando las respuestsa recibidas de los diferentes servidores consultados. Los servidores se limitan a responder a los comandos recibidos ( menos en el caso de los mensajes de tipo broadcast a los que no responden):
1-El cliente ( master ) solicita al servidor @2 la ejecución de un comando ( una lectura o escritura en una I/O, lectura de un registro o cualquier otra operación ). 2-El servidor ( slave ) ejecuta y responde al cliente con el resultado de dicha operación.
La comunicación del cliente hacia los servidores puede ser de dos tipos: - “peer to peer”: en que se establece comunicación 1:1 del “cliente a un servidor“, el cliente solicita información y el servidor responde (se envía el comando a un dispositivo comprendido entre las direcciones 1d y 247d). Es el tipo utilizado normalmente. - “broadcast”: en que se establece comunicación 1:n del “cliente a todos los servidores”, el cliente envía un comando a todos los servidores de la red sin esperar respuesta (se envía a la dirección @0d). La secuencia básica en las comunicaciones MODBUS consiste siempre en una trama de pregunta por parte del cliente, seguida de su correspondiente trama de respuesta por parte del servidor consultado: - Pregunta (solicitud): el cliente envía el código de función que indica al servidor que operación ha de realizar, y los bytes necesarios (datos, comprobación …) para su ejecución. - Respuesta: el servidor responde con la confirmación o datos resultantes de la ejecución de la función. Existe algún caso concreto en que hay más de una trama de respuesta para una trama de pregunta, como p.ej. cuando el cliente solicita la ejecución de una operación cuya respuesta puede llevar al servidor un tiempo elaborar. En estas situaciones el servidor envía una primera respuesta indicando que aún no tiene los datos y tardará un tiempo en disponer de ellos, y otra segunda con los datos o confirmación de la operación. MODBUS no impide que un equipo que actua como servidor pueda actuar a su vez como cliente con otros dispositivos y viceversa si el tipo de red lo permite. Esto puede ser de utilidad en aquellas aplicaciones que requieran de un intercambio bidireccional de datos. Ejemplos de transaccion MODBUS exitosa y transacción MODBUS con fallo ( como fallo se debe contemplar también que el servidor no conteste en el tiempo máximo establecido ).
Las tramas MODBUS constan de 2 partes diferenciadas:
- PDU: Protocol Data Unit: es común a todas las implementaciones MODBUS. La estructura y datos de esta parte es la misma independientemente de las capas inferiores de comunicaciones. - ADU: Application Data Unit: son datos que acompañan y encapsulan a la PDU y pueden ser diferentes dependiendo de las particularides de las capas inferiores de comunicaciones. ![]() Los campos del ADU son distintos dependiendo del tipo de implementación MODBUS. Las implementaciones de MODBUS más extendidas son: MODBUS TCP, MODBUS RTU y MODBUS ASCII. En cambio los campos PDU son siempre los mismos: Function Code + Data. El contenido del campo Data dependerá del Function Code, pues cada operación requiere de datos diferentes para su ejecución. Dentro de una misma implementación MODBUS los campos del ADU son siempre los mismos, tanto en las trama de pregunta como en las de respuesta, en cambio los campos del PDU sí pueden ser diferentes pues en un caso contienen la información de la solicitud y en el otro los datos de la respuesta. Tramas MODBUS ASCII (formato texto): -ADU: Inicio de trama: 1 byte codificando el caracter ASCII “:” (0x3A) -ADU: NºServidor: 2 bytes correspondientes a los 2 caracteres ASCII con la representación en hexadecimal de la dirección del servidor destino de la trama. -PDU: Código de operación: 2 bytes correspondientes a los 2 caracteres ASCII con la representación en hexadecimal del byte del código de operación. -PDU: Datos: grupos de 2 bytes correspondientes a los caracteres ASCII con la representación en hexadecimal de los datos necesarios para realizar la operación. -ADU: LRC(16): 2 bytes correspondientes a los caracteres ASCII con la representación en hexadecimal del valor del cálculo LRC. -ADU: Final de trama: 2 bytes codificando los carácteres ASCII CR- LF (0x0D - 0x0A) ![]() Tramas MODBUS RTU (formato binario, el inicio de trama debería ser tras 3.5 tiempo de carácter): -ADU: NºServidor: 1 byte con la dirección del servidor destino de la trama -PDU: Código de operación: 1 byte con el código de operación -PDU: Subfunciones Datos: con los parámetros necesarios para realizar la operación. -ADU:CRC(16): H L. ![]() Tramas MODBUS TCP (formato binario): -ADU: Identificador de la transacción: 2 bytes con el número de transacción. Cada transacción realizada se identifica de forma única con un número generalmente incremental. Este identificador permitirá saber a que comando perviamente enviado por el cliente corresponde cada respuesta del servidor. -ADU: Identificador del protocolo: 2 bytes correspondientes al identificador de protocolo . -ADU: Longitud de la trama recibida: 2 bytes correspondientes al numero de bytes que siguen hasta el final de la trama. -ADU: NºServidor: 1 byte con la dirección del servidor destino de la trama -PDU: Datos: 1 byte con el código de opreación. -PDU: Dirección datos y subfunciones datos: con los parámetros necesarios para realizar la operación. ![]() En MODBUS TCP y RTU los bytes se envían en binario, tal cual, mientras que en MODBUS ASCII los bytes se envían codificados en ASCII, es decir, que por cada byte a transmitir se envían en realidad dos bytes correspondientes a los dos caracteres ASCII (2 bytes) que codifican los caracteres de su representación en hexadecimal. Esto permite leer directamente las tramas con un simple editor o terminal de texto, p.ej: en modo RTU y TCP el byte '0x36' se transitiría tal cual con 1 único byte '0x36', mientras que en modo ASCII el byte '0x36' se transitiría con los 2 bytes '0x33,0x36' correspondientes a los caracteres '3' y '6' y al visualizarse con un editor o terminal de texto ser vería como '36'. El byte '0x05' en modo TCP y RTU se transmitiría también como '0x05' pero en modo ASCII como '0x30,0x35' que al visualizarse con un editor o terminal de texto se vería '05'. MODBUS utiliza "big endian" tanto para las direcciones como para los datos, lo que signfica que cuando se transmite un valor mayor que 1 byte, el byte más significaivo se transmite primero (el receptor lo recibe primero) y el menos significativo se transmite el último (el receptor lo recibe el último). P.ej: dada la direccción o dato de 16 - bits 0x1234, el primer byte en enviarse es 0x12 y el ultimo 0x34. En el modo ASCII las tramas comienzan por el byte 3AH (carácter ASCII ':'), y terminan con los bytes 0DH-0AH (caracteres ASCII CR LF Carrier Return y Line Feed). En modo TCP y RTU no se utiliza ningún carácter para indicar el inicio ni el final de trama. ![]() El modo TCP se utiliza generalmente sobre redes Ethernet, mientras que los modos MODBUS RTU y MODBUS ASCII se utilizan en medios serie (rs232, rs485 etc.). Estas son las particularidades de la comunicaciones serie en los modos MODBUS RTU y MODBUS ASCII:
El siguiente es un ejemplo de red de comunicaciones industrial con diferentes implemetaciones MODBUS:
![]()
A continuación se describen los campos ADU más comunes en los diferentes tipos de trama MODBUS. Estos estarán o no en el ADU de la trama, dependiendo de si la implementación de MODBUS es TCP, RTU o ASCII:
- Destination Address (1byte número de servidor o Node Id): está presente en MODBUS ASCII, RTU y TCP. En el caso de las tramas enviadas por el cliente, el campo de número de servidor indica la dirección del servidor al que va dirigida la trama. Permite direccionar hasta 247 esclavos, con las direcciones de 1d a 247d (0x00 a 0xF7). El 0x00 es para los mensajes de Broadcast, así el primer servidor comienza con la dirección 1 (de 1 a 247). En el caso de las tramas enviadas por los esclavos, este byte sirve para indicar al cliente a quién pertenece la respuesta. Es decir, cada vez que un servidor responde, sitúa su propia dirección en el byte de dirección lo que permite saber al cliente a que equipo corresponde cada respuesta. Las tramas broadcast, no tienen asociada respuesta, y algunas implementaciones de MODBUS no admiten la trama de broadcast. - Frame ID (2bytes Identificador de transacción): está presente en MODBUS TCP y se utiliza para asociar las preguntas enviadas por el cliente con las respuestas enviadas por el servidor. Debe ser un número único y se puede utilizar de diferentes formas: se puede usar como un simple "número de secuencia TCP" con un contador que se incrementa en cada solicitud. También se puede usar a modo de indice o puntero para identificar un contexto de transacción, con el fin de memorizar el servidor remoto actual y la solicitud MODBUS pendiente. Normalmente, en las implementaciones serie de MODBUS (ASCII y RTU), un cliente debe enviar una única solicitud a la vez y esperar a haber recibido la respuesta antes de enviar la siguiente. Esto significa que el cliente debe esperar la respuesta a la primera solicitud antes de enviar una segunda solicitud. En cambio, en las implementaciones MODBUS TCP, gracias a este identificador de transaccion se pueden enviar varias solicitudes al mismo servidor sin tener que esperar una confirmación para enviar la siguiente solicitud. El número de solicitudes aceptadas por un servidor depende de su capacidad en términos del número de recursos y del tamaño de las ventanas TCP. De la misma manera, el número de transacciones inicializadas simultáneamente por un cliente también depende de su capacidad de recursos. Este parámetro de implementación se llama "NumberMaxOfClientTransaction" y debe describirse como una de las características del cliente MODBUS. Dependiendo del tipo de dispositivo, este parámetro puede tener un valor de 1 a 16. - Protocol ID (2 bytes): está presente en MODBUS TCP, y en el caso de MODBUS TCP convencional vale 0. - Length (2 bytes): está presente en MODBUS TCP y sirve para indicar el total de bytes que siguen a este campo hasta el final del mensaje, es decir el numero de bytes tras este campo hasta el final del ADU (los 2 bytes de la longitud no se contabilizan en el valor). - Error check (control de errores LRC o CRC): está presente en MODBUS ASCII y RTU. Se utiliza un sistema de detección de errores diferente dependiendo del tipo de codificación utilizado (ASCII o RTU) . En el caso de la codificación ASCII es el checksum (o Longitud Redundancy Check LRC) en módulo 16 expresado en ASCII (2 caracteres representan 1 byte), sin considerar el ":" ni el “CR LF” de la trama. En la codificación RTU se utiliza el método de CRC (Cyclical Redundancy Check) codificado en 2 bytes (16 bits). Para calcular el CRC se carga un registro de 16 bits todo con '1's , se hace OR con cada uno de los caracteres de 8 bits con el contenido de cada byte y el resultado se desplaza una bit a la izquierda insertando un 0 en la posición de menos peso (la de la derecha). El de la izquierda se extrae y se examina: si es 1 se vuelve a hacer OR con un valor prefijado, si es 0 no se hace ninguna OR etc. y el proceso se repite hasta que se han hecho los 8 shifts del byte. La siguiente es una implementación en C de la función de cálculo del CRC (modo RTU):te sirve para indicar al cliente a quién pertenece la respuesta. Es decir, cada vez que un servidor responde, sitúa su propia dirección en el byte de dirección lo que permite saber al cliente a que equipo corresponde cada respuesta. Las tramas broadcast, no tienen asociada respuesta, y algunas implementaciones de MODBUS no admiten la trama de broadcast.
Los siguientes son los campos de los PDUs presentes en todas las tramas MODBUS, independientemente de si la implementación MODBUS es TCP, RTU o ASCII:
- Function code (1 byte Código de operación): Indica el tipo de operación que queremos realizar sobre el servidor. Las operaciones se pueden clasificar en dos tipos: - De lectura / escritura en memoria: para consultar o modificar el estado de los registros del mapa de memoria del servidor. - Ordenes de control del servidor: para realizar alguna actuación sobre el servidor. El código de operación puede tomar cualquier valor comprendido entre el 0 y el 127 (el bit de más peso 0x80 se reserva para marcar la respuesta como excepción). Cada código se corresponde con una determinada operación. Algunos de estos códigos se consideran estándar y son aceptados e interpretados por igual por todos los dispositivos que dicen ser compatibles con MODBUS, mientras que otros códigos son implementaciones propias de cada fabricante. Es decir que algunos fabricantes realizan implementaciones propias de estos códigos “no estándar”. Los más utilizados son el 1,2,3,4,5,6,7,15 y 16. El servidor utiliza también el código de operación de la trama de respuesta para confirmar si la operación se ha ejecutado correctamente o no. Si ha ido bien, el servidor responde con el mismo código de operación que se le ha enviado, mientras que si se ha producido algún error, responde también con el mismo código de operación pero con su bit de más peso a 1 (0x80) y un byte en el campo de datos indicando el código de error / excepción que ha tenido lugar. - Data (n bytes Dirección, datos y subfunciones): Este campo contiene la información necesaria para realizar la operación indicada por el código de operación. Cada operación necesitará de unos parámetros u otros, por lo que el contenido y el número de bytes de este campo variará según la operación. Un campo frecuente en este bloque es la dirección MODBUS accedida. Las respuestas del servidor pueden tener o no campo de datos dependiendo de la operación. Tal como se indica en el apartado dedicado al Function code, en los casos en que se produzca algún error, el servidor responderá con una trama de error / excepción. Cuando se produce un error en la ejecución de un comando en el servidor, este responde con una trama de error / excepción poniendo a 1 el bit de más peso del codigo de función (0x80). Con este bit el cliente sabe que se ha producido un error en el servidor al intentar ejectuar el comando enviado, pero para obtener mas detalle sobre el tipo de error, ha de comprobar el campo de datos que sigue al campo Function code:
Un equipo servidor MODBUS puede exponer hasta 4 bancos de direcciones MODBUS cada uno de los cuales se encuentra dedicado a un determinado tipo de datos, con direcciones que van de 1 a n en cada caso (codificados de 0 a n-1 en las tramas). Estos son los cuatro bancos de direcciones o tablas visibles en las comunicaciones MODBUS:
- Discretes Input (banco de Entradas Discretas o tambien Digital Input): 1 direccion -> 1 bit único de solo lectura. Este tipo de datos puede ser proporcionado por un sistema de E/S y leido desde la aplicación. Cada dirección del banco corresponde a 1 booleano. Las direcciones de este rango se suelen acceder con la función 2 . - Coils (banco de Bobinas o también Digital Outputs): 1 direccion -> 1 bit único de lectura-escritura. Este tipo de datos puede ser modificado por un programa de aplicación y publicado por un dispositivo de E/S. Cada dirección del banco corresponde a 1 booleano. Las direcciones de este rango se suelen acceder mediante las funciones 1 (lectura), 5 (escritura), 15 (escritura múltiple). - Input Registers (banco de Registros de Entrada o también Analog Inputs): 1 direccion -> 1 palabra de 16 bits de solo lectura. Este tipo de datos puede ser proporcionado por un sistema de E/S y leido desde la aplicación. Cada dirección del banco corresponde a un valor de 2 bytes. Las direcciones de este rango se acceden mediante la función 4 (lectura). - Holding Registers (banco de Registros de Retención o también Analog Outputs): 1 direccion -> 1 palabra de 16 bits de lectura-escritura. Este tipo de datos puede ser modificado por un programa de aplicación y publicado por un dispositivo de E/S. Cada dirección del banco corresponde a un valor de 2 bytes. Se acceden con las funciones 3 (lectura), 6 (escritura) o 16 (escritura múltiple). Tal como se indica, en los bancos del tipo Discretes Input y Coils cada dirección expuesta corresponde a un booleano (1bit). En los bancos dedicados a Input Registers o Holding Registers cada dirección expuesta son 16 bits. Luego internamente, tanto el equipo servidor como el cliente, pueden organizar y mapear esos datos en un único rango de direcciones. También pueden reagrupar, dividir e interpretar los datos como el tipo de datos que le convenga. El acceso a uno u otro banco por parte del cliente se realiza dependiendo del comando MODBUS utilizado (cada Funcion Code lleva implicito el acceso a un banco u otro del servidor MODBUS). Es obvio que todos los datos manejados a través de MODBUS (bits, registros) deben estar ubicados en la memoria de la aplicación del dispositivo, pero la dirección física interna en la memoria o en la aplicación no debe confundirse con la direccion MODBUS del banco usada para hacer referencia a los datos en las comunicaciones. Es la aplicación la que debe vincular las direcciones de memoria internas con las direcciones de los diferentes bancos MODBUS. ![]() Por tanto la preasignación entre el modelo de direcciones de datos MODBUS y de la aplicación del dispositivo es totalmente libre y específica del proveedor / fabricante del dispositivo, aunque tradicionalmente muchos dispositivos mapeaban los 4 bacos anteriores a estos rangos de direcciones internos de aplicación: @00001-10000 : para datos de banco Coils. @10001-20000 : para datos de banco Discretes Input. @20001-30000 : el protocolo MODBUS estándar no hace uso de este rango de direcciones. @30001-40000 : para datos de banco Input Registers. @40001-50000 : para datos de banco Holding Registers. El tamaño / tipo de dato a nivel de aplicación asociado a cada dato MODBUS puede ser también el que se considere. Al establecer la dirección de una variable u otro elemento en el mapa de direcciones MODBUS, direccionamos con 1 unidad menos a la del registro al que queremos acceder, de manera que si p.ej. quisiéramos acceder al relé @ 127d, lo haríamos situando el valor 126d en el byte del campo de dirección. Otros ejemplos: - El relé número 1 de un controlador se direccionaría con el valor 0000 en el campo de dirección de un mensaje MODBUS. - El relé 0x007F (127d) de un controlador se direccionaría con el valor 0x007E (126d) en el campo de dirección de un mensaje MODBUS. - El Holding Register 40001 se accedería situando el valor 0000 en el campo de dirección del mensaje. Como se puede ver el código de función de acceso a los Holding Registers lleva implícito el acceso a la dirección ‘4XXXX’. - El Holding Register 40108 es accedido leiendo de la dirección 0x006B (107d). Algunos fabricantes expresan la dirección de forma compuesta, separando la dirección de palabra y la dirección de bit: p.ej word 0x30 bit 1 En C: “… #definePOLY0xA001 unsignedcrc16(char*buf,intlen) { char i; unsigned crc; for(crc=0xFFFF;len!=0;len--){
crc^=*buf++; for(i=0;i<8;i++){ if(crc&0x0001){ crc=(crc>>1)^POLY; }else{ crc>>=1; } } } return(crc); } …”
En C#:
“… uint crc16(byte [ ] buf , uint len) { uint POLY=0xA001; int crc; uint i; uint j; j = 0; for (crc = 0xFFFF; len != 0; len --){ crc ^= buf[j]; j++; for (i = 0; i < 8; i ++){ if ((crc & 0x0001)>0){ crc = (crc >> 1) ^ POLY; }else{ crc >>= 1; } } } return (crc); } …” Los siguientes ejemplos corresponden a dos tramas MODBUS (ADU + PDU) una en modo ASCII y otra en modo RTU, de petición de lectura de 3 registros del servidor y la correspondiente respuesta :
-PETICION de 3 datos: |
|||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
| -RESPUESTA con los 3 datos: |
Los siguientes códigos son algunos de los códigos de función MODBUS más extendidos, soportados por la mayoría de dispositivos que dicen cumplir con las especificaciones del estándar MODBUS: - Función 1 Read Coil Status - Función 2 Read Input Status - Función 3 Read Holding Registers - Función 4 Read Input Registers - Función 5 Force Single Coil - Función 6 Preset Single Register - Función 7 Read Exception Status - Función 8 Diagnostics - Función 9 Program 484 - Función 10 Poll 484 - Función 11 Fetch Communication Event Counter - Función 12 Fetch Communication Event Log - Función 13 Program Controller - Función 14 Poll Controller - Función 15 Force Multiple Coils - Función 16 Preset Multiple Registers - Función 17 Report Slave ID - Función 18 Program 884/M84 - Función 19 Reset Comm. Link - Función 20 Read General Reference - Función 21 Write General Reference - Función 22 Mask Write 4X Register - Función 23 Read/Write 4X Registers - Función 24 Read FIFO Queue
Función 1 o 2 (1 Read Coil Status - 2 Read Input Status):
Permite la lectura del estado de las DIs (banco de Entradas Discretas o tambien Digital Input) o DOs (banco de bits de DOs) del servidor. Para ello el cliente solicita el número de bits que desea leer a partir de una determinada dirección. Cada dirección apunta a un registro de 1 bit con el estado del la entrada o salida digital. El servidor responde indicando el número de bits consecutivos que retorna y sus valores. En la trama de respuesta se aprovechan todos los bits del byte, y puede haber hasta 256 bytes. MODBUS RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: 0x01 o 0x02 PDU: Dirección del registro (de 1 bit) a leer H PDU: Dirección del registro (de 1 bit) a leer L PDU: Nº de bits que se desea leer H PDU: Nº de bits que se desea leer L ADU: CRC(16): H ADU: CRC(16): Respuesta del servidor:
Función 3 o 4 (3 Read Holding Registers – 4 Read Input Registers) :
Permite la lectura del valor de las AIs (banco de Registros de Entrada o también Analog Inputs) o AOs (banco de Bobinas o también Digital Outputs) del servidor. El cliente indica la dirección base y número de palabras a leer a partir de esta dirección, mientras que el servidor indica en la respuesta el número bytes retornados, seguido de estos valores. Aunque en realidad se está escribiendo en el rango de registros o valores numéricos , los registros son direccionados a partir de la dirección 0.Cada palabra o dato escrito mediante esta funcion se corresponde con 2 bytes ¡¡¡(1 word = 16 bits). MODBUS RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: 0x03 o 0x04 PDU: Dirección del registro a leer H PDU: Dirección del registro a leer L PDU: Nº de datos que se desea leer: max 128 datos (2 bytes por dato) ADU: CRC(16): H ADU: CRC(16): L Respuesta del servidor: ADU: NºServidor PDU: Código Operación: 0x03 o 0x04 PDU: Nº de bytes leidos: 1 byte PDU: Datos recibidos: ¿ max 128 datos (2 bytes por dato) ADU: CRC(16): H ADU: CRC(16): L Ej 1 MODBUS RTU: P:[01][03][01][00][00][06][C4][34] R:[01][03][0C][20][81][00][00][00][00][00][00][00][00][1C][01][76][F1] Ej 2 MODBUS RTU: P:[0A][04][00][00][00][0A][71][76] ADU: NºServidor / periférico 10 : [0A] PDU: Código Operación:.000 0100 = Function Code: Read Input Registers 4 : [04] PDU: Dirección del registro a leer. Registro donde se va a comenzar la lectura 0 : [00][00] PDU: Nº de datos que se desea leer: numero de registros a leer: 10 : [00][0A] ADU: CRC [71][76] R:[0A][04][14][00][00][08][4D][00][00][23][28][00][00][0F][A0][00][00][00][90][00][00][00][60][CB][2E] ADU: NºServidor / periférico que responde 10 : [0A] PDU: Código Operación:.000 0100 = Function Code: Read Input Registers 4 : [4] PDU: Nºdatos recibidos: Número de bytes recibidos 20 : [14]. PDU: Datos recibidos: 00 00 08 4D : V1x 10 (registro 00 Hex) con valor en decimal 212,5 V 00 00 23 28 : mA 1, en decimal 9000 mA 00 00 0F A0 : W 1, en decimal 4000 W 00 00 00 90 : varL 1, en decimal 144 varL 00 00 00 60 : PF1 x 100, en decimal 96 ADU: CRC(16): [CB][2E] Ej 3 MODBUS RTU: P:[01][03][00][30][00][10][44][09] ADU: NºServidor / periférico 1 : [01] PDU: Código Operación:.000 0011 = Function Code: Read Holding Registers 3 : [03] PDU: Dirección del registro a leer. Registro donde se va a comenzar la lectura 48 : [00][30] PDU: Nº de datos que se desea leer: numero de registros a leer: 16 : [00][10] ADU: CRC [44][09] R:[01][03][20][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][27][0F][16][18][00][00][2E][DF][00][00][42][CF] ADU: NºServidor / periférico 1 : [01] PDU: Código Operación:.000 0011 = Function Code: Read Holding Registers 3 : [03] PDU: Nºdatos recibidos: Número de bytes recibidos 32 : [20]. PDU: Datos recibidos: (32 bytes a 2 bytes por registro: 16 registros 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 0F 16 18 00 00 2E DF 00 00 ADU: CRC(16): [42][CF] MODBUS TCP: Petición del cliente: ADU: Identificador de transacción H ADU: Identificador de transacción L ADU: Identificador de protocolo H ADU: Identificador de protocolo L ADU: Longitud (in bytes) H ADU: Longitud (in bytes) L ADU: NºServidor PDU: Código Operación: 0x03 o 0x04 PDU: Nº de datos que se desea leer max 128 (2 bytes por dato) a leer H PDU: Nº de datos que se desea leer max 128 (2 bytes por dato) a leer L Respuesta del servidor: ADU: Identificador de transacción H ADU: Identificador de transacción L ADU: Identificador de protocolo H ADU: Identificador de protocolo L ADU: Longitud (in bytes) H ADU: Longitud (in bytes) L ADU: NºServidor PDU: Código Operación: 0x03 o 0x04 PDU: Nº de bytes leidos: 1 byte PDU: Datos: max 128 datos (2 bytes por dato = 256 bytes) Ej 1 MODBUS TCP: P:[00][04][00][00][00][06][01][04][00][20][00][01] ADU: Identificador de transacción: 4 : [00][04] ADU: Identificador de protocolo: 0 : [00][00] ADU: Longitud: 6 : [00][06] ADU: NºServidor: 1 : [01] PDU: .000 0100 = Function Code: Read Input Registers (4) PDU: Dirección del registro: 32 : [00][20] PDU: Datos a leer (words): 1: [00][01] R:[00][04][00][00][00][05][01][04][02][00][00] ADU: Identificador de transacción: 4 : [00][04] ADU: Identificador de protocolo: 0 : [00][00] ADU: Longitud: 5 : [00][05] ADU: NºServidor: 1 PDU: .000 0100 = Function Code: Read Input Registers (4) : [04] PDU: Byte Count: 2 : [02] PDU: Datos (Words): [00][00] Función 5 (Force Single Coil): Permite modificar el estado de una DO del servidor. Es decir mediante este comando podemos modificar bits de alguna de las variables internas del servidor u ordenar la ejecución o activación de un mando. Actúa sobre el banco de Bobinas o Digital Outputs ¡¡¡(pueden ser mandos, relés, salidas digitales o simples bits en memoria). El cliente especifica la dirección del bit o mando que quiere modificar seguido de 0x00 para ponerlo a 0 o 0xFF para ponerlo a 1. El servidor responde con una trama similar indicando la dirección que ha modificado y el valor que ha establecido en el bit o mando. Cada dato escrito mediante esta funcion se corresponde con 1 bit. MODBUS RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit a escribir H PDU: Dirección del bit a escribir L PDU: Estado deseado para el bit: 0xXX (0x00 : 0 , 0xFF : 1) + ¿0x00 padding? ADU: CRC(16): H ADU: CRC(16): L Respuesta del servidor: ADU: NºServidor PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit escrito H PDU: Dirección del bit escrito L PDU: Estado del bit escrito: 0xXX (0x00 : 0 , 0xFF : 1) + ¿0x00 padding? ADU: CRC(16): H ADU: CRC(16): L Ej 1 MODBUS RTU: P:[01][05][00][01][FF][00][DD][FA] ADU: NºServidor 1 : [01] PDU: Código Operación 5: [05] PDU: Dirección del bit a escribir 1 : [00][01] PDU: Estado deseado para el bit: 1 : [FF] (0x00 : 0 , 0xFF : 1) + ¿[00] padding? ADU: CRC(16): [DD][FA] R:[01][05][00][00][FF][00][8C][3A] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit escrito 1 : [00][01] PDU: Estado del bit escrito 1 : [FF] (0x00 : 0 , 0xFF : 1) + ¿[00] padding? ADU: CRC(16): [8C][3A] Ej 2 MODBUS RTU: P:[01][05][00][00][00][00][CD][CA] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit a escribir 0 : [00][00] PDU: Estado deseado para el bit 0 : [00] (0x00 : 0 , 0xFF : 1) + ¿[00] padding? ADU: CRC(16): [CD][CA] R:[01][05][00][01][00][00][CD][CA] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit escrito 0 : [00][00] PDU: Estado del bit escrito: [00] (0x00 : 0 , 0xFF : 1) + ¿ [00] padding? ADU: CRC(16):[CD][CA] MODBUS TCP: Petición del cliente: ADU: Identificador de transacción H ADU: Identificador de transacción L ADU: Identificador de protocolo H ADU: Identificador de protocolo L ADU: Longitud (in bytes) H ADU: Longitud (in bytes) L ADU: NºServidor PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit a escribir H PDU: Dirección del bit a escribir L PDU: Estado deseado para el bit: 0xXX (0x00 : 0 , 0xFF : 1) + ¿0x00 padding? Respuesta del servidor: ADU: Identificador de transacción H ADU: Identificador de transacción L ADU: Identificador de protocolo H ADU: Identificador de protocolo L ADU: Longitud (in bytes) H ADU: Longitud (in bytes) L ADU: NºServidor PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit escrito H PDU: Dirección del bit escrito L PDU: Estado del bit escrito: 0xXX (0x00 : 0 , 0xFF : 1) + ¿0x00 padding? Ej 1 MODBUS TCP: P:[00][03][00][00][00][06][01][05][00][00][00][00] ADU: Identificador de transacción 3 : [00][03] ADU: Identificador de protocolo 0 : [00][00] ADU: Longitud (in bytes) 6 : [00][06] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit a escribir [00][00] PDU: Estado deseado para el bit: 0 ([00] : 0 , [FF] : 1) + ¿ [00] Padding ? R:[00][03][00][00][00][06][01][05][00][00][00][00] ADU: Identificador de transacción 3 : [00][03] ADU: Identificador de protocolo 0 : [00][00] ADU: Longitud (in bytes) 6 : [00][06] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0101 = Function Code: Write Single Coil (5) : [05] PDU: Dirección del bit escrito 0 : [00][00] PDU: Estado del bit escrito 0 : [00] ([00] : 0 , [FF] : 1) + ¿ [00] Padding ? Función 6 (Preset Single Register) : Permite la escritura en las AOs del servidor (ya sea una señal o valor interno del equipo), y por tanto actúa sobre el banco de Registros de Retención o también Analog Outputs. Deberemos indicar la dirección del valor que queremos modificar y la magnitud que queremos asignarle. Luego el servidor debería responder con la dirección del dato que ha modificado y el valor que le ha asignado, que debería coincidir con el enviado. Cada dato escrito mediante esta funcion se corresponde con 2 bytes ¡¡¡(1 word = 16 bits). MODBUS RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato a escribir H PDU: Dirección del dato a escribir L PDU: Valor del dato a escribir H PDU: Valor del dato a escribir L ADU: CRC(16): H ADU: CRC(16): L Respuesta del servidor: ADU: NºServidor PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato escrito H PDU: Dirección del dato escrito L PDU: Valor del registro tras la escritura H PDU: Valor del registro tras la escritura L ADU: CRC(16): H ADU: CRC(16): L Ej 1 MODBUS RTU: P:[01][06][01][F1][00][02][58][04] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato a escribir 497 : [01][F1] PDU: Valor del dato a escribir 2: [00][02] ADU: CRC(16): [58][04] R:[01][06][01][F1][00][02][58][04] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato escrito 497 : [01][F1] PDU: Valor del registro tras la escritura: [00][02] ADU: CRC(16): [58][04] MODBUS TCP: Petición del cliente: ADU: Identificador de transacción H ADU: Identificador de transacción L ADU: Identificador de protocolo H ADU: Identificador de protocolo L ADU: Longitud (in bytes) H ADU: Longitud (in bytes) L ADU: NºServidor PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato a escribir H PDU: Dirección del dato a escribir L PDU: Valor del dato a escribir H PDU: Valor del dato a escribir L Respuesta del servidor: ADU: Identificador de transacción H ADU: Identificador de transacción L ADU: Identificador de protocolo H ADU: Identificador de protocolo L ADU: Longitud (in bytes) H ADU: Longitud (in bytes) L ADU: NºServidor PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato escrito H PDU: Dirección del dato escrito L PDU: Valor del registro tras la escritura H PDU: Valor del registro tras la escritura L Ej 1 MODBUS TCP: P:[00][03][00][00][00][06][01][06][00][20][00][02] ADU: Identificador de transacción 3 : [00][03] ADU: Identificador de protocolo 0 : [00][00] ADU: Longitud (in bytes) 6 : [00][06] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato a escribir 32 : [00][20] PDU: Valor del dato a escribir: [00][02] R:[00][03][00][00][00][06][01][06][00][20][00][02] ADU: Identificador de transacción 3 : [00][03] ADU: Identificador de protocolo 0 : [00][00] ADU: Longitud (in bytes) 6 : [00][06] ADU: NºServidor 1 : [01] PDU: Código Operación: .000 0110 = Function Code: Write Single Register (6) : [06] PDU: Dirección del dato escrito 32 : [00][20] PDU: Valor del registro tras la escritura 2: [00][20] Función 7 (Read Exception Status) : Permite la lectura rápida de un byte fjo de un servidor, que generalmente es el de excepción y que informa del estado del equipo. No tiene dirección del byte debido a que siempre se lee el byte de excepción (interno del servidor): MODBUS RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: .000 0111 = Function Code: Read Exception Status (7) ADU: CRC(16): H ADU: CRC(16): L Petición del cliente: ADU: NºServidor PDU: Código Operación: .000 0111 = Function Code: Read Exception Status (7) PDU: Valor del byte de excepcion ADU: CRC(16): H ADU: CRC(16): L Función 15 (Force Multiple Coils): Permite la modificación simultanea de varios bits de DOs en el servidor, pasándolos a OFF (‘0’) o a ON (‘1’) según convenga. Actúa sobre el banco de memoria de las DOs. Así en el comando se pasan la dirección inicial (dirección del primer bit o mando a modificar) y la cantidad y estado de cada uno de los sucesivos mandos (bits) a modificar. Modo RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: .000 1111 = Function Code: Force Multiple Coils (15) PDU: Dirección base de los mandos (bits) H PDU: Dirección base de los mandos (bits) L PDU: Cantidad de mandos (bits) H PDU: Cantidad de mandos (bits) L PDU: Numero de bytes enviados con el estado de los mandos (bits) H PDU: Numero de bytes enviados con el estado de los mandos (bits) L PDU: Estado de los 8 primeros mandos (bits) a modificar , PDU: Estado de los 8 siguientes mandos (bits) a modificar , ... PDU: Estado de los 8 últimos mandos (bits) a modificar ADU: CRC(16): H L Aunque el estado de las DOs se especifica bit a bit, las tramas se componen de bytes, y esto obliga a enviar los estados en grupos de 8. El servidor no debería hacer caso a los bits sobrantes, es decir, no debería considerar los que queden por encima del último bit indicado en el campo “cantidad de mandos a modificar”. Así, si quisiéramos modificar 12 mandos o relés a partir de la dirección 7, indicaríamos como dirección origen la dirección 7, como cantidad de mandos a modificar 12, y en el campo de estado de mandos: 0x3C , 0x0B (el servidor no considerará los que queden por encima del 12o bit) Relé: 14 13 12 11 10 09 08 07 - 22 21 20 19 18 17 16 15 Bits: 0 1 1 1 1 0 0 0 X X X X 1 0 1 1 Respuesta del servidor: ADU: NºServidor PDU: Código Operación: .000 1111 = Function Code: Force Multiple Coils (15) PDU: Dirección base de los mandos (bits) H PDU: Dirección base de los mandos (bits) L PDU: Cantidad de mandos forzados (bits) H PDU: Cantidad de mandos forzados (bits) L ADU: CRC(16): H L Función 16 (Preset multiple registers): Permite la escritura en un grupo de registros consecutivos del banco de AOs. Se debe especificar la dirección a partir de la que queremos comenzar a actualizar valores, el número de valores que queremos actualizar, y la lista de valores que queremos asignar a estos registros. Modo RTU: ADU: NºServidor PDU: Código Operación: 0x10 PDU: Dirección base de los datos: 2 bytes PDU: Número de datos H PDU: Número de datos L PDU: Valor del dato 0: 2 bytes PDU: Valor del dato 1: 2 bytes ... PDU: Valor del dato n-1: 2 bytes ADU: CRC(16): H ADU: CRC(16): L Respuesta del servidor: ADU: NºServidor PDU: Código Operación: 0x10 PDU: Dirección base de los datos: 2 bytes PDU: Número de datos H PDU: Número de datos L ADU: CRC(16): H ADU: CRC(16): L Función 20 (Read General Reference): Retorna el contenido de los regitros de la Extended Memory (@6XXXX). En la trama se envía la dirección del servidor, el código de función, el número de bytes que se va a leer y los bytes de comprobación de error. En los datos se establece el grupo o grupos o referencias a leer. Cada grupo se define en un campo "sub-request" que contiene: - Reference type: 1 byte (debe ser 6) - Extended Memory file number: 2 bytes (0x01 a 0x0A) - La direccion del "fichero" a partir de la que queremos comenzar a leer: 2 bytes - La cantidad de registros a leer: 2 bytes Los datos a leer seguidos de los demas campos no debe superar la longitud máxima permitida en los mensajes MODBUS, es decir los 256 bytes. Modo RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: .001 0100 = Function Code: Read General Reference (20) : [14] PDU: Byte Count 0x0E PDU: Data: Sub–Req 1, Reference Type 0x06 PDU: Data: Sub–Req 1, File Number Hi 0x00 PDU: Data: Sub–Req 1, File Number Lo 0x04 PDU: Data: Sub–Req 1, Starting Addr Hi 0x00 PDU: Data: Sub–Req 1, Starting Addr Lo 0x01 PDU: Data: Sub–Req 1, Register Count Hi 0x00 PDU: Data: Sub–Req 1, Register Count Lo 0x02 PDU: Data: Sub–Req 2, Reference Type 0x06 PDU: Data: Sub–Req 2, File Number Hi 0x00 PDU: Data: Sub–Req 2, File Number Lo 0x03 PDU: Data: Sub–Req 2, Starting Addr Hi 0x00 PDU: Data: Sub–Req 2, Starting Addr Lo 0x09 PDU: Data: Sub–Req 2, Register Count Hi 0x00 PDU: Data: Sub–Req 2, Register Count Lo 0x02 ADU: CRC(16) Respuesta del servidor: ADU: NºServidor PDU: Código Operación: .001 0100 = Function Code: Read General Reference (20) : [14] PDU: Byte Count 0x0C PDU: Data: Sub–Res 1, Byte Count 0x05 PDU: Data: Sub–Res 1, Reference Type 0x06 PDU: Data: Sub–Res 1, Register Data Hi 0x0D PDU: Data: Sub–Res 1, Register Data Lo 0xFE PDU: Data: Sub–Res 1, Register Data Hi 0x00 PDU: Data: Sub–Res 1, Register Data Lo 0x20 PDU: Data: Sub–Res 2, Byte Count 0x05 PDU: Data: Sub–Res 2, Reference Type 0x06 PDU: Data: Sub–Res 2, Register Data Hi 0x33 PDU: Data: Sub–Res 2, Register Data Lo 0xCD PDU: Data: Sub–Res 2, Register Data Hi 0x00 PDU: Data: Sub–Res 2, Register Data Lo 0x40 ADU: CRC(16) Función 21 (Write General Reference): Modifica el contenido de los registros de la Extended Memory Esta función permite trabajar en grupos de registros que no tienen porque ser contiguos (internamente sí que han de ser contiguos). Cada grupo se define en un campo "sub-request" que contiene: - Reference type: 1 byte (debe ser 6) - Extended Memory file number: 2 bytes (0x01 a 0x0A) - La direccion del "fichero" a partir de la que queremos comenzar a leer: 2 bytes - La cantidad de registros a leer: 2 bytes Los datos a leer seguidos de los demas campos no debe superar la longitud máxima permitida en los mensajes MODBUS, es decir los 256 bytes. Modo RTU: Petición del cliente: ADU: NºServidor PDU: Código Operación: .001 0101 = Function Code: Write General Reference (21) : [15] PDU: Byte Count 0x0D PDU: Data: Sub–Req 1, Reference Type 0x06 PDU: Data: Sub–Req 1, File Number Hi 0x00 PDU: Data: Sub–Req 1, File Number Lo 0x04 PDU: Data: Sub–Req 1, Starting Addr Hi 0x00 PDU: Data: Sub–Req 1, Starting Addr Lo 0x07 PDU: Data: Sub–Req 1, Register Count Hi 0x00 PDU: Data: Sub–Req 1, Register Count Lo 0x03 PDU: Data: Sub–Req 1, Register Data Hi 0x06 PDU: Data: Sub–Req 1, Register Data Lo 0xAF PDU: Data: Sub–Req 1, Register Data Hi 0x04 PDU: Data: Sub–Req 1, Register Data Lo 0xBE PDU: Data: Sub–Req 1, Register Data Hi 0x10 PDU: Data: Sub–Req 1, Register Data Lo 0x0D ADU: CRC(16) Respuesta del servidor: ADU: NºServidor PDU: Código Operación: .001 0101 = Function Code: Write General Reference (21) : [15] PDU: Byte Count 0x0D PDU: Data:Sub–Req 1, Reference Type 0x06 PDU: Data:Sub–Req 1, File Number Hi 0x00 PDU: Data:Sub–Req 1, File Number Lo 0x04 PDU: Data:Sub–Req 1, Starting Addr Hi 0x00 PDU: Data:Sub–Req 1, Starting Addr Lo 0x07 PDU: Data:Sub–Req 1, Register Count Hi 0x00 PDU: Data:Sub–Req 1, Register Count Lo 0x03 PDU: Data:Sub–Req 1, Register Data Hi 0x06 PDU: Data:Sub–Req 1, Register Data Lo 0xAF PDU: Data:Sub–Req 1, Register Data Hi 0x04 PDU: Data:Sub–Req 1, Register Data Lo 0xBE PDU: Data:Sub–Req 1, Register Data Hi 0x10 PDU: Data:Sub–Req 1, Register Data Lo 0x0D ADU: CRC(16) | ||||||||||||||||||||||||||||||||||||||||||||||||||