Módulo smartCORE ModBus
Descripción
El módulo "modbus" lee principalmente los registros ModBus de los nodos ModBus. Estos nodos pueden estar conectados
- mediante una conexión serie (ModBus/RTU)
- mediante TCP (ModBus/TCP)
Interfaces y protocolos utilizados
- ModBus
Configuración JSON
En la sección siguiente se describe la configuración JSON completa del módulo y se explican los distintos parámetros.
Configuración de ejemplo
A continuación se muestra una configuración de ejemplo de ModBus/TCP:
{
"module": "ModBus",
"comment": "ModBus/TCP config",
"factory": "modbus",
"config": {
"version": 1,
"type": "modbus",
"enable": true,
"pollCycleInMilliseconds": 1000,
"transport": {
"type": "tcp",
"ipAddress": "192.168.0.1",
"ipPortNumber": 502,
"timeoutInMilliseconds": 200
},
"devices": [
{
"enable": true,
"deviceName": "Device Name",
"deviceAddress": 1,
"readChannels": [
{
"name": "Channel Name",
"address": 49152,
"registerType": "HoldingReg",
"registerFormat": "REAL",
"byteOrder": "ABCD",
"bitOffset": 0,
"unit": "",
"scale": 1.0,
"offset": 0.0
}
]
}
]
}
}
Parámetros globales del módulo
| Nombre del parámetro | Obligatorio | Tipo de datos | Rango de valores recomendado | Valor por defecto | Descripción |
|---|---|---|---|---|---|
| version | SÍ | INT | 1 | Versión del protocolo ModBus | |
| type | SÍ | STRING | "modbus" | Interfaz serie para la comunicación | |
| enable | SÍ | BOOL | true | Interruptor para la producción de los datos en smartCHANNELs | |
| pollCycleInMilliseconds | SÍ | INT | 1 - | Intervalo de consulta [ms] de los accesos ModBus | |
| transport | SÍ | JSON Objekt | Configuración de la capa de transporte ModBus (véase más abajo) | ||
| devices | SÍ | JSON Array de objetos JSON | Lista de los nodos ModBus | ||
| pollCycleInNanoseconds | No | INT | 1 - | 100000000 | Intervalo de consulta [ns]. Si la clave está establecida, tiene prioridad sobre pollCycleInMilliseconds. Si faltan ambas, se utilizan 100 ms |
| enableInternalDataReduction | No | BOOL | true, false | false | Añade a cada canal generado una reducción de datos (absTolerance 0.0, timeoutMs 60000): los valores sin cambios no se escriben, pero sí se vuelven a escribir como máximo tras 60 s |
| autoGroup | No | BOOL | true, false | true | Agrupa automáticamente los registros adyacentes de un dispositivo en bloques de registros que se leen en una sola transacción (véase Bloques de registros) |
| autoGroupAllowGaps | No | BOOL | true, false | false | Permite huecos dentro de un bloque: los registros no necesarios se leen igualmente en lugar de separar el bloque |
| maxRegisterGroup | No | INT | 1 - 125 | 125 | Número máximo de registros de un bloque. Los valores mayores se limitan a 125 con una advertencia; ModBus no admite más en una transacción |
| useF23withoutOutputs | No | BOOL | true, false | false | Utiliza el código de función 23 (Read/Write Multiple Registers) también cuando no hay nada que escribir (a partir de smartCORE 2.12) |
| minimalChannelAlarmCount | No | INT | 1 - | 2 | Número de intentos fallidos inmediatamente consecutivos tras el cual se desactiva un bloque de registros (véase Timeout y desactivación) |
| retryAfterBlockFailS | No | INT | 0 - | 0 | Tiempo de espera [s] tras el cual se vuelve a intentar un bloque de registros desactivado. 0 = sin nuevo intento, el bloque permanece desactivado durante la medición (a partir de smartCORE 2.12) |
| workloadAsChannel | No | BOOL | true, false | false | Crea un canal de diagnóstico que registra la carga del bus |
| workloadChannelBuffersize | No | INT | 1 - | 100 | Tamaño del búfer del canal de carga del bus en elementos |
| workloadChannel | No | STRING o JSON Objekt | Nombre o definición completa del canal de carga del bus |
Parámetros de transporte específicos de ModBus/TCP ("transport")
| Nombre del parámetro | Obligatorio | Tipo de datos | Rango de valores recomendado | Valor por defecto | Descripción |
|---|---|---|---|---|---|
| type | SÍ | STRING | "tcp" | Selección de ModBus/TCP | |
| ipAddress | SÍ | STRING | Dirección IP válida | Dirección IP del dispositivo ModBus | |
| ipPortNumber | SÍ | INT | Número de puerto IP válido | Número de puerto IP del dispositivo ModBus (si no se especifica otra cosa, debe establecerse en 502) | |
| timeoutInMilliseconds | SÍ | INT | 1 - | Timeout [ms] de la conexión TCP (si no se especifica otra cosa, debe establecerse en 200) |
Parámetros de transporte específicos de ModBus/RTU ("transport")
| Nombre del parámetro | Obligatorio | Tipo de datos | Rango de valores recomendado | Valor por defecto | Descripción |
|---|---|---|---|---|---|
| type | SÍ | STRING | "rtu" | Selección de ModBus/RTU | |
| baudRate | SÍ | INT | Velocidad en baudios ModBus válida | Velocidad en baudios de la interfaz serie | |
| dataBits | SÍ | INT | 5 - 8 | Bits de datos de la interfaz serie | |
| parity | SÍ | STRING | "no", "even", "odd" | Paridad de la interfaz serie | |
| stopBits | SÍ | DOUBLE | 1.0, 1.5, 2.0 | Bits de parada de la interfaz serie | |
| portName | SÍ | STRING | Archivo de dispositivo válido | Archivo de dispositivo de la interfaz serie | |
| timeoutInMilliseconds | SÍ | INT | 1 - | Timeout de respuesta [ms] de la conexión serie. Limita cuánto tiempo se espera la respuesta de un nodo y se pasa a libmodbus como modbus_set_response_timeout() | |
| deviceTimeoutInMilliseconds | No | INT | 0 - | 0 | Timeout adicional [ms] entre las consultas a distintos nodos ModBus |
| readDelayMs | No | INT | 0 - | Sobrescribe el silencio de trama t3.5 [ms] que se respeta antes de cada solicitud. Sin la clave se calcula a partir de la velocidad en baudios (véase Silencio de trama) |
Parámetros de dispositivo ModBus ("devices")
| Nombre del parámetro | Obligatorio | Tipo de datos | Rango de valores recomendado | Valor por defecto | Descripción |
|---|---|---|---|---|---|
| enable | SÍ | BOOL | true | Interruptor para activar el dispositivo ModBus | |
| deviceName | SÍ | STRING | Nombre del dispositivo ModBus | ||
| deviceAddress | SÍ | INT | 1 - | Dirección del dispositivo ModBus | |
| readChannels | SÍ | JSON Array de objetos JSON | véase más abajo |
Las claves autoGroup, autoGroupAllowGaps, maxRegisterGroup y useF23withoutOutputs
pueden indicarse además por dispositivo y sobrescriben allí el valor global.
Configuración de canales ModBus ("readChannels")
| Nombre del parámetro | Obligatorio | Tipo de datos | Rango de valores recomendado | Valor por defecto | Descripción |
|---|---|---|---|---|---|
| name | SÍ | STRING | Nombre del smartCHANNEL | ||
| address | SÍ | INT | Dirección del registro ModBus | ||
| registerType | SÍ | STRING | Tipo de registro ModBus válido | Tipo del registro ModBus ("InputReg", "HoldingReg", "Coil", "Status", "0x17" (solo lectura)) | |
| registerFormat | SÍ | STRING | Formato de registro ModBus válido | Formato del registro ModBus ("I8","I16","I32","I64","UI8","UI16","UI32","UI64","REAL","BOOL") | |
| byteOrder | SÍ | STRING | véase más abajo | Orden de los bytes del valor, véase Orden de los bytes | |
| bitOffset | SÍ | UINT | Desplazamiento de bits (offset) del valor que se va a interpretar | ||
| unit | SÍ | STRING | Unidad del smartCHANNEL | ||
| scale | SÍ | DOUBLE | Escalado del smartCHANNEL | ||
| offset | SÍ | DOUBLE | Desplazamiento (offset) del smartCHANNEL | ||
| enable | No | BOOL | true, false | true | Un canal con false no se crea ni se lee |
| pollingIntervalMultiplicator | No | INT | 1 - | 1 | El bloque de registros de este canal solo se lee en cada n-ésimo ciclo de consulta |
| registerGroup | No | INT | 0 - | Asigna el canal a un bloque de registros manualmente. Los canales con el mismo número forman un bloque y quedan excluidos de la agrupación automática |
Configuración de canales ModBus ("readChannelGroups")
Como alternativa, varias configuraciones de canal pueden agruparse en una matriz JSON, de modo que los registros ModBus en los que se basa este grupo puedan leerse en un único paso (si el tipo de registro es idéntico). Esta matriz readChannelGroup así agrupada puede enumerarse después en la matriz JSON "readChannelGroups", p. ej.
"readChannelGroups": [
[
{
"name": "Channel 1",
"address": 49152,
"registerType": "HoldingReg",
"registerFormat": "REAL",
"byteOrder": "ABCD",
"bitOffset": 0,
"unit": "",
"scale": 1.0,
"offset": 0.0
},
{
"name": "Channel 2",
"address": 49158,
"registerType": "HoldingReg",
"registerFormat": "REAL",
"byteOrder": "ABCD",
"bitOffset": 0,
"unit": "",
"scale": 1.0,
"offset": 0.0
}
]
]
Pueden especificarse, alternativamente, "readChannels" o "readChannelGroups".
Bloques de registros
Los canales de un dispositivo no se leen individualmente. smartCORE los agrupa en bloques de registros: un bloque es un rango de direcciones contiguo de un tipo de registro y se lee en exactamente una transacción ModBus. Cada canal es atendido por exactamente un bloque.
La agrupación se realiza por tipo de registro y dirección. Los cuatro espacios de direcciones de ModBus (Coil, Discrete Input, Input Register, Holding Register) son independientes entre sí: Coil 4 e Input Register 4 son cosas distintas y nunca acaban en el mismo bloque. Se inicia un nuevo bloque en cuanto
- el rango abarcaría más de
maxRegisterGroupregistros, o - el siguiente registro no es contiguo al anterior y
autoGroupAllowGapsestá enfalse.
Con autoGroupAllowGaps: true se salvan los huecos: el bloque lee también registros que ningún
canal necesita, pero ahorra una transacción. Esto compensa en el caso de huecos pequeños y accesos costosos,
no con direcciones muy separadas entre sí.
Quien desee determinar la división por su cuenta asigna registerGroup a cada canal: los canales con el mismo
número forman un bloque y quedan excluidos de la agrupación automática.
Orden de los bytes
El valor de un canal se extrae del búfer leído con el mismo componente que en el
módulo fmProducer, el SimpleBufferPicker. Por ello, byteOrder admite
dos notaciones:
- Con nombre:
bigEndian(tambiénbig,be,motorola,msb,network) olittleEndian(tambiénlittle,le,intel,lsb). Sin indicación se aplica big endian. - Como correspondencia: una secuencia de letras que coloca los bytes del valor en el orden en que se encuentran en el bus. La longitud de la secuencia indica a cuántos bytes se extiende el valor, el orden de las letras indica cómo deben intercambiarse.
Con ello también se aclara la diferencia entre "AB" y "BA": ambos describen un
valor de dos bytes. "AB" los toma en el orden leído, "BA" los intercambia.
De forma análoga con cuatro bytes: "ABCD" sin cambios, "CDAB" intercambiado por palabras, "DCBA"
completamente invertido: las cuatro variantes con las que los dispositivos ModBus almacenan valores de 32 bits.
"BIT" es un caso especial para el acceso a un único bit. Una secuencia que no es ni un
nombre conocido ni una correspondencia válida desactiva el canal; el mensaje lo nombra
expresamente.
Comportamiento temporal y gestión de errores
Ciclo de consulta
El bus es atendido por un hilo propio que, en cada ciclo de consulta
(pollCycleInMilliseconds o pollCycleInNanoseconds), lee uno tras otro todos los bloques de registros
pendientes. Un bloque con pollingIntervalMultiplicator: n está pendiente solo en cada n-ésimo ciclo;
los bloques con el mismo multiplicador se distribuyen en distintos ciclos para que
no coincidan todos en el mismo ciclo.
Un bloque que no está pendiente en un ciclo no produce nada. Hasta smartCORE 2.11 se
emitía en su lugar el contenido sin cambios del bloque de nuevo con la hora actual: un
canal con pollingIntervalMultiplicator: 5 entregaba así cinco veces más valores que mediciones
se habían realizado.
Marca de tiempo de los valores medidos
Cada canal lleva la marca de tiempo de la transacción de la que procede su valor: el instante en que llegó la respuesta del dispositivo. Por ello, todos los canales de un bloque de registros llevan la misma marca de tiempo. El instante en que el dispositivo formó el valor o lo puso en la línea no es observable a través de ModBus: la llegada de la respuesta es el instante más cercano que ofrece el protocolo.
Hasta smartCORE 2.11, los valores llevaban el instante de su salida al smartCHANNEL, no el de la medición, es decir, el instante posterior a la consulta de todos los dispositivos del bus, con un retraso de varios segundos en algunos casos.
Silencio de trama en ModBus/RTU
Antes de cada solicitud se mantiene la línea en silencio durante la duración del silencio de trama t3.5, es decir, la pausa que separa un mensaje RTU del siguiente. Su duración resulta de:
| Condición | Silencio |
|---|---|
readDelayMs está establecido | el valor indicado |
| Velocidad en baudios superior a 19200 (o desconocida) | 1,75 ms: el valor fijo de la MODBUS over Serial Line Specification V1.02; el calculado se reducía a 0,33 ms a 115200 baudios y ya no separaría nada |
| en otro caso | 3,5 caracteres de 11 bits, es decir, 38500000 / velocidad en baudios microsegundos: 4,01 ms a 9600 baudios |
La pausa se realiza antes de la solicitud. Hasta smartCORE 2.11 se hacía la pausa tras una respuesta correcta, es decir, no tras un timeout y, por tanto, justo no en el caso en que la línea más necesita el silencio.
Se registran además dos cosas, porque indican una instalación configurada demasiado rápido: bytes de la solicitud anterior que al iniciarse la siguiente siguen en la cola de envío («la línea es más lenta de lo que supone el ciclo de consulta») y datos que se encuentran de forma inesperada en el búfer de entrada. Estos últimos se leen y se notifican con sus primeros bytes, no se descartan en silencio.
Timeout y desactivación de un bloque de registros
Si una solicitud no recibe respuesta dentro de timeoutInMilliseconds, el acceso se considera
fallido. El bloque de registros cuenta estos intentos fallidos y, tras
minimalChannelAlarmCount intentos fallidos consecutivos, se desactiva: ya no se
consulta y sus canales dejan de producir. El mensaje indica el dispositivo, la dirección de registro,
el código de función, la longitud de la serie de errores y si está previsto un nuevo intento.
No todos los errores cuentan para este umbral:
| Respuesta del dispositivo | Efecto |
|---|---|
| Sin respuesta (timeout), Illegal Function (01), Illegal Data Address (02), Illegal Data Value (03), Server Failure (04), Negative Acknowledge (07), Memory Parity (08), Gateway Target Failed To Respond (0B) | cuenta para la desactivación: el dispositivo o la configuración no están correctos de forma permanente |
| Acknowledge (05), Server Busy (06), Gateway Path Unavailable (0A) | no cuenta: el dispositivo pide paciencia |
| Trama dañada, p. ej. error de CRC | no cuenta: es un evento, no un estado; repetir la solicitud es la respuesta correcta |
retryAfterBlockFailS decide si un bloque desactivado vuelve: con 0 permanece
desactivado durante la medición; con un valor mayor que cero se vuelve a intentar tras ese tiempo.
Si el intento tiene éxito, el bloque vuelve a estar en funcionamiento y el contador se pone a cero;
si fracasa, el tiempo de espera comienza de nuevo.
Un dispositivo que en el campo desaparece ocasionalmente y vuelve necesita
retryAfterBlockFailS. Sin la clave, tras minimalChannelAlarmCount intentos fallidos
se acabó, aunque el dispositivo vuelva a estar conectado al bus dos minutos después.
Información del módulo
| Información | Valor |
|---|---|
| Autores | optiMEAS GmbH |
| desde smartCORE | 0.1 |
| Tipo de módulo | Producer |
| Dependencias | NINGUNA |