Archive for mayo, 2010

Sinópticos I.

Uno de los retos a los que nos enfrentamos es el de aumentar la calidad de la apariencia de las aplicaciones HMI. Hoy pienso hacer una presentación de algunas herramientas para el diseño de gráficos de calidad. Como siempre, intento utilizar aplicaciones source code y esta no sera una excepción. Mas aun me he llevado una grata sorpresa al comprobar las posibilidades de estas herramientas.

En concreto he hecho algunas pruebas con Sketchup y Kerkytea. El primero es un programa de diseño Cad 3D y el segundo una aplicación para renderizar objetos 3D.  Por ahora solo he hecho algunas pruebas pero espero que pronto pueda presentar alguna aplicación en vb.net utilizando las posibilidades que nos presentas estos programas.

Instalación frigorífica realizada con Sketchup.

Y este es el resultado despues de aplicar el renderizado:

Y esto son algunos ejemplos:

Aquí podéis descargar Sketchup, Kerkytea, PlugIn para Sketchup con herramientas interesantes y por ultimo plugin para exportar modelo desde  Sketchup a Kerkytea.

Registro de estado IV. Grafica.

Hoy toca hacer la primera gráfica, como veremos en otra ocasión, vb.net nos proporciona herramientas para poder dibujar de manera que podríamos construir nuestro gráfico con estas herramientas. En esta ocasión toca la ley del mínimo esfuerzo, utilizar el trabajo de otro. Existe un control muy sencillo de utilizar para realizar esta tarea, ZedGraph nos permite realizar gráficos de diferentes tipos con realmente poco esfuerzo.

Aquí podéis ver los detalles de este interesante control. Y aquí podéis descargar todos los archivos. En concreto lo único que necesitamos para este proyecto es la dll. Descargáis el archivo, se descomprime y se guarda en una carpeta de fácil acceso.

En el proyecto del anterior post, añadimos un formulario que llamaremos FormGrafica. Ahora veamos los pasos necesarios para incluir este control en nuestro proyecto:

Herramientas   > elegir elementos del cuadro de herramientas.

Una vez se ha abierto el cuadro de diálogo pinchamos en Examinar, buscamos la carpeta donde guardamos el control

Como se puede ver, yo descargue la librería, manuales y el sourcecode. Abrimos la carpeta zedgraph_dll_v515

Y seleccionamos el archivo ZedGraph. Con esto ya podemos utilizar el control en nuestro formulario

Arrastramos el control al formulario FormGrafica y le cambiamos la propiedad Dock a fill. Para poder ver el gráfico tendremos que poner un botón en el FormAnalizar, y como siempre, pinchamos dos veces, y en el gestor de eventos FormGrafica.Show().

Ahora veamos el código necesario para que el gráfico muestre nuestros datos.

Imports ZedGraph
 
Public Class FormGrafica
 
Private Sub FormGrafica_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
'Creamos el grafico
 
CreateGraph(ZG1)
 
End Sub
 
Private Sub CreateGraph(ByVal zgc As ZedGraphControl)
 
Dim myPane As GraphPane = zgc.GraphPane
 
' Asignamos titulos, escalas, etc
 
myPane.Title.Text = "Grafica de datos historicos"
 
myPane.XAxis.Title.Text = "TIEMPO"
 
myPane.YAxis.Title.Text = ""
 
myPane.YAxis.Scale.Min = 0
 
myPane.YAxis.Scale.Max = 16
 
myPane.XAxis.Type = AxisType.Text
 
myPane.XAxis.Scale.TextLabels = FormAnalizar.Momento
 
myPane.XAxis.MajorGrid.IsVisible = True
 
myPane.YAxis.MajorGrid.IsVisible = True
 
myPane.XAxis.Scale.FontSpec.Angle = 90
 
myPane.XAxis.Scale.FontSpec.Size = 8
 
'Transformar el dato en puntos
 
Dim Bit(1) As Double
 
ReDim Bit(FormAnalizar.Dato.Length - 1)
 
Dim i As Integer 'Variable para recorrer cada momento
 
Dim j As Integer 'Variable para cada bits
 
For j = 0 To 15
 
For i = 0 To FormAnalizar.Dato.Length - 1
 
If FormAnalizar.Dato(i).Chars(j) = "0" Then Bit(i) = 0 + j Else Bit(i) = 0.5 + j
 
Next
 
Dim myCurve0 As LineItem = myPane.AddCurve("Bit" & j, Nothing, Bit, Color.Black, SymbolType.None)
 
Next
 
' Fill the axis background with a color gradient
 
myPane.Chart.Fill = New Fill(Color.White, Color.LightGoldenrodYellow, 45.0F)
 
' Fill the pane background with a color gradient
 
myPane.Fill = New Fill(Color.White, Color.FromArgb(220, 220, 255), 45.0F)
 
' Calculate the Axis Scale Ranges
 
zgc.AxisChange()
 
End Sub
 
Private Sub Form1_Resize(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Resize
 
'Si cambiamos el tamaño del formulario se lee este código que envía a la función SetSice
 
SetSize()
 
End Sub
 
Private Sub SetSize()
 
'Reconstruye el tamaño en funcion del tamaño del formulario
 
ZG1.Location = New Point(10, 50)
 
' Leave a small margin around the outside of the control
 
ZG1.Size = New Size(ClientRectangle.Width - 20, ClientRectangle.Height - 80)
 
End Sub
 
End Class

Y este es el resultado:

Aquí dejo el proyecto completo.

Registro de estados III. Visualizar en tabla.

En los anteriores post vimos como guardar el estado de las entradas/salidas del PLC en el PC. Hoy vamos a leer estos archivos y generar una tabla que nos muestre de una forma clara como se han producido los cambios. La técnica empleada para esto es leer texto separado por “;”. En el anterior proyecto añadiremos un botón que nos abra un nuevo formulario. A este botón lo llamaremos buAnalizar y en la propiedad texto le pondremos Analizar. Doble click en el botón y nos genera el evento donde pondremos el siguiente código.

También podríamos utilizar el siguiente código para abrir el formulario, este código nos permite abrir múltiples estancias del mismo formulario:

Como podemos ver en el código, en el segundo caso se crea una nueva estancia del formulario cada vez que presionamos el botón.

En el explorador de soluciones, click con el derecho y añadir nuevo elemento:

Y este es el aspecto de nuestro formAnalizar:

He previsto tres posibilidades para elegir el archivo, las dos primera (IN, OUT), son RadioButon y tienen la peculiaridad de que solo podrá estar marcada una. Cuando marcamos IN se desmarca Out y viceversa. La última posibilidad es un CheckBoxy la función es abrir un cuadro de dialogo para elegir el archivo a analizar. Aunque los tres podrían ser RadioButon he considerado poner un Checkbox para que podáis apreciar la diferencia entre los dos primeros y el tercero. Por último ponemos un botón para proceder a la lectura del archivo.

El cuadro blanco situado a la derecha es un ListView. Podríamos configurar las columnas directamente pero yo prefiero hacerlo por código. Hacemos doble click en el formAnalizar y nos genera el gestor de eventos del FormAnalizar.Load. Lo que quiere decir que será el código que primero leerá cuando se abra el formulario. Aprovechamos este evento para configurar la tabla en el listView. Aunque es un poco largo porque hay muchas columnas, es fácil y prácticamente es copiar pegar, puesto que la diferencia entre las columnas de la tabla son los nombres, bit0, bit1, etc

Private Sub FormAnalizar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
 
Handles MyBase.Load
 
ListView1.View = View.Details
 
ListView1.BackColor = Color.GhostWhite
 
ListView1.GridLines = True
 
ListView1.Columns.Add("Fecha / Hora")
 
ListView1.Columns(0).Width = 150
 
ListView1.Columns.Add("bit.0")
 
ListView1.Columns(1).Width = 40
 
ListView1.Columns.Add("bit.1")
 
ListView1.Columns(2).Width = 40
 
ListView1.Columns.Add("bit.2")
 
ListView1.Columns(3).Width = 40
 
ListView1.Columns.Add("bit.3")
 
ListView1.Columns(4).Width = 40
 
ListView1.Columns.Add("bit.4")
 
ListView1.Columns(5).Width = 40
 
ListView1.Columns.Add("bit.5")
 
ListView1.Columns(6).Width = 40
 
ListView1.Columns.Add("bit.6")
 
ListView1.Columns(7).Width = 40
 
ListView1.Columns.Add("bit.7")
 
ListView1.Columns(8).Width = 40
 
ListView1.Columns.Add("bit.8")
 
ListView1.Columns(9).Width = 40
 
ListView1.Columns.Add("bit.9")
 
ListView1.Columns(10).Width = 40
 
ListView1.Columns.Add("bit.10")
 
ListView1.Columns(11).Width = 40
 
ListView1.Columns.Add("bit.11")
 
ListView1.Columns(12).Width = 40
 
ListView1.Columns.Add("bit.12")
 
ListView1.Columns(13).Width = 40
 
ListView1.Columns.Add("bit.13")
 
ListView1.Columns(14).Width = 40
 
ListView1.Columns.Add("bit.14")
 
ListView1.Columns(15).Width = 40
 
ListView1.Columns.Add("bit.15")
 
ListView1.Columns(16).Width = 40
 
End Sub

Bien, tenemos el formulario gráficamente terminado, ahora vamos a leer los archivos y a llenar la tabla con datos. El primer paso es seleccionar el archivo con el que queremos trabajar:

Agregamos un componente, que nos hará el trabajo de abrir un cuadro de diálogo para seleccionar un archivo. OpenFileDialog.

Lo arrastramos hasta el formulario, y automáticamente se pasará a la barra gris situada debajo del formulario.

Le he cambiado la propiedad Name por Ofd1. El siguiente extracto de código muestra la selección del nombre del archivo a leer, en función de los requerimientos del usuario:

'Borramos el listview
 
ListView1.Items.Clear()
 
'Comprobamos si quiere ver In, Out o abrir un cuadro de dialogo
 
Dim Filename As String = ""
 
If ckMostrarDialogo.Checked Then
 
Ofd1.ShowDialog()
 
Filename = Ofd1.FileName
 
Else
 
If rdIn.Checked Then Filename = "In.csv"
 
If rdOut.Checked Then Filename = "Out.csv"
 
End If
 
If Filename = "" Then
 
MessageBox.Show("Error en parametros")
 
Exit Sub
 
End If

Declaramos la variable FileName donde almacenaremos el nombre del archivo a abrir. Si está marcado el Cheked.Box abre el cuadro de diálogo para que seleccionemos un archivo, una vez seleccionado pasa el nombre a la variable. De no ser así, se comprueba cual de los RadioButton está marcado para asignar el nombre del archivo como In.csv u Out.csv.

Como no sabemos a priori cuantas líneas tendrá el archivo que vamos a abrir, lo haremos en dos pasadas, en la primera pasada contamos las líneas, dimensionamos las variables que almacenaran los datos y en la siguiente pasada pasamos los datos a las variables. Realmente no es necesario almacenar los datos, puesto que como veremos más adelante, los datos se irán escribiendo en la tabla a medida que los leemos, pero esto no termina en una tabla, en la próxima entrada mostraremos los datos en un gráfico, por este motivo los guardamos en unas variables, para posteriormente poder visualizarlos en grafico.

¿Y cómo podemos leer un archivo de este tipo? Pues que lo diga el IDE. Pincha con el derecho dentro del evento buLeerDatos, insertar fragmento de código:

En nuestro caso quitamos la primera línea, ya que filename ya está declarada y cambiamos delimiter por “;”. El código completo del gestor de eventos leerdatos es este:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
 
Handles buLeerDatos.Click
 
'Borramos el listview
 
ListView1.Items.Clear()
 
'Comprobamos si quiere ver In, Out o abrir un cuadro de dialogo
 
Dim Filename As String = ""
 
If ckMostrarDialogo.Checked Then
 
Ofd1.ShowDialog()
 
Filename = Ofd1.FileName
 
Else
 
If rdIn.Checked Then Filename = "In.csv"
 
If rdOut.Checked Then Filename = "Out.csv"
 
End If
 
If Filename = "" Then
 
MessageBox.Show("Error en parametros")
 
Exit Sub
 
End If
 
Dim i As Integer
 
Dim fields As String()
 
Dim delimiter As String = ";"
 
Try
 
'Leemos para dimensionar las variables
 
Using parser As New TextFieldParser(Filename)
 
parser.SetDelimiters(delimiter)
 
While Not parser.EndOfData
 
' Read in the fields for the current line
 
fields = parser.ReadFields()
 
' Add code here to use data in fields variable.
 
i += 1
 
End While
 
End Using
 
Catch ex As Exception
 
MessageBox.Show("Error de parametros")
 
Exit Sub
 
End Try
 
'Dimensionamos las variables
 
ReDim Momento(i - 1)
 
ReDim Dato(i - 1)
 
i = 0
 
'Leemos y asignamos a variables
 
Using parser As New TextFieldParser(Filename)
 
parser.SetDelimiters(delimiter)
 
While Not parser.EndOfData
 
' Read in the fields for the current line
 
fields = parser.ReadFields()
 
' Add code here to use data in fields variable.
 
Momento(i) = fields(0)
 
Dato(i) = DecToBin(fields(1))
 
Trace1(Momento(i), Dato(i), Color.Black)
 
i += 1
 
End While
 
End Using
 
End Sub

Como podemos ver en el código, en la primera pasada sólo incrementamos i de manera que al final del bucle i = total filas. Redimensionamos las variables y volvemos a leer para asignar los valores a las variables, a la vez llamamos a la función Trace1, que es la encargada de rellenar la tabla de una manera especial.

Public Sub Trace1(ByVal Momento As String, ByVal ValorInt16 As String, ByVal ColorMsg As Color)
 
Dim Texto(16) As String
 
Texto(0) = Momento
 
Dim i As Integer
 
For i = 0 To ValorInt16.Length - 1
 
If DatoAnterior.Chars(i) <> ValorInt16.Chars(i) Then
 
If ValorInt16.Chars(i) = "0" Then Texto(i + 1) = "OFF" Else Texto(i + 1) = "ON"
 
End If
 
Next
 
Dim item As New ListViewItem(Texto)
 
item.ForeColor = ColorMsg
 
ListView1.Items.Add(item)
 
DatoAnterior = ValorInt16
 
End Sub

Principalmente se trata de ir comprobando cada carácter de la variable string que contiene el valor binario, si es diferente de la vez anterior. De ser así, escribimos en la tabla. El resultado es este:

Y este es el código completo:

Imports Microsoft.VisualBasic.FileIO
 
Public Class FormAnalizar
 
Dim Dato(1) As String
 
Dim Momento(1) As String
 
Dim DatoAnterior As String = "0000000000000000"
 
Private Sub FormAnalizar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
 
Handles MyBase.Load
 
ListView1.View = View.Details
 
ListView1.BackColor = Color.GhostWhite
 
ListView1.GridLines = True
 
ListView1.Columns.Add("Fecha / Hora")
 
ListView1.Columns(0).Width = 150
 
ListView1.Columns.Add("bit.0")
 
ListView1.Columns(1).Width = 40
 
ListView1.Columns.Add("bit.1")
 
ListView1.Columns(2).Width = 40
 
ListView1.Columns.Add("bit.2")
 
ListView1.Columns(3).Width = 40
 
ListView1.Columns.Add("bit.3")
 
ListView1.Columns(4).Width = 40
 
ListView1.Columns.Add("bit.4")
 
ListView1.Columns(5).Width = 40
 
ListView1.Columns.Add("bit.5")
 
ListView1.Columns(6).Width = 40
 
ListView1.Columns.Add("bit.6")
 
ListView1.Columns(7).Width = 40
 
ListView1.Columns.Add("bit.7")
 
ListView1.Columns(8).Width = 40
 
ListView1.Columns.Add("bit.8")
 
ListView1.Columns(9).Width = 40
 
ListView1.Columns.Add("bit.9")
 
ListView1.Columns(10).Width = 40
 
ListView1.Columns.Add("bit.10")
 
ListView1.Columns(11).Width = 40
 
ListView1.Columns.Add("bit.11")
 
ListView1.Columns(12).Width = 40
 
ListView1.Columns.Add("bit.12")
 
ListView1.Columns(13).Width = 40
 
ListView1.Columns.Add("bit.13")
 
ListView1.Columns(14).Width = 40
 
ListView1.Columns.Add("bit.14")
 
ListView1.Columns(15).Width = 40
 
ListView1.Columns.Add("bit.15")
 
ListView1.Columns(16).Width = 40
 
End Sub
 
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
 
Handles buLeerDatos.Click
 
'Borramos el listview
 
ListView1.Items.Clear()
 
'Comprobamos si quiere ver In, Out o abrir un cuadro de dialogo
 
Dim Filename As String = ""
 
If ckMostrarDialogo.Checked Then
 
Ofd1.ShowDialog()
 
Filename = Ofd1.FileName
 
Else
 
If rdIn.Checked Then Filename = "In.csv"
 
If rdOut.Checked Then Filename = "Out.csv"
 
End If
 
If Filename = "" Then
 
MessageBox.Show("Error en parametros")
 
Exit Sub
 
End If
 
Dim i As Integer
 
Dim fields As String()
 
Dim delimiter As String = ";"
 
Try
 
'Leemos para dimensionar las variables
 
Using parser As New TextFieldParser(Filename)
 
parser.SetDelimiters(delimiter)
 
While Not parser.EndOfData
 
' Read in the fields for the current line
 
fields = parser.ReadFields()
 
' Add code here to use data in fields variable.
 
i += 1
 
End While
 
End Using
 
Catch ex As Exception
 
MessageBox.Show("Error de parametros")
 
Exit Sub
 
End Try
 
'Dimensionamos las variables
 
ReDim Momento(i - 1)
 
ReDim Dato(i - 1)
 
i = 0
 
'Leemos y asignamos a variables
 
Using parser As New TextFieldParser(Filename)
 
parser.SetDelimiters(delimiter)
 
While Not parser.EndOfData
 
' Read in the fields for the current line
 
fields = parser.ReadFields()
 
' Add code here to use data in fields variable.
 
Momento(i) = fields(0)
 
Dato(i) = DecToBin(fields(1))
 
Trace1(Momento(i), Dato(i), Color.Black)
 
i += 1
 
End While
 
End Using
 
End Sub
 
#Region "Conversion binario decimal "
 
Private Function BinToDec(ByVal ValorBin As String) As Decimal
 
Dim Longitud As Integer = ValorBin.Length
 
'Debug.WriteLine("Entrar: " & ValorBin & "Longitud: " & Longitud)
 
Dim i As Integer = 0
 
Dim ValorDec As Decimal = 0
 
For i = 0 To Longitud - 1
 
Dim _Char As Char = ValorBin.Chars(i)
 
Dim ValorChar As Integer
 
If _Char = "0" Then ValorChar = 0 Else ValorChar = 1
 
ValorDec += ValorChar * System.Math.Pow(2, ((Longitud - i) - 1))
 
Next
 
Return (ValorDec)
 
End Function
 
Private Function DecToBin(ByVal ValorDec As Int32) As String
 
'Esta funcion convierte en binario tanto palabras INT como UINT.
 
'En caso de haber valores negativos se asume que es una palabra INT
 
' y hace la conversión con esta formula
 
If ValorDec < 0 Then
 
ValorDec = 65536 + ValorDec
 
End If
 
Dim Cociente As Int32 = ValorDec
 
Dim Resto As Int32 = 0
 
Dim ValorBinMatriz(17) As Char
 
Dim ValorBin As String = ""
 
Dim i As Integer = 0
 
If ValorDec = 1 Then ValorBinMatriz(0) = "1"
 
While Cociente > 1
 
Cociente = System.Math.DivRem(Cociente, 2, Resto)
 
ValorBinMatriz(i) = Resto.ToString
 
If Cociente < 2 Then ValorBinMatriz(i + 1) = Cociente.ToString
 
i += 1
 
End While
 
Dim j As Integer
 
For j = 0 To 15
 
If ValorBinMatriz(j) = "1" Then ValorBin &= "1" Else ValorBin &= "0"
 
Next
 
Return (ValorBin)
 
End Function
 
#End Region
 
Public Sub Trace1(ByVal Momento As String, ByVal ValorInt16 As String, ByVal ColorMsg As Color)
 
Dim Texto(16) As String
 
Texto(0) = Momento
 
Dim i As Integer
 
For i = 0 To ValorInt16.Length - 1
 
If DatoAnterior.Chars(i) <> ValorInt16.Chars(i) Then
 
If ValorInt16.Chars(i) = "0" Then Texto(i + 1) = "OFF" Else Texto(i + 1) = "ON"
 
End If
 
Next
 
Dim item As New ListViewItem(Texto)
 
item.ForeColor = ColorMsg
 
ListView1.Items.Add(item)
 
DatoAnterior = ValorInt16
 
End Sub
 
End Class

Registro de estados I. Introducción.

Cuando tienes averías raras de las que desconoces la causa, interrogas a los usuarios de las instalaciones he intentas reconstruir lo que pasó. En otras ocasiones te gustaría saber cómo funciona la instalación para poder saber cómo mejorarla. Para no tener que volver a hacer interrogatorios podemos crear nuestro espía que grabará en el PC cada cambio de estado para más tarde poder reconstruir el pasado.

En esta entrada y siguientes construiremos una pequeña aplicación que guarde el estado de las entradas/salidas del PLC en el PC, para más tarde poder ver gráficamente lo que pasó con nuestra instalación mientras estábamos fuera. Para compactar la información guardaremos el estado de las entradas/salidas en palabras INT.

Tenemos que realizar los siguientes pasos en el PLC:

  • Convertir el estado de 16 entradas en una palabra INT.
  • Convertir el estado de 16 salidas en una palabra INT.

Estos en el programa del PC (vb.net) para guardar:

  • Guardar en un archivo las palabras cuando se produzca un cambio.

Y éstos en el programa del PC (vb.net) para reconstruir el pasado:

  • Leer los registros en un intervalo de tiempo.
  • Decodificarlos a binario para poder ver cada I/O por separado.
  • Mostrar en una tabla los cambios y el momento.
  • Mostrar gráficamente estos estados.

Programa de PLC.

Lógicamente tendremos que declarar las entradas/salidas y dos variables que guardarán el estado de las I/0 en formato INT.

El resto del programa es asignar las entradas a la variable EstadoIn y las salidas a la variable EstadoOut. Para extraer un bit de una palabra basta con poner un “.” Y el número de bit. Por ejemplo Var.2 es el bit 2 de la variable Var.

Y esta es la función que convierte valores INT ó UINT a binario. Mediante esta función podremos obtener el estado de un bit, guardar grupos de valores binarios en un valor INT, etc.

La figura muestra el cálculo necesario. Consiste en dividir entre dos mientras el resto sea mayor de uno. Los bit serán los cociente.

Y esta es la función:

A esta función le entregamos un valor INT o UINT y nos devuelve un texto con el valor en binario 16 bit. Más tarde haremos otra función que usando esta nos devuelva el valor (TRUE/FALSE) de un bit.

INT vs UINT.

Los valores INT van desde -32767 hasta + 32767. O lo que es lo mismo, un valor de 15 bit (2 ^ 15) y un bit para el signo. Los valores UINT van desde 0 hasta 65536 y no existen valores negativos (2^16). Cuando leemos una variable del PLC desde vb.net u otro programa, no sabemos cómo se declaró en el PLC , leemos los bits y lo reconstruimos a INT o UINT. Por lo tanto podemos tener valores en el plc declarados como INT y en el PC reconstruidos como UINT. También podemos convertir valores UINT a INT.

Bien, en la primera parte de la función comprobamos si el valor es negativo, en ese caso sabemos con seguridad que es INT y lo convertimos a UINT para descomponerlo en bit. En los casos que sea positivo, no hay diferencias entre los dos tipos a la hora de convertirlos a bits.

Una vez hecho esto lo que hacemos es dividir entre dos el valor entregado en un bucle While End While. Este bucle se repite hasta que se cumple la condición de que el cociente sea < 1.

Mientras hacemos el bucle se almacenan los valores en una matriz de caracteres que contendrá 1 ó 0. Una vez terminado el bucle se convierte en una cadena de texto. Al pasarlo a cadena de texto rellenamos los valores vacíos con 0 hasta completar los 16 bits.

Esta misma función la utilizaremos para realizar otras tareas, como saber el estado de un bit (TRUE/FALSE).

En la próxima entrada realizaré el programa completo de registrar en el PC, cuando se produzca un cambio.

Registro de estados II. Guardar en PC.

En este proyecto añadiremos una mejora. Vamos a crear un control de usuario con el botón conectar. En otras palabras, construimos un botón con funcionalidad añadida. En nuestro caso el código necesario para conectarse al PLC. Si la conexión se realiza con éxito pondrá a true una variable pública de manera que podamos consultar el estado de la conexión. Si estamos conectados al PLC, el botón pasara a hacer la función de desconexión.

En este caso, dejaré el proyecto para descargar y me centro en explicar las funciones.

Una de las ventajas que debemos de aprovechar de vb.net es la llamada POO (programación orientada a objetos) aunque en un principio la utilizaremos de una forma muy rudimentaria, puesto que esto tiene muchas posibilidades y por lo tanto puede llegar a ser compleja. Empezaremos por crear pequeños controles reutilizables que nos ahorren algo de trabajo. Nuestro primer control será un botón que haga la función de conectar al PLC.

Vamos a agregar un control de usuarios, como muestra la siguiente imagen.

El control le pondremos ucBuConectar y agregar.

Dentro del pequeño formulario introducimos un botón y le cambiamos la propiedad Dock a Fill (El botón del centro) y el Text a Conectar. Reducimos el tamaño del formulario al ancho y largo del Boton, y pinchamos con el derecho ver código.

En el código crearemos unas propiedades que vendrían a ser como variables IN/OUT de los FB en programación del PLC. Para crear este código podemos utilizar una función del IDE que nos ahorra trabajo y nos ayuda con la memoria.

Seleccionamos Insertar fragmento de código del menú contextual que aparece al pinchar con el derecho el área de código.

Una vez seleccionado el código que queremos utilizar los escribirá por nosotros. Las áreas resaltadas en verde tienen ciertas características especiales. Las propiedades tienen dos variables, una que se utiliza dentro del control y otra pública que será accesible desde fuera del control. Podemos llamar a ambas variables con el mismo nombre al que añadimos algo para modificarlo, en mi caso la variable interna tendrá un carácter de subrayado ” _Var” y la pública, no ” Var”.

Los pasos son: modificar la variable interna, pulsamos tabulador y modificamos el tipo, en este caso boolean:

Y ahora modificamos la variable pública y tabulador. Automáticamente se modifica el resto de código y ya tenemos la propiedad lista para usarla.

Este control utilizará el evento del botón para conectarse al PLC. Hacemos doble click en el botón y escribimos el siguiente código:

El proyecto en detalle:

Cuando se inicia la aplicación se cargan los datos de la conexión en el control ucBuConectar.

Bien, cuando el usuario pulsa el botón, éste se conectará al PLC y activa un temporizador, como podemos ver en el código del ucBuConectar, en esta línea:

Form1.TimerRuntime.Enable = TRUE

Trascurrido el tiempo definido en las propiedades de el control Timer el programa se dirige hasta el siguiente evento:

De esta manera emulamos el funcionamiento de un PLC en el PC, creando una tarea repetitiva que actualiza el valor de las variables del PLC y demás tareas repetitivas que necesite nuestra aplicación. Cuando pasa por la función LeerUINT se dirige a esta función, que leerá las variables para almacenarlas en la variable global Valor. Cuando queramos consultar el valor de estas variables simplemente valor = Valor(numero de marca).

En el primer paso por el código, se inicializa las variables MemoIn y MemoOut con los valores de las variables del plc, y ponemos ConfInicial a True para que no vuelva a entrar. Lo siguiente es comprobar si ha cambiado el valor de las entradas o salidas, de ser así lo muestra en la texbox, que hemos llamado tbTrace y llama a la función Grabar.

Y tan fácil como el siguiente código para grabar un log.

Y éste es el resultado:

Naturalmente esto no tiene sentido para nosotros, y necesitaremos otra aplicación para convertir estos datos en una tabla, y un gráfico que nos ayude a visualizar de una forma comprensible esta información.

Desde aquí podéis descargar el proyecto PLC y PC. Os recuerdo que el este archivo se encuentra en el área de descarga del foro de Infoplc. Por lo tanto será necesario estar registrado para poder descargarlo. De todas formas, si alguien  no quiere registrarse solo tiene que escribir un comentario con su dirección correcta y os lo enviaré.

En la próxima entrada veremos como reconstruir estos datos para mostrarlos en una tabla y en un gráfico. Bueno, no sé si en la próxima o en las próximas.