18 KiB
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 contactoVar
se evalúa directamente (TRUE cuandoVar
=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 comoNOT 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ógicaCond1 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). FinalmenteD0001
sería el nombre o dirección de la variable de esa bobina. En un contexto real, en lugar deD0001
aparecería el nombre de la salida (por ejemploMotorOn
) 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 aVar := Resultado_logico
cuando la lógica es TRUE (bobina estándar), mientras que una variante_OUTPUT _POSITIV _SET Var
significaría queVar
se establece (latchea) a TRUE con la condición, y_OUTPUT _POSITIV _RESET Var
queVar
se resetea con la condición.
- Bobinas Set/Reset: Si la bobina fuera del tipo latch (enganche) de Set/Reset, en lugar de
-
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 conEND_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 sobreVar
. Si el token va seguido de_POSITIV
, significa que la condición es simplementeVar
(TRUE cuando la variable es TRUE). Si estuviera negado, la condición seríaNOT Var
. En pseudocódigo ST podemos representar un contacto normalmente abierto comoVar
y uno normalmente cerrado comoNOT 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 comoExpresionResultado = (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 esExpr
y hay dos salidasOut1
yOut2
, 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 aVar := 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 comoIF Resultado THEN Var := TRUE; END_IF
(y análogamente un coil de Reset conIF 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 bobinaMotor1
, la pseudocódigo podría ser:Motor1 := A0001 AND A0002;
(suponiendoA0001
yA0002
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.