ParamManagerScripts/backend/script_groups/TwinCat/.doc/EXP Report.md

18 KiB
Raw Blame History

Perfecto. Buscaré documentación, ejemplos y recursos útiles sobre cómo interpretar el archivo .EXP exportado por TwinCAT 2.8, especialmente enfocados en los tokens de lenguaje ladder (LAD) como _NETWORK, _LD_ASSIGN, _LD_AND, _LD_CONTACT, etc. Priorizaré repositorios de GitHub y recursos prácticos que ayuden a traducir estos tokens a un pseudocódigo similar a Structured Text (ST), útil para documentación. Te aviso en cuanto tenga los resultados.

Interpretación de archivos .EXP de TwinCAT 2.8 para lógica Ladder (LD)

Formato de exportación ASCII en TwinCAT 2.8

TwinCAT 2 (basado en CoDeSys 2.x) permite exportar el código PLC a archivos de texto con extensión .exp. Dado que los lenguajes gráficos como Ladder Diagram (LD) o Function Block Diagram (FBD) no tienen una representación textual estándar en IEC 61131-3, TwinCAT utiliza un formato ASCII propio para exportar estos POUs. En un archivo .EXP exportado, cada red (rung) de un diagrama Ladder se describe mediante una secuencia de tokens o palabras clave especiales en texto plano. Estos tokens representan contactos, bobinas, operaciones lógicas y la estructura de las redes. Por ejemplo, el manual oficial indica que las POUs en LD/FBD se pueden guardar como ASCII porque “no existe un formato de texto para esto en IEC 61131-3”, por lo que TwinCAT escribe los objetos seleccionados a un archivo ASCII.

Al exportar en TwinCAT 2.8, puede elegirse exportar cada POU en un archivo separado <nombre>.exp (por ejemplo, Program1.exp) o combinar todo en un solo archivo. El contenido del .exp incluye secciones para variables, listas de símbolos y, lo más importante, el código Ladder como secuencia de tokens que representan la lógica. A continuación, detallamos los tokens Ladder más comunes y cómo mapearlos a pseudocódigo legible (similar a Structured Text).

Tokens del lenguaje Ladder en archivos .EXP

A continuación se listan los principales tokens encontrados en un .exp exportado de TwinCAT 2.8 para Ladder, junto con su significado e interpretación:

  • _NETWORK Indica el inicio de una red Ladder (un rung). Cada red Ladder comienza con este token. Puede ir seguida de un identificador de red o comentario de rung. Por ejemplo, un .exp típico mostrará cada rung separado iniciando con _NETWORK. Si existen comentarios de red, suelen aparecer a continuación.

  • _COMMENT / _END_COMMENT Delimitan un bloque de comentario. TwinCAT 2 permitía agregar comentarios por red (rung comment) que en el archivo .exp aparecen entre _COMMENT y _END_COMMENT. Este bloque (si existe) contiene el texto del comentario del rung.

  • _LD_CONTACT Representa un contacto en Ladder. Va seguido de la referencia de la variable booleana asociada (p. ej. una entrada, bit interno, etc.). Indica un contacto normalmente abierto por defecto, a menos que se especifique lo contrario con un flag de inversión. Inmediatamente después del _LD_CONTACT <Variable> suele aparecer un token _EXPRESSION que define si el contacto está invertido o no.

  • _EXPRESSION _POSITIV Este par de tokens suele seguir a un contacto o a una asignación para indicar polaridad positiva (no invertido). En el caso de un contacto, _POSITIV significa que es un contacto normalmente abierto (pasa la energía cuando la variable es TRUE). Si el contacto fuese normalmente cerrado, aparecería un indicador distinto (por ejemplo, _NEG u otro flag en lugar de _POSITIV en la documentación de terceros se describe este campo como “si está negado”, siendo _POSITIV el valor cuando no está negado). En resumen, _EXPRESSION _POSITIV después de _LD_CONTACT Var confirma que el contacto Var se evalúa directamente (TRUE cuando Var=TRUE). Si fuera un contacto negado, veríamos un flag indicando inversión (p.ej., _EXPRESSION _NEG), lo que implicaría que en pseudocódigo se interpreta como NOT Var.

  • _LD_AND Operador lógico AND en Ladder. Este token señala que se realiza una conjunción lógica de las condiciones previas en la red. Por ejemplo, si dos contactos en serie alimentan una bobina, en el .exp aparecerá un _LD_AND para combinar ambos contactos. Generalmente viene acompañado de _LD_OPERATOR : N, donde N es el número de operandos que está combinando. Un _LD_AND con _LD_OPERATOR : 2 indica que dos condiciones previas se están combinando con AND (es decir, ambas deben ser TRUE). En pseudocódigo, esto equivale a la operación lógica Cond1 AND Cond2. De modo similar existe _LD_OR (no mostrado arriba pero presente en exportaciones con ramas paralelas) para la operación OR lógico entre ramas.

  • _LD_OR (Aunque no aparece en nuestros ejemplos concretos, es análogo a _LD_AND.) Representaría una operación OR entre condiciones/paralelos en la red Ladder. Por ejemplo, contactos en paralelo se exportarían con _LD_OR y un _LD_OPERATOR : N indicando cuántos caminos paralelos se están OR-combinando.

  • _LD_ASSIGN Marca el fin de la evaluación lógica de la red y el inicio de las asignaciones a salidas. Es decir, una vez que se han procesado todos los contactos y operaciones lógicas de la red, _LD_ASSIGN indica que ese resultado booleano (TRUE/FALSE) se va a asignar a una o varias bobinas de salida. En la exportación, después de _LD_ASSIGN típicamente vendrá otra línea _EXPRESSION _POSITIV (o _NEG) para indicar si el resultado de la red se utiliza tal cual o invertido para las salidas. Por lo general, será _POSITIV salvo que se invierta toda la lógica del rung (situación poco común).

  • _OUTPUTS : N Indica el número de salidas (bobinas) en esta red. Si un rung Ladder tiene varias bobinas en paralelo que dependen de la misma lógica de contactos (por ejemplo, bobinas paralelas), aquí se listarán cuántas son. En la mayoría de redes Ladder típicas N=1 (una bobina al final del rung). Un ejemplo del formato exportado: _OUTPUTS : 1 --1 个输出 significa “1 salida”. Si hubiera, por ejemplo, dos bobinas en paralelo, veríamos _OUTPUTS : 2.

  • _OUTPUT Define una bobina de salida (coil) a activar. Tras _OUTPUT se indican flags que describen el tipo de bobina y su polaridad, seguidos del nombre de la variable de salida asociada. Por ejemplo: _OUTPUT _POSITIV _NO_SET D0001. Aquí _POSITIV indica que la bobina no está invertida (es una bobina “normalmente desactivada”, energizada directamente con el resultado TRUE de la lógica) y _NO_SET indica que es una bobina regular (no del tipo Set/Reset). Finalmente D0001 sería el nombre o dirección de la variable de esa bobina. En un contexto real, en lugar de D0001 aparecería el nombre de la salida (por ejemplo MotorOn) o la dirección (%QX etc., dependiendo de cómo se exporten las variables).

    • Bobinas Set/Reset: Si la bobina fuera del tipo latch (enganche) de Set/Reset, en lugar de _NO_SET aparecería otro token. Por ejemplo, es esperable _SET para una bobina de Set dominante y _RESET para una de Reset. En la documentación no oficial se observa que _NO_SET se usa para bobinas normales, por lo que presumiblemente existen _SET/_NO_RESET como flags alternativos. Asimismo, la polaridad _POSITIV podría cambiar a _NEG si se tratara de una bobina negada (una bobina especial energizada cuando la condición es FALSE). En general: _OUTPUT _POSITIV _NO_SET Var corresponde a Var := Resultado_logico cuando la lógica es TRUE (bobina estándar), mientras que una variante _OUTPUT _POSITIV _SET Var significaría que Var se establece (latchea) a TRUE con la condición, y _OUTPUT _POSITIV _RESET Var que Var se resetea con la condición.
  • END_PROGRAM Marca el fin del bloque de programa exportado. El archivo .exp típico comienza con la declaración del POU (p. ej. PROGRAM NombreProg LD) y finaliza con END_PROGRAM una vez listadas todas las redes Ladder y salidas. Todo lo descrito entre estos delimitadores corresponde al contenido del POU Ladder en formato textual.

Ejemplo ilustrativo: En un foro técnico se mostró un fragmento de .exp resultante de exportar Ladder, que ayuda a visualizar varios de estos tokens y su secuencia. Por ejemplo:

_LD_CONTACT  A0001  (... variable de entrada ...)
_LD_CONTACT  A0002  (... otra entrada ...)
_LD_AND 
_LD_OPERATOR : 2    ; AND de 2 operandos (A0001 y A0002)
_LD_ASSIGN 
_OUTPUTS : 1        ; Una salida en esta red
_OUTPUT  _POSITIV  _NO_SET  D0001
END_PROGRAM

En este caso hipotético, A0001 y A0002 podrían ser dos contactos en serie y D0001 una bobina de salida. Los tokens indican: carga dos contactos (_LD_CONTACT), combínalos con un AND de 2 entradas (_LD_AND + _LD_OPERATOR:2), asigna el resultado (_LD_ASSIGN) a 1 salida (_OUTPUTS:1), que es una bobina normal no invertida (_OUTPUT _POSITIV _NO_SET) asignada a la variable D0001.

Del mismo modo, otro ejemplo simple tomado de la documentación no oficial muestra la estructura para una red con un contacto y una bobina únicamente: primero el contacto y su variable, luego la asignación y la bobina de salida. Allí se observa _LD_CONTACT p1 seguido de _EXPRESSION _POSITIV (contacto normalmente abierto con variable p1), luego _LD_ASSIGN con _EXPRESSION _POSITIV y finalmente _OUTPUTS:1 con _OUTPUT _POSITIV _NO_SET p2 para energizar la variable p2. Esta red equivale a una lógica donde p2 = p1, es decir, la bobina p2 se activa cuando la entrada p1 está activa.

Mapeo de la lógica Ladder a pseudocódigo (Structured Text)

El objetivo de interpretar estos tokens es poder traducir la lógica Ladder en texto entendible, similar a Structured Text (ST) o pseudocódigo, para facilitar la documentación. Básicamente, se trata de reconstruir las expresiones booleanas y asignaciones a partir de la secuencia de tokens:

  • Contactos: Cada _LD_CONTACT Var se convierte en una condición booleana sobre Var. Si el token va seguido de _POSITIV, significa que la condición es simplemente Var (TRUE cuando la variable es TRUE). Si estuviera negado, la condición sería NOT Var. En pseudocódigo ST podemos representar un contacto normalmente abierto como Var y uno normalmente cerrado como NOT Var.

  • Operadores lógicos AND/OR: Tokens como _LD_AND con _LD_OPERATOR:n indican combinaciones lógicas. Por ejemplo, si hay dos contactos seguidos de _LD_AND, en ST sería una conjunción: Cond1 AND Cond2. Si hubiera _LD_OR, sería una disyunción: Cond1 OR Cond2. Estos operadores reflejan ramas en serie (AND) o en paralelo (OR) en el esquema Ladder. Por ejemplo, _LD_AND con 2 operandos se traduce como ExpresionResultado = (Expr1 AND Expr2).

  • Asignación a salidas: El token _LD_ASSIGN señala que la expresión lógica formada por los contactos y operadores anteriores ya determina el resultado del rung. En Ladder, ese resultado se envía a una o varias bobinas. En pseudocódigo, esto corresponde a realizar asignaciones a las variables de salida. Si _OUTPUTS : 1, hay una sola salida y simplemente pondremos esa variable igual a la expresión booleana resultante. Si hay múltiples salidas (p. ej. dos bobinas en paralelo), cada una recibirá el mismo valor de la expresión lógica. Por ejemplo, si la lógica calculada es Expr y hay dos salidas Out1 y Out2, en ST podríamos escribir: Out1 := Expr; Out2 := Expr;.

  • Bobinas (coils): Un _OUTPUT _POSITIV _NO_SET Var se interpreta como una asignación directa: Var := ResultadoLogico. Si la bobina estuviera invertida (_NEG), equivaldría a Var := NOT(ResultadoLogico). Si es un coil de Set, en Ladder significa que cuando la condición es TRUE se establece la variable (la mantiene a 1 hasta otro evento), lo cual en pseudocódigo se modelaría con algo como IF Resultado THEN Var := TRUE; END_IF (y análogamente un coil de Reset con IF Resultado THEN Var := FALSE; END_IF). No obstante, Ladder maneja set/reset de forma interna, por lo que para documentación suele ser suficiente indicar “(Set)” o “(Reset)” junto a la asignación.

  • Rung completo: En conjunto, cada _NETWORK puede traducirse a un bloque IF/THEN o a una expresión booleana asignada. Una forma de documentarlo estilo ST es escribir la ecuación booleana de la red. Por ejemplo, considerando el fragmento anterior con dos contactos en serie asignando una bobina Motor1, la pseudocódigo podría ser: Motor1 := A0001 AND A0002; (suponiendo A0001 y A0002 son variables booleanas). Si hubiera contactos en paralelo (OR), se agruparían con paréntesis adecuadamente. Alternativamente, se puede expresarlo como lógica condicional:

    IF (A0001 AND A0002) THEN 
        Motor1 := TRUE; 
    ELSE 
        Motor1 := FALSE; 
    END_IF;
    

    Ambas formas representan la misma lógica de la red Ladder en un formato textual claro.

Notas: También existen tokens para construcciones especiales. Por ejemplo, _JUMP <etiqueta> puede aparecer en .exp para reflejar instrucciones de salto (gotos) dentro de Ladder il o saltos condicionales (similar a instrucciones en lenguaje IL) aunque en Ladder puro estándar no son comunes, CoDeSys permitía elementos como jump. Otro posible token es _EN/_ENO para conexiones de habilitación a cajas de función (FB/funciones) insertadas en Ladder. Estos casos avanzados van más allá de simples contactos y bobinas, pero siguen una lógica similar: el .exp listará llamados a funciones o saltos con sus parámetros en texto. Si el objetivo es documentación, normalmente se enfoca en la lógica combinacional de contactos y bobinas, que es lo descrito arriba.

Herramientas y recursos para la conversión

Encontrar documentación detallada de este formato no estándar puede ser difícil, pero existen recursos oficiales y de la comunidad que ayudan a interpretarlo. Beckhoff no publica abiertamente la gramática completa de .exp, pero la información fragmentada en manuales y foros nos da guía. Por ejemplo, un manual de HollySys (un PLC basado en CoDeSys) incluye una sección explicando cada token Ladder (_LD_CONTACT, _LD_AND, _OUTPUT, etc.) y cómo corresponden a los elementos gráficos. Aunque esté en chino, confirma la semántica: por ejemplo, _LD_CONTACT --触点标识... _EXPRESSION --是否置反标识 _POSITIV significa que _LD_CONTACT identifica un contacto y _POSITIV indica que no está negado. Del mismo modo, muestra _OUTPUT ... _POSITIV _NO_SET ... para una bobina normal. Este tipo de documentación no oficial puede servir de referencia de mapeo.

En cuanto a herramientas automáticas para convertir .exp Ladder a código legible o ST, no se conocen utilidades públicas específicas enfocadas solo en TwinCAT 2 .exp. Sin embargo, hay enfoques posibles:

  • Uso de TwinCAT 3/PLCopen: Beckhoff TwinCAT 3 ofrece un convertidor de formatos TwinCAT 2 integrado. Es posible importar el proyecto o POU exportado de TwinCAT 2 (archivo .exp o .tpy) a TwinCAT 3 y luego exportarlo a XML PLCopen, que es un formato estándar. El XML PLCopen describirá la lógica Ladder de forma estructurada, más fácil de leer o de procesar con scripts (por ejemplo, extrayendo las ecuaciones lógicas). De hecho, un experto sugiere usar PLCopen XML como vía de intercambio entre plataformas. Esto requeriría tener TwinCAT 3 instalado para la conversión, pero puede ahorrar tiempo si se dispone de muchos rungs.
  • Scripting personalizado: Dado que el .exp es texto ASCII, se puede escribir un script (en Python u otro lenguaje) para parsear los tokens y regenerar la lógica. La gramática es relativamente simple (como se detalló arriba). Por ejemplo, uno podría leer línea a línea, identificar bloques _NETWORK ... _OUTPUTS y construir la expresión booleana intermedia. No encontramos una librería Python ya hecha para esto, pero es viable implementarlo. Algunos usuarios en foros han discutido partes del formato precisamente con la idea de traducirlo; por ejemplo, en un foro chino se intentó “traducir un programa Ladder de Siemens (TIA) a Beckhoff” analizando un .exp de TwinCAT, lo que evidencia el interés en tales conversiones. Un proyecto open-source relacionado es Blark (un parser de código ST de TwinCAT), que aunque está orientado a Structured Text, demuestra que es posible crear gramáticas para lenguajes PLC en Python. Para Ladder, un desarrollador podría definir reglas similares: contactos -> operandos booleanos, _LD_AND -> operador AND, etc., o incluso usar expresiones regulares dado el formato estructurado lineal del .exp.
  • Recursos comunitarios: Revisar comunidades de automatización y repositorios GitHub puede dar frutos. Si bien no hallamos una herramienta específica lista para usar, sitios como PLCtalk y Stack Overflow tienen hilos donde se menciona la exportación .exp. Por ejemplo, en Stack Overflow se preguntó sobre importar .exp entre distintos entornos CoDeSys, confirmando que .exp es un formato Codesys genérico utilizado por múltiples marcas. Esto significa que documentación de CoDeSys 2.3 también aplica (muchos controladores usaban el mismo formato export). En suma, buscar por “CoDeSys export .exp Ladder” puede arrojar tips de usuarios que hayan hecho ingeniería inversa del formato.

Conclusión: Mediante la combinación de fuentes oficiales (manuales de TwinCAT/Codesys) y no oficiales (ejemplos en foros, manuales de terceros), es posible mapear los tokens _NETWORK, _LD_CONTACT, _LD_AND, _LD_ASSIGN, _OUTPUT, etc., a construcciones lógicas comprensibles. La clave es reconocer la secuencia: una red Ladder en .exp corresponde a una expresión booleana (derivada de contactos y operadores) asignada a una o varias salidas. Documentar esa lógica en pseudocódigo estilo ST por ejemplo, escribiendo ecuaciones lógicas o condiciones IF/THEN hará más legible el programa. Con los ejemplos y explicaciones recopilados aquí, se tiene un guía de referencia para emprender esa traducción manual o mediante script, facilitando la comprensión de programas Ladder exportados de TwinCAT 2.8.

Referencias usadas: Documentación de Beckhoff TwinCAT 2, fragmentos de manual Hollysys/AutoThink, y ejemplos de código .exp discutidos en foros, entre otros. Estas fuentes proporcionan casos prácticos y descripciones claras para respaldar la interpretación de cada token y su equivalente lógico. Por último, la utilización de herramientas modernas (TwinCAT 3, PLCopen) o scripts personalizados son caminos recomendados si se requiere automatizar la conversión de .exp Ladder a texto estructurado.