Evolución de los tipos de datos de los PLC a los PAC
Pere Garriga analiza los cambios en la organización de la memoria de los PLC en lo referente a tipos de datos

El propósito de este artículo es hacer un repaso a los cambios en la organización de la memoria de los PLC en lo referente a tipos de datos y dar a conocer las ventajas que ofrecen los PAC actuales con las estructuras de datos y los tipos de datos creados por el usuario.
Organización de la memoria y tipos de datos en los antiguos PLCs
La memoria tenía un mapeado que determinaba la cantidad disponible de datos, normalmente del tipo Word (16 bits), F (booleanos), T (temporizadores) y contadores. También se disponía de una zona de memoria no volátil con cierta cantidad de variables de tipo W y de tipo F.
En función del modelo de PLC se disponía de más o menos capacidad para cada tipo de variables. Así un determinado PLC podía tener del W001 al W2048, del F000, al F999, del T#01 al T#16, del C#01, al C#16 y una zona de memoria retentiva del W4000 al W4128 y del F1000 al F1128. Esto complicaba un poco la programación puesto que había que hacer una tabla externa para saber dónde se ubicaban los datos, como se muestra en esta imagen.
Si se querían tener los datos bien organizados, había que dejar huecos con palabras de reserva porque no se podían insertar. Por otra parte, la escritura e interpretación del programa se ralentizaba enormemente porque para saber que palabra contenía el dato deseado había que mirar en la tabla del mapeado
En la primera línea del gráfico -abajo-, sin comentarios, tenemos que acudir a la tabla del mapeado para saber de qué señales se trata, en la segunda, con comentarios, tenemos que dedicar tiempo a escribir los comentarios.
Y llegaron los controladores PAC.
Con la llegada de los Programable Automation Controllers, la mejora fue total. Los PAC permiten:
1) Disponer de todos los tipos de datos, BOOL, BYTE, SINT, INT, DINT, LINT, USINT, UINT, UDINT, ULINT, REAL, LREAL WORD, DWORD, LWORD, STRING, TIME, POINTER, ARRAY, UDTs, STRUCT.
2) Datos ilimitados, mientras se disponga de suficiente memoria, se pueden crear más datos del tipo que sea.
3) A los datos o variables se les denomina tags y son simbólicos, es decir, en el ejemplo anterior W1144 sería un tag llamado Piezas, que declararíamos del tipo adecuado (WORD o DWORD), sin necesidad de mapearlo.
Lo mejor, las estructuras de datos y los datos de usuario.
Lo que más facilita y simplifica la programación son las estructuras de datos (STRUCT) y los tipos de datos de usuario, los UDT (User Data Type)
Me he encontrado algunos técnicos que siguen programando como en los PLCs de antaño, se crean unas variables que numeran como en los antiguos equipos (V001 a Vxxx) y otros que emplean los tags de manera simbólica pero no les ven las ventajas a los datos de usuario, ni a las estructuras de datos.
Las ventajas de las estructuras de datos.
Si tuviese que elegir una sola palabra para describir lo que ofrecen las estructuras de datos, esta sería orden. A modo de ejemplo voy a hacer un símil con la información que almacenamos en nuestros PC. En la parte izquierda se muestran unos tags, referidos a ejes, en forma de lista. En este caso resulta difícil encontrar el tag deseado, la solución pasa por estructurar la información y lo primero será crear una “carpeta” llamada MachineAxes que contendrá los tags referidos a todos los ejes de la maquina (X, Y, Z). Dentro da la carpeta MachineAxes, crearemos otras carpetas, una para cada eje, X_Axis, Y_Axis y Z_Axis.
Y puesto que cada eje dispone de tags referidos a la configuración de los mismos, a tags informativos y tags referidos a posicionados crearemos un siguiente nivel de agrupación con las carpetas Config, Move e Info, para cada eje.
De esta forma la información queda perfectamente ordenada y resulta muy fácil de acceder, tanto a la hora de escribir código, como a la hora de depurarlo.
En este ejemplo puede parecer que la diferencia no es tanta, pero en un programa real de una máquina puede haber miles de tags, si no se estructuran bien, puede resultar caótico. Otro punto muy importante es el del nombre que se dan a los tags, para ello existe una recomendación llamada la notación húngara, básicamente se trata de unas siglas iniciales en el nombre del tag, de forma que solo con ver el nombre ya se identifica el tipo de dato que se trata. A modo de ejemplo: si veo unos tags llamados X, C, Step, Vel, su nombre me da algo de información, pero si sus nombres fuesen: axisX, stCoords, intStep, rVel, sabría que X es un eje, C es una estructura de datos de coordenadas, que step es del tipo integer y que Vel es un tag del tipo real. Por lo que el nombre que se asigna a los tags puede facilitar muchísimo el desarrollo y la depuración del programa.
Declaración de los tags
En los PAC, el compilador necesita saber que tags y de que tipo vamos a emplear en el programa para que se pueda organizar la memoria, para ello hay que declarar los tags. O, dicho de otra forma, hay que hacerle saber al compilador el nombre y el tipo de dato de cada tag. En la siguiente imagen se muestra un ejemplo del script necesario.
Declaración de UDTs.
Los UDT (User Data Type) son tipos de datos que el usuario crea a su medida, según las necesidades de cada proyecto.
Por poner un ejemplo, supongamos que me iría bien tener un tipo de dato llamado stCoord para almacenar una coordenada 3D, este UDT debería contener tres tags de tipo LREAL para el valor de la coordenada del eje X, del Y y del Z.
Crear un UDT implica la creación de una estructura de datos con los tags necesarios, el script para crear el UDT stCoord sería el siguiente:
TYPE stCoord:
STRUCT
lrXcoord :LREAL; //Coordenada del eje X
lrYcoord :LREAL; //Coordenada del eje Y
lrZcoord :LREAL; //Coordenada del eje Z
END_STRUCT
END_TYPE
A partir de este momento disponemos de un nuevo tipo de datos, el tipo stCoord, que ya podremos usar en nuestra aplicación. Supongamos en un robot cartesiano en el que tenemos un tag que contiene la posición de pick y otro la de place.
Lo primero tendríamos que declarar las variables, con el siguiente script
VAR
stPick :stCoord; //Coordenadas X, Y, Z de la posición de recogida
stPlace :stCoord; //Coordenadas X, Y, Z de la posición de dejada
END_VAR
A la hora de asignar valores a stPick, a stPlace y a cualquier otra coordenada 3D, se haría de la siguiente forma:
stPick.lrXcoord := 34,20 //Posición de X para carga de este formato
stPick.lrYcoord := 444,00 //Posición de Y para carga de este formato
stPick.lrZcoord := 110,50 //Posición de Z para carga de este formato
stPlace.lrXcoord := 234,20 //Posición de X para descarga de este formato
stPlace.lrYcoord := 80,00 //Posición de Y para descarga de este formato
stPlace.lrZcoord := 10,50 //Posición de Z para descarga de este formato
Volviendo al ejemplo inicial, tendríamos que declarar un tipo de datos para cada carpeta -según el símil- y otro que los agruparía todos (MachineAxis). En la imagen se muestran los UDT en la estructura en árbol del proyecto y el script para la creación de las estructuras de cada uno de los tipos de dato.
Faltaría crear la variable stEjesRobC01, del tipo MachineAxis y ya podríamos acceder a toda la información de forma bien estructurada.
Ejemplos de líneas de código con estructuras de datos.
Este ejemplo se ha creado con la intención de mostrar las ventajas de emplear datos de usuario y estructuras, no quiere decir que el código sea funcional para ninguna aplicación. Para mayor claridad se han dado diferentes colores a cada “carpeta” y a cada eje.
Para asignar parámetros de configuración a los ejes de stEjesRobC01:
-stEjesRobC01 significa estructura de ejes del robot cartesiano número 1-
stEjesRobC01.stXAxis.stAxisConfig.inGearIn := 22; //Denominador ratio reductor eje X
stEjesRobC01.stYAxis.stAxisConfig.inGearIn := 10; //Denominador ratio reductor eje Y
stEjesRobC01.stZAxis.stAxisConfig.inGearIn := 4; //Denominador ratio reductor eje Z
stEjesRobC01.stXAxis.stAxisConfig.inGearOut := 38; //Numerador ratio reductor eje X
stEjesRobC01.stYAxis.stAxisConfig.inGearOut := 10; // Numerador ratio reductor eje Y
stEjesRobC01.stZAxis.stAxisConfig.inGearOut := 40; // Numerador ratio reductor eje Z
stEjesRobC01.stXAxis.stAxisConfig.rFeedCt := 150; //Cte. De avance eje X
stEjesRobC01.stYAxis.stAxisConfig.rFeedCt := 150; // Cte. De avance eje Y
stEjesRobC01.stZAxis.stAxisConfig.rFeedCt := 40; // Cte. De avance eje Z
Para asignar parámetros de movimiento a los ejes de stEjesRobC01:
stEjesRobC01.stXAxis.stAxisMove.rVel := 540.0; // Velocidad posicionado eje X
stEjesRobC01.stXAxis.stAxisMove.rAcel:= 4000.0; // Aceleración eje X
stEjesRobC01.stXAxis.stAxisMove.rTargetPos := 1200.0; // Posición final eje X
stEjesRobC01.stYAxis.stAxisMove.rVel := 540.0; // Velocidad posicionado eje Y
stEjesRobC01.stYAxis.stAxisMove.rAcel:= 4000.0; // Aceleración eje Y
stEjesRobC01.stYAxis.stAxisMove.rTargetPos := 1200.0; // Posición final eje Y
stEjesRobC01.stZAxis.stAxisMove.rVel := 120.0; // Velocidad posicionado eje Z
stEjesRobC01.stZAxis.stAxisMove.rAcel:= 2000.0; // Aceleración eje Z
stEjesRobC01.stZAxis.stAxisMove.rTargetPos := 240.0; // Posición final eje Z
Para consultar si los ejes han llegado a su posición:
IF (stEjesRobC01.stXAxis.stAxisInfo.xAxisInPos AND
stEjesRobC01.stYAxis.stAxisInfo.xAxisInPos AND
stEjesRobC01.stZAxis.stAxisInfo.xAxisInPos) THEN
DO
// Operaciones a realizar
END
END_IF
Aquellos que vienen más del mundo de la lógica cableada y no tanto de la programación en lenguajes estructurados, pueden llegar a pensar que el empleo de estas estructuras no les aportan nada. Les aseguro que cambiarán de opinión tan pronto tengan que desarrollar un programa “serio” o reutilizar código.
Conclusiones:
1) Los controladores PAC disponen de todos los tipos de datos posibles y permiten crear tipos de datos propios y estructuras con todos los tipos disponibles. La cantidad de datos está en función de la capacidad de memoria de la CPU. El direccionamiento es simbólico y no hay que hacer ningún tipo de mapeado. Todas estas características facilitan enormemente el desarrollo, puesta en marcha y el mantenimiento del código, especialmente para quien no lo haya escrito.
2) La principal aportación de las estructuras de datos y los tipos de datos creados por el usuario es la claridad y el orden del código resultante.
3) El empleo de la notación húngara aporta mucha más claridad al código del programa, solo con ver el nombre de un tag, ya sabemos de que tipo de dato se trata, si es una variable global, si es una entrada de un FB, etc.
Anímense a emplear al máximo las estructuras de datos los UDT y sobre todo empleando la notación húngara. Al poco tiempo lo agradecerán