24 de abril de 2017

Gráfica X/Y en HMI Siemens a partir de puntos almacenados en un bloque de datos (DB)

Si utilizamos un PLC Siemens para realizar una captura de datos y después pretendemos realizar una gráfica con estos datos en un panel táctil de Siemens (un Comfort Panel por ejemplo), veremos que la cosa no es tan sencilla.

Los controles para mostrar gráficas en los sistema HMI de Siemens parecen estar pensados para que el propio sistema HMI haga la captura de datos para su representación, como queriendo liberar al PLC de esta tarea. Sin embargo el limitado ciclo de adquisición que tienen estos sistemas nos limitan a procesos con una dinámica lenta, en los que registrando un punto cada varios segundos sea suficiente. Si es necesario registrar un proceso más rápido deberá ser el PLC el que se haga cargo, guardando, por ejemplo, los datos en tablas en un bloque de datos (DB), pero entonces se plantea el problema de cómo llevar estos datos al control de visualización de gráficas.

En esta entrada voy a explicar cómo representar en un control "Visor de curvas f(x)" datos almacenados en un bloque de datos en un PLC. Me he basado en un ejemplo que me facilitó un técnico de Siemens, aunque yo lo he elaborado un poco más.

La idea general será que el control "Visor de vurvas f(x)" permite ser configurado para obtener los datos de un fichero de texto en formato CSV, y como desde un script podemos crear ficheros de texto y además tenemos acceso a las variables del PLC, programaremos uno que vaya leyendo los datos almacenados en el bloque de datos y escribiéndolos en un fichero CSV digerible por el control "Visor de curvas f(x)".

El material que voy a utilizar en esta entrada es un PLC 1510SP F-1 PN de la serie 1500 de Siemens, aunque valdría cualquiera de las series 300/400/1200/1500. Como panel tengo un TP900 Comfort, pero sería igualmente válido uno que tuviese capacidad de ejecutar scripts y llevase como sistema operativo Windows CE (no serviría un panel que ejecutase Windows normal de PC). Además, el panel debe disponer de algún puerto USB libre o ranura para tarjetas SD.


Para crear los ficheros hay que disponer de una unidad de almacenamiento donde ubicarlos, y esta debe ser una memoria externa, ya sea conectada a un puerto USB o una tarjeta SD (desde un script no podemos escribir en la memoria interna del panel). La ruta de los ficheros debe ser ajustada en el script y en la configuración de ficheros en el panel, como iremos viendo más adelante.

El proyecto sobre el que estoy trabajando está generado con el software de ingenería TIA Portal V14, aunque todo lo aquí explicado debería funcionar con versiones anteriores.

Configurados nuestro PLC y panel para que se comuniquen a través de una red Profinet, procederemos a crear en el PLC un bloque de datos donde almacenaremos los puntos que queramos representar en el panel. En este ejemplo, este DB será lo único que necesitemos en el PLC.


Este DB consta de un Índice que me indica la última posición de las tablas que contienen datos y dos tablas de 500 valores reales donde se iran almacenando los puntos a representar en sus coordenadas X e Y respectivamente. Estas tablas podrían tener un tamaño máximo de 1600 elementos, ya que es límite que se impone para poder ser enlazadas desde el panel.

Pasamos entonces a realizar la configuración en el panel. Lo primero será crear las variables que necesitamos: enlazaremos las tablas creadas en el PLC ("DATOS_X" y "DATOS_Y"), el índice (HMI_Índice); crearemos dos variables reales ("LogValX" y "LogValY") que nos servirar para ir leyendo los datos y un booleano ("Espera") para visualizar en el panel que se están procesando los datos de la gráfica.


En el árbol del proyecto hacemos doble clic sobre Ficheros.


Deberemos generar dos ficheros de variables "DATOX" y "DATOY". Les damos como ubicación "Archivo – CSV (ASCII)", asignamos la ruta "\Storage Card USB\" en el caso de que utilicemos una memoria USB como unidad de trabajo o "\Storage Card SD\" si dicha unidad es una tarjeta SD. El método de archivación será "Fichero circular" y el comportamiento al reiniciar será "Restaurar fichero". En cada fichero de variable deberemos asignar una variable de fichero, que serán las que previamente hemos creado como reales en la tabla de variables "LogValX" y "LogValY". Es importante que nos aseguremos de que el modo de adquisición esté seleccionado "Bajo demanda".



El siguiente paso será programar el script, cuya función será recorrer las tablas en el bloque de datos en el PLC e ir escribiendo los ficheros en formato CSV de donde tomará los datos el control de visualización de la gráfica. El nombre de los ficheros (se genera un fichero por cada variable) deberá ser el que hayamos asignado en la configuración de ficheros de variables ("DATOX" y "DATOY") añadiéndo "0.csv", quedando como "DATOX0.csv" y "DATOY0.csv". Es importante en el script ajustar la misma ruta que la que hayamos configurado en la configuración de ficheros de variables ("\Storage Card USB\" o "\Storage Card SD\").


El código del script es el siguiente:
Sub Grafica_Dibujar()
'=============================================================================
' Notas de automatización 2017 - https://notasdeautomatizacion.blogspot.com
'-----------------------------------------------------------------------------
'Herramienta de ingeniería: TIA Portal 14
'Requerimientos adicionales:
' -Tarjeta SD o memoria USB contactada al panel (ajustar la ruta adecuada)
' -Panel que ejecute Windows CE
'Funcionalidad: A partir de datos almacenados en un DB del PLC se representa
' una gráfica en el panel.
'-----------------------------------------------------------------------------
'Registro de cambios:
'01.00.00 31.03.2017 GR - Primera versión
'=============================================================================

'NOTA: Los nombres de fichero a utilizar deberán ser los que hayamos asignado
'      en la configuración de ficheros de variables en el panel, añadiendo '0'
'      y la extensión '.csv'.

'Rutas y nombres de fichero para las variables a representar en los ejes X e Y
'(Si se usa como memoria de almacenamiento una tarjeta SD)
'IMPORTANTE: Se deben asignar las mismas rutas en la configuración de ficheros
'Const pathX = "\Storage Card SD\DATOX0.csv"
'Const pathY = "\Storage Card SD\DATOY0.csv"

'Rutas y nombres de fichero para las variables a representar en los ejes X e Y
'(Si se usa como memoria de almacenamiento una memoria USB)
'IMPORTANTE: Se deben asignar las mismas rutas en la configuración de ficheros
Const pathX = "\Storage Card USB\DATOX0.csv"
Const pathY = "\Storage Card USB\DATOY0.csv"

Const varNametagX = "LogValX" 'Nombre de la variable para el eje X en HMI
Const varNametagY = "LogValY" 'Nombre de la variable para el eje Y en HMI

Const ForAppending = 8 'Modo de acceso a fichero
Const fsAttrArchive = 32 'Dir command attribute (archive)

Const validity = 1
Const splitSign = ";" 'Separador de campos

Dim array_x, array_y, fsc, dir_return, fsoX, fsoY, delay_counter
Dim i, data_count, timeMS, timestring

'ShowSystemAlarm "Iniciando representación de gráfica..."
SetBit "Espera" 'Para señalizar en la pantalla que se está dibujando

CloseAllLogs 'Close logs and files

'Espera para dar tiempo a cerrar todos los ficheros
delay_counter = 0
While delay_counter < 100000
    delay_counter = delay_counter + 1
Wend

'Si hay ficheros previos creados se borran
Set fsc = CreateObject("FileCtl.FileSystem")

dir_return = fsc.dir(pathX, fsAttrArchive)
If dir_return <> "" Then
    fsc.kill pathX
    'ShowSystemAlarm pathX & " deleted" 'Debug code
End If

dir_return = fsc.dir(pathY, fsAttrArchive)
If dir_return <> "" Then
    fsc.kill pathY
    'ShowSystemAlarm pathY & " deleted" 'Debug code
End If

Set fsc = Nothing

'SE GENERAN LOS FICHEROS A PARTIR DE LOS CUALES SE DIBUJARÁ LA GRÁFICA

'Para Windows CE - NO FUNCIONA PARA WINDOWS DE PC
Set fsoX = CreateObject("FileCtl.File")
Set fsoY = CreateObject("FileCtl.File")

'Open files for appending
fsoX.open pathX, ForAppending
fsoY.open pathY, ForAppending

Set array_x = SmartTags("DATOS_X") 'Tabla de datos para el eje X
Set array_y = SmartTags("DATOS_Y") 'Tabla de datos para el eje Y

'Se escribe la cabecera para el fichero CSV del eje X
fsoX.LinePrint("""VarName"";""TimeString"";""VarValue"";""Validity"";""Time_ms""")
fsoX.LinePrint("""$RT_DIS$"";""30.03.2017 12:00:00"";0;0;0,0")
fsoX.LinePrint("""$RT_COUNT$"";2;;;;")

'Se escribe la cabecera para el fichero CSV del eje Y
fsoY.LinePrint("""VarName"";""TimeString"";""VarValue"";""Validity"";""Time_ms""")
fsoY.LinePrint("""$RT_DIS$"";""30.03.2017 12:00:00"";0;0;0,0")
fsoY.LinePrint("""$RT_COUNT$"";2;;;;")

'Se recorren las tablas de datos escribiendo en los ficheros CSV
data_count = SmartTags("HMI_Índice")
If data_count > 0 And data_count < 500 Then '500 es el número de elementos en las tablas en el PLC
    For i=0 To data_count
        timeMS = i
        fsoX.LinePrint (varNametagX & splitSign & timestring & splitSign & array_x(i) & splitSign & validity & splitSign & timeMS)
        fsoY.LinePrint (varNametagY & splitSign & timestring & splitSign & array_y(i) & splitSign & validity & splitSign & timeMS)   
    Next
Else
    ShowSystemAlarm "Sin datos en la tabla (índice no válido)."
End If

'Una vez terminada la escritura se cierran los ficheros   
fsoX.Close
fsoY.Close
Set fsoX = Nothing
Set fsoY = Nothing

If Err.Number <> 0 Then
    ShowSystemAlarm "Error #" & CStr(Err.Number) & " " & Err.Description
    Err.Clear
Else
    'ShowSystemAlarm "Representación gráfica finalizada." 'Debug code
End If
            
'Restablecer la conexión entre WinCC y los ficheros
OpenAllLogs

'Espera para dar tiempo a abrir todos los ficheros
delay_counter = 0
While delay_counter < 100000
    delay_counter = delay_counter + 1
Wend

'Actualizar/acceder a la pantalla donde se representa la gráfica
'NOTA: En versiones de firmware anteriores al TIA 14, al ejecutar la siguiente línea
' aparecía un error indescifrable en el panel y no se visualizaba la gráfica. Si eso
' sucede, la solución es crear un script adicional donde se ejecute únicamente esta
' línea de código (la llamada a la pantalla). Este script se llamaría en lugar de la
' línea problemática "ActivateScreen".
ActivateScreen "Gráfica", 0

ResetBit "Espera"

End Sub

Al final el script llama a la pantalla donde tengamos el visor de la gráfica, para que se actualice. No me paro a explicar en detalle el script ya que resultaría tedioso y creo que lo mejor es analizarlo apoyándose en sus comentarios.

Ahora vamos a crear una pantalla con el control de visualización de la gráfica, la que yo he preparado tiene el siguiente aspecto:


Básicamente consiste en un control "Visor de curvas f(x)", un botón desde el que se llamará al script y en la parte inferior un "Visor de avisos" para la visualización de mensajes del sistema. Además visualiza la variable "Índice" y como en mis pruebas voy a usar una memoria USB pongo un botón para poder retirarla con seguridad.

En las propiedades del visor de curvas nos interesa la opción de "Curvas", donde añadiremos nuestra gráfica.


En "Estilo" configuraremos a nuestro gusto cómo queremos que se represente la línea (o los puntos) de nuestros datos.


En "Origen de los datos" deberemos seleccionar como tipo de origen "Variables de fichero".


Como valores X e Y deberemos seleccionar las variables "LogValX" y "LogValY" que hemos incluido en los ficheros "DATOX" y "DATOY".


En rango de datos deberemos seleccionar "Puntos de medición", siendo el tiempo de inicio irrelevante.


El resto de configuraciones del visor de curvas lo ajustaremos según nuestras necesidades, teniendo muchas de ellas un efecto simplemente estético.

A continuación, en el botón con el texto redibujar, voy a asignar la llamada al script "Grafica_Dibujar". Cada vez que pulse este botón se leerán los datos del PLC, se escribirán en ficheros en la memoria USB y a partir de ahí se representarán en el visor de curvas.


Para probar la representación deberemos forzar valores directamente en las tablas del DB.


Pulsando el botón "REDIBUJAR" deberían aparecer representados nuestros datos en el visor de gráficas.


Y hasta aquí este ejemplo, que espero sea útil para hacer desarrollos más elaborados.

8 comentarios:

  1. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  2. Buenos días. Estoy intentando que me funcione este ejemplo, pero no lo consigo. ¿sería posible tener el ejemplo como descarga para comparar con mi versión?

    ResponderEliminar
  3. Hola, después de mucho darle vueltas, he podido hacer que funcione. Muchas gracias por la valiosa información.
    Un saludo

    ResponderEliminar
    Respuestas
    1. Puedes decir como has hecho que funcione? Gracias y un saludo

      Eliminar
  4. Saludos!
    Estoy intentando hacer este proyecto en WinCC Flexible clásico ( no TIA PORTAL)

    Me quedan dudas de cómo configurar el Visor de curvas en mi proyecto.

    En el apartado : Eje x : Qué modo he de poner?
    En el apartado : Curva : Qué tipo de curva y qué configuración de fuente he de poner ?

    Muchas gracias!

    ResponderEliminar
  5. Buenas,

    Sabes como se puede hacer esto, pero con WinCC flexible?

    Es que por lo que veo solo puedo hacer graficas de variables dinamicas, y yo quiero generar una gráfica fija, en función de unos valores que tenga en un DB.

    Gracias de antemano,

    Un saludo.

    ResponderEliminar
  6. hola, si quiero usar el ejemplo solo como simulación cuales serán las carpetas de almacenamiento de las variables?
    muchas gracias

    ResponderEliminar
  7. If data_count > 0 And data_count < 500 Then '500 es el número de elementos en las tablas en el PLC
    For i=0 To data_count
    timeMS = i
    fsoX.LinePrint (varNametagX & splitSign & timestring & splitSign & array_x(i) & splitSign & validity & splitSign & timeMS)
    fsoY.LinePrint (varNametagY & splitSign & timestring & splitSign & array_y(i) & splitSign & validity & splitSign & timeMS)
    Next
    Else
    ShowSystemAlarm "Sin datos en la tabla (índice no válido)."
    End If

    ResponderEliminar

Por favor, no pidas copias de programas comerciales, licencias o números de serie.