Archive for the ‘ Sin categoría ’ Category

Lavadora Web 2.0. Los recursos necesarios.

Para poder afrontar los siguientes pasos de la lavadora web, necesitamos ciertos recursos para poder interactuar con la base de datos. MySql dispone de un conector para vb.net pero no es compatible con las versiones express. Por este motivo utilizaremos MySqlDriverCs que podéis descargar desde aquí.

Para crear el código de las páginas web, se puede utilizar el bloc de notas, pero es de agradecer ciertas ayudas como el resaltado de código y algunas ayudas mas. En mi caso para las aplicaciones web utilizo Pspad.

En cuanto a la gestión de la base de datos, xammp incluye phpMyAdmin que permite interactuar con la base de datos para crear usuarios, tablas, etc. De todas formas os recomiendo MySqlWorkbench que es mucho mas potente y amigable (para mi). Lo podéis descargar desde aquí.

Respecto a Workbench tenemos varias posibilidades, yo he marcado dos. En la primera (flecha negra) es para instalar, la segunda opción no se instala. Es la que yo utilizo. Descargamos el archivo, lo descomprimimos y guardamos la carpeta en C/. Si queremos, podemos crear un acceso directo y ponerlo en el escritorio o anclarlo en la barra de W7.

La secuencia de la lavadora web.

He creado una secuencia en plc control para continuar con la lavadora web. En un principio pensé en hacer esta secuencia en vb.net, pero me ha parecido más interesante hacerla con plc control. Así, de paso, vemos una secuencia creada en ST (Texto Extructurado).Despues de tener la lavadora funcionando, haré la supervisión en vb.net y el guardado en MySql.

La secuencia es una versión beta que modificaremos sobre la marcha. En el siguiente paso crearé la interface en vb.net.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
VAR_GLOBAL
	Y1 AT %Q*:BOOL; (*Electroválvula cajon*)
	Y2 AT %Q*:BOOL;	(*Electroválvula Bombo*)
	M1 AT %Q*:BOOL;	(*Motor bombo*)
	M2 AT %Q*:BOOL;	(*Motor desagüe*)
	X1 AT %Q*:BOOL;	(*Bloqueo puerta*)
	Resistencia AT %Q*:BOOL;
	CajonCerrado AT %I*:BOOL;
	PuertaCerrada AT %I*:BOOL;
 
	InicioLavado:BOOL;
	Temperatura:INT;
	NivelAgua:INT;
 
END_VAR
 
PROGRAM MAIN
VAR
	stateMain:INT;
	Aviso:INT;
	txtAviso:STRING;
	PermisoCalentar: BOOL;
	Termostato: BOOL;
	Pulso1Sec: TON;
	Espera: INT;
END_VAR
 
(*LLamada a subprogramas*)
SecCalentar();
 
(*Otros*)
Pulso1Sec(IN:=NOT Pulso1Sec.Q, PT:= T#1s);
 
 
 
 
CASE stateMain OF
0:(*Comprobar condiciónes para inicio*)
	IF NOT  CajonCerrado THEN
		Aviso := 1;
		txtAviso :='Cajon sin cerrar';
	ELSE
		IF NOT PuertaCerrada THEN
			Aviso := 2; (*Puerta sin cerrar*)
			txtAviso :='Puerta sin cerrar';
		ELSE
			Aviso := 3;
			txtAviso :='Preparado para inicio';
			IF InicioLavado THEN
				stateMain:= 10;
				InicioLavado := FALSE;
			END_IF
		END_IF
	END_IF
 
10:(*Bloqueo de puerta*)
	X1 := TRUE;
	stateMain := 20;
20:(*Llenar de agua I*)
	Espera := 30;
	stateMain :=21;
	Y2:= TRUE;
21:(*Llenar de agua II*)
	IF Espera > 0 AND Pulso1Sec.Q THEN
		Espera := Espera - 1;
		Aviso := 20;
		txtAviso :='Llenado de agua';
	END_IF
	IF Espera < 1 THEN
		Espera := 0;
		stateMain := 30;
	END_IF;
30:(*Calentar agua*)
	PermisoCalentar := TRUE;
	stateMAIN := 40;
40:(*Esperar hasta conseguir temperatura*)
	IF Temperatura > 60 THEN
		stateMain:= 50;
	END_IF
	Aviso := 40;
	txtAviso :='Calentando agua';
50:(*Mover bombo con agua, esto tendrá un nombre pero...*)
	Espera := 20;
	stateMain := 51;
	M1 :=TRUE;
51:(*Continua mover bombo*)
	IF Espera > 0 AND Pulso1Sec.Q THEN
		Espera := Espera - 1;
		Aviso := 50;
		txtAviso :='Moviendo bombo';
	END_IF
	IF Espera > 1 THEN
		Espera := 0;
		stateMain := 60;
	END_IF;
60:(*Abrimos electroválvula jabon I*)
	Espera := 5;
	stateMain := 61;
	Y1 :=TRUE;
61:(*Continua mover bombo*)
	IF Espera > 0 AND Pulso1Sec.Q THEN
		Espera := Espera - 1;
		Aviso := 60;
		txtAviso :='Introducir jabon';
	END_IF
	IF Espera < 1 THEN
		Espera := 0;
		stateMain := 70;
	END_IF;
70:(*Cerramos jabon*)
	Y1:= FALSE;
	stateMain := 80;
80:(*Lavando*)
	Espera := 25;
	stateMain := 81;
81:(*Continua lavado*)
	IF Espera > 0 AND Pulso1Sec.Q THEN
		Espera := Espera - 1;
		Aviso := 60;
		txtAviso :='Lavando';
	END_IF
	IF Espera < 1 THEN
		Espera := 0;
		stateMain := 90;
	END_IF;
90:(*Extraer agua*)
	Espera := 25;
	stateMain := 91;
	M2 := TRUE;
91:(*Continua Extraer agua*)
	IF Espera > 0 AND Pulso1Sec.Q THEN
		Espera := Espera - 1;
		Aviso := 90;
		txtAviso :='Sacando agua';
	END_IF
	IF Espera < 1 THEN
		Espera := 0;
		stateMain := 100;
	END_IF;
100:(*Llenar agua  y extraer*)
	Espera := 25;
	stateMain := 101;
 
101:(*Continua llenar agua y extraer*)
	IF Espera > 0 AND Pulso1Sec.Q THEN
		Espera := Espera - 1;
		Aviso := 60;
		txtAviso :='Llenar agua y extraer';
	END_IF
	IF Espera < 1 THEN
		Espera := 0;
		stateMain := 110;
	END_IF;
110:(*Paramos agua y extraer*)
	M2:= FALSE;
	Y2:= FALSE;
	stateMain := 120;
120:(*Centrifugar, para simplificar sólo dejo el bombo en marcha un tiempo*)
	Espera := 25;
	stateMain := 121;
 
121:(*Continúa centrifugado*)
	IF Espera &gt; 0 AND Pulso1Sec.Q THEN
		Espera := Espera - 1;
		Aviso := 120;
		txtAviso :='Centrifugado';
	END_IF
	IF Espera < 1 THEN
		Espera := 0;
		stateMain := 130;
	END_IF;
130:(*Fin lavado*)
	M1:= FALSE;
	X1:= FALSE;
	Aviso :=0;
	stateMain :=0;
END_CASE
 
PROGRAM Simular
VAR
	Pulso1Sec: TON;
END_VAR
 
Pulso1Sec(IN:=NOT Pulso1Sec.Q, PT:= T#1s);
 
IF Pulso1Sec.Q AND Resistencia THEN
	Temperatura := Temperatura + 1;
END_IF
 
IF Y2 THEN
	NivelAgua := NivelAgua + 1;
END_IF;

Dentro del programa creado en ST he añadido una ACTION en LEADER. Esto nos permite hacer ciertas líneas de código en otro lenguaje por diferentes razones.

Este es el árbol del programa:

Y este el action:

La secuencia se construye con un CASE. Cuando el plc lee la instrucción CASE, lee el valor de la variable que sigue a esta palabra clave. Luego leerá sólo el código que este seguido de este valor y sólo ese hasta el siguiente ciclo de scan. 

CASE <variable> OF
<Valor>: Codigo
<Valor>: Codigo
END_CASE

En el siguiente ejemplo si Var = 1, se pone M1 a true y si Var = 2, se pone Y2 a FALSE. Esto es equivalente a hacer un SET.

CASE Var OF
1:M1:=TRUE;
2:Y2:=FALSE;
END_CASE

Otra cosa que me parece interesante es la variable txtAviso. Esta variable de tipo STRING nos informa de el estado actual de la máquina, a efecto de depuración creo que puede ser interesante.

Bueno y por el momento esto es todo, cualquier cosa un comentario. Y el programa lo dejo en la próxima entrada con la aplicación en vb.net.

Simular Modbus

Bueno, primero de todo quería pedir disculpas por dejar parado el blog. Últimamente me he metido en demasiados líos y ando con el tiempo justito, justito.

Hace poco tiempo, me vi en la necesidad de desarrollar una aplicación web, para supervisar una instalación con un autómata telemecanique. Como protocolo de comunicaciones preferí utilizar Modbus rtu. Pero tenía que terminar el proyecto en casa, y no me apetecía montar un autómata con el jaleo de cables y demás, para hacer las pruebas. Así que busque la forma de poder simular el funcionamiento y, por suerte, pronto encontré la solucción.

Utilicé un simulador de modbus libre llamado Modbus_RcSim, lo siguiente era encontrar la forma de comunicar éste con mi aplicación, para esto usé VSPE, Virtual Serial Port Emulator. Este interesante programa, nos permite realizar algunas cosas interesantes con los puertos series. En este caso, lo usé para crear dos puertos series virtuales conectados entre sí. De esta manera podía establecer una comunicación con RcSim y mi aplicación.

El resto del trabajo era poner en marcha una aplicación en Vb.net, que fuera capaz de leer modbus y servir los datos a php para hacer  la aplicación web. Para poder leer modbus utilice una libreria libre modbus llamada NModbus.

Mucho pequeño = Muy grande.

En mi humilde opinión, creo que un mundo nuevo se abre en el futuro próximo, por no decir el presente. Y la verdad, no veo movimientos en este sentido. ¿Por qué?. Bueno, bueno, me explico.

Con este blog y mis proyectos he utilizado mucho software libre, y la verdad es que he quedado  gratamente sorprendido por lo que he visto. Hay maravillas esperando a ser utilizadas. Como son el software que hace posible este blog (wordpress), bases de datos, servidores web, IDE`s, programas de retoque fotográfico, gráficos vectoriales, etc.

Y yo me pregunto, ¿Por qué no podemos hacer nosotros lo mismo?. De hecho, ya existen desarrollos en este sentido, como la librería OSCAT para plc programados con Codesys.

Recientemente, he andado programando con php para hacer aplicaciones web, para la supervisión de cámaras frigoríficas. El resultado me tiene aún alucinando, aunque quede mucho trabajo por hacer. El coste de una aplicación de este tipo permite crear sistemas de supervisión con un coste realmente asequible y con posibilidades infinitas. Sólo requiere una cosa, tiempo.

Sí, estamos de acuerdo, el tiempo vale dinero, perdón mucho dinero. Pero lo importante de todo esto, es que una vez creada una función, ésta puede ser reutilizada un número infinito de veces y mejorarla requiere poco tiempo.

Está claro que yo, como programador que hago mis propios desarrollos, no soy nada comparado con marcas como eliwell, ako, osaka (frio) o siemens, telemecanique, indusoft, etc (SCADAS). Pero sí veo que tengo un hueco en este mundo, mis proyectos salen a delante, los clientes quedan contentos, etc. El secreto es trabajar, trabajar y trabajar.
Trabajar para crear FB, por ejemplo, que convierten presión en temperatura para el 404, otra para el 134, 22, NH3,… Trabajar para crear unas funciones que permiten graficar temperatura, envío de mail y sms, recibir sms, etc. Otro programador se verá en las mismas necesidades y creará sus propias funciones, y ahí estamos trabajando, trabajando, trabajando para hacer todos lo mismo.

Sinceramente, creo que se podrían aunar esfuerzos en este sentido. No es una tarea fácil sentar las bases de una colaboración, aún no sé ni cómo se podría hacer, pero creo firmemente en esta idea.

Bueno, ¿Qué pensáis de esto?.

Lavadora web I.

Durante algunos post, realizaré un sistema de supervisión  de una lavadora. El hecho de utilizar la lavadora, es por hacer algo genérico que todos entenderemos. ¿Quién no ha puesto una lavadora? …

La idea es crear una simulación de la lavadora en vb.net, que esta aplicación guarde los estados en Mysql y más tarde generar una web de supervisión. He utilizado Inkscape para realizar las imágenes, mwsnap y beneton movie gif para realizar los gif animados. Esta es la lavadora:

La cuestión es sustituir los motores, el bombo y las válvulas por gif animados cuando estén en marcha. Además añadiremos algunos valores como: tiempo restante de funcionamiento, nivel de agua, temperatura del agua, etc. Por supuesto que mis conocimientos sobre lavadoras son meramente contemplativos, y esto es solo un ejemplo que nada tiene que ver con la realidad. Es la única lavadora web del mundo y no creo que consigamos que limpie nada.

Elementos:
Y1 es una electroválvula que permite el paso de  agua en el cajón del jabón para que se limpie.
Y2 es la electroválvula de llenado.
M1 es el motor que hace girar el bombo.
M2 es la bomba de desagüe.
X1 es un pequeño cerrojo eléctrico que bloquea la puerta.
Ademas de esto, tenemos un sensor para saber cuando el cajón del jabón está cerrado, y otro para cuando la puerta esta cerrada.

Estos son los elementos que sustituyen para dar la sensación de funcionamiento:

Fig. 1 Preparada para empezar, puerta y cajón cerrados.

Fig. 2 Bomba desagüe.

Fig. 3 Motor.

Fig. 4 Bombo con la puerta cerrada.

Fig. 5 Bloqueo puerta.

Fig. 6 Electroválvulas.

El siguiente paso es crear la aplicación en vb.net, y guardar los datos en la bd (MySql), para poder crear la aplicación en php.

Interface grafica I.

En esta entrada he realizado un pequeño ejemplo de una interface grafica tipo HMI con vb.net. El programa en Vb.net simula el funcionamiento de una cámara frigorífica y controla los elementos graficos, que como veremos es la parte mas fácil.

Para aumentar el efecto y simplificar la realización he utilizado imagenes .gif, que como todos sabemos son las tipicas imágenes con movimiento, para muestra un botón.

Bueno, la idea era hacer un ejemplo, no una maravilla. Para realizar esta imagen he utilizado un programita Java, muy sencillo, vamos hipersencillo. Lo podéis descargar desde aquí. Solo hay que pinchar en abrir, seleccionar todas la imágenes que forma el gif, cambiar el tiempo de refresco  y listo. Aquí un vídeo demostrativo.

El sinóptico esta creado con google Scketchup y es este:

Está coloreado con el paint, recortamos los bloques, compresor, ventilador, solenoide, etc., y los coloreamos y giramos para formas los gif necesarios:

El resto del proceso es muy sencillo. Ponemos un picturebox en nuestro formulario principal, con el tamaño que queramos, que tenga el sinóptico. Y luego vamos poniendo otros picturebox con los gifs y le cambiamos la propiedad visible a false. Puedes ver los anteriores post para repasar el proceso.

Como dije al principio, he añadido el código necesario para simular el funcionamiento. Os dejo el proyecto completo aquí. Y si quereis algún gif, sólo teneis que descargarlos directamente, derecho y guardar imagen, aunque creo que son mejorables.

Este es el código de vb.net:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
Public Class Form1
    'Variables globales
    Dim Temp, Pa, Pb As Integer
    Dim C, Sol, Co1, Co2, Evap As Boolean
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Enabled = True
        Button2.Tag = False
    End Sub
 
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Timer1.Enabled = False
 
 
        'Simula las entradas de calor a la camara
        Temp = Temp + 1
        'Simula el descenso de temperatura por el equipo frigorifico
        If C Then Temp = Temp - 2
        'Termostato
        If Temp > 120 Then
            Sol = True
        ElseIf Temp < 100 Then
            Sol = False
        End If
        'Simula el cambio de presión en baja
        If Sol And Not C Then
            Pb = Pb + 1
        ElseIf C And Not Sol Then
            Pb = Pb - 1
        End If
 
        If Sol And Not C Then
            Pb = Pb + 1
        End If
        'Arranque del compresor por pb (Presión de baja)
        If Pb > 30 Then
            C = True
        ElseIf Pb < 20 Then
            C = False
        End If
        'Simula la presión de alta
        If C And Not Co2 Then
            Pa = Pa + 1
        ElseIf Co2 Then
            Pa = Pa - 2
        End If
        'Arranque de condensador para control de condensación
        If Pa > 150 Then
            Co2 = True
        ElseIf Pa < 145 Then
            Co2 = False
        End If
 
        'El primer vent de condensador entra con el compresor y el vent de evaporador con la solenoide
        Co1 = C
        Evap = Sol
 
        'Asignar imagen
        Img(pbCompresor, C)
        Img(pbSolenoide, Sol)
        Img(pbVentCo1, Co1)
        Img(pbVentCo2, Co2)
        Img(pbVentEvap, Evap)
        'Tempreturas y presiones
        laTemp.Text = Temp / 10
        laPa.Text = Pa / 10
        laPb.Text = Pb / 10
        'Si se pulso en parar no reactivamos el timer para detener la simulación
        If Button2.Tag = False Then
            Timer1.Enabled = True
        End If
 
    End Sub
 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        'para parar el simulador
        sender.Tag = True
    End Sub
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Temp = 100
        Pa = 100
        Pb = 20
    End Sub
    Private Sub Img(ByVal Pb As PictureBox, ByVal Estado As Boolean)
        If Estado Then
            Pb.Visible = True
        Else
            Pb.Visible = False
        End If
    End Sub
End Class

SFC. Rutina de inicio.

En esta entrada, mostraré un pequeño ejemplo en lenguaje SFC (Secuencial Funtion Chart, diagrama de secuencia de funciones). La verdad es que nunca he hecho nada en este lenguaje, pero está claro que puede ser un importante apoyo para trabajar con ST. Total que intentaré ir aprendiendo y mostrando los avances.
Bueno al grano. En este primer ejemplo he realizado una pequeña secuencia como muestra la figura:

Como puede verse, he creado dos variables globales Rst y OK. La secuencia es la siguiente:
El plc se pone en Run y se activa al paso EsperaOff durante  el tiempo T_espera. Transcurrido este tiempo, se activa el  paso BorrarAlarmas del que saldrá transcurrido el tiempo T_Rst. Al entrar en este paso (E) , se activa la marca Rst y al salir se borra. El siguiente paso sera SistemaOn, y hay permanece mientras el PLC no se reinicie. Esta rutina puede servir para temporizar todos los equipos ante una falta de suministro eléctrico y un borrado de alarmas antes de volver arrancar.

EsperaOff.
En este paso he añadido un tiempo mínimo, de manera que aunque la condición para continuar es True, no lo hará hasta no completar el tiempo mínimo. Esto lo hacemos con el menú contextual y Step Attributes. En este caso he utilizado una variable time pero igualmente podríamos haber utilizado un tiempo directamente (T#5s).

BorrarAlarmas.
Ademas del atributo de tiempo, he añadido una Acción de entrada (E) y otra de salida (X). Lo hacemos, igualmente con el menú contextual y Add Entry-Action o Add Exit-Action. Al hacer click sobre una de estas acciones nos preguntará en que lenguaje queremos añadir la entrada. En mi caso he elegido ST, se abre el editor y ponemos Rst:=TRUE; para la acción de entrada y Rst:=FALSE; para la acción de salida.

SistemaOn.
En este paso he añadido una acción, hacemos click sobre el paso, nos pregunta el lenguaje, marcamos ST  y en el editor ponemos Ok:=TRUE;

La siguiente figura muestra el menú contextual:

Tipos de datos IV. Enumeraciones.

El tipo de dato Enumeración que forma parte de los tipos definidos por el usuario, nos permite llamar a las cosas por su nombre y aun así, poder sumar, restar, etc. ¿Que diría de esto la de sumar peras con manzanas?, en fin, eso es otro tema.

Para declararlo lo hacemos igual que con las estructuras, borramos lo de estructuras y ponemos la enumeración, como muestra la siguiente imagen:

En este caso hemos utilizado el recurrido recurso del semáforo. El siguiente ejemplo muestra un ejemplo de programa donde simulamos el funcionamiento de un semáforo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PROGRAM MAIN
VAR
	Color1: Colores;
	Cambiar:BOOL;
	TiempoAm: TON;
	TiempoRoj: TON;
	TiempoVer: TON;
END_VAR
 
IF Cambiar = TRUE THEN
	Color1 := Color1 +1;
	IF Color1 > 2 THEN Color1 := 0;END_IF;
	Cambiar := FALSE;
END_IF;
 
TiempoAm(IN:= Color1 = Amarillo, PT:= T#5s);
TiempoRoj(IN:= Color1 = rojo, PT:= T#10s);
TiempoVer(IN:= Color1 = verde, PT := T#7s);
 
IF TiempoAm.Q OR TiempoRoj.Q OR TiempoVer.Q THEN
	Cambiar := TRUE;
END_IF;

Y esta es la declaración y uso de enumeraciones en vb.net

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Public Class Form1
    Enum Colores
        Amarillo
        Rojo
        Verde
    End Enum
    Dim Sema1 As Colores
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
        Sema1 += 1
 
 
    End Sub
End Class

Tipos de datos III. Structuras.

Podemos decir que una estructura es una forma de organizar una serie de variables relacionadas. Un ejemplo puede ser el control de un registro. Supongamos que tenemos una temperatura y queremos controlar que no supere unos valores.
Generaremos las siguientes variables dentro de la estructura:

1
2
3
4
	Valor: INT;
	Maximo: INT;
	Minimo: INT;
	Alarma: BOOL;

Declaración de structuras:

Para declarar las estructuras tenemos que ir a Data types, pinchamos con el derecho y Add Object.

Y declaramos las diferentes variables con sus tipos:

Al definir la estructura hemos definido un tipo pero aún no tenemos declarada ninguna variable de este tipo. Para trabajar con las estructuras deberemos declara una variable de este tipo, en este caso Reg.

El ejemplo anterior muestra como declarar esta variable y como utilizarla posteriormente en el programa. Con este ejemplo quizás no le veamos demasiado sentido a este tipo de dato, pero veamos un ejemplo algo más complejo creando una matriz de estructura.

Ejemplo del uso de estructuras y matrices de estructuras para Codesys.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(*ZONA DECLARACIÓN DE VARIABLES*)
PROGRAM MAIN
VAR
	Reg1:ARRAY[0..100] OF Reg;
	i:BYTE;
END_VAR
(*ZONA DE PROGRAMA*)
FOR i := 0 TO 100 DO
	IF Reg1[i].Valor > Reg1[i].Maximo OR Reg1[i].Valor < Reg1[i].MInimo THEN
		Reg1[i].Alarma := TRUE;
	ELSE
		Reg1[i].Alarma := FALSE;
	END_IF;
END_FOR;

Y este es el resultado

Ejemplo del uso de estructuras y matrices de estructuras para Vb.net. Para que el programa funcione de una manera analoga a como lo Plc Control he creado un control timer que hará que el código se lea de forma recurrente cada seg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
Public Class Form1
    Structure Reg
        Dim Valor As Short
        Dim Maximo As Short
        Dim Minimo As Short
        Dim Alarma As Boolean
    End Structure
    Dim Reg1(101) As Reg
 
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim i As Integer
        For i = 0 To 100
            If Reg1(i).Valor > Reg1(i).Maximo Or Reg1(i).Valor < Reg1(i).Minimo Then
                Reg1(i).Alarma = True
            Else
                Reg1(i).Alarma = False
            End If
        Next
    End Sub
End Class

Y este es el resultado:

Como se puede ver en la imagen he creado un BreakPoint para poder ver lo que pasa en el código. Si nos situamos encima de la variable Reg1 podremos ver los valores, así como modificarlos pinchando en el valor.

Tipos de datos I. Tipos de datos estándar.

En esta entrada repasare los tipos de datos en Codesys y el equivalente en vb.net.

Resumen de tipos de datos estándar.

Tipo de dato Codesys vb.net Limites Uso memoria
BOOL BOOL Boolean TRUE ò FALSE 1 bit
BYTE BYTE Byte 0 a 255 8 Bit
WORD WORD UShort 0 a 65535 16 Bit
DWORD UInteger 0 a 4294967295 32 Bit
Simple integer SINT Sbyte -128 a 127 8 Bit
Unsigned Simple Integer USINT Byte 0 a 255 8 Bit
Integer INT Short -32768 a 32767 16 Bit
Unsigned integer UINT UShort 0 a 65535 16 Bit
Double integer DINT Integer -2147483648 a 2147483647 32 Bit
UDINT UInteger 0 a 4294967295 32 Bit
REAL Single* -3.402823 E38 a 3.402823 E38 32 Bit
LREAL Double* -1.79769313486231E308 a 1.79769313486232E308 64 Bit
Cadena de caracteres STRING String* Nota 1
TIME Date* T#0ms a T#71582m47s295ms 32 Bit
TIME_OF_DAY Date* TOD#00:00 a TOD#1193:02:47.295 32 Bit
Fecha DATE Date* D#1970-01-01 D#2106-02-06 32 Bit
Fecha y hora DATE_AND_TIME Date* DT#1970-01-01-00:00 a DT#2106-02-06-06:28:15 32 Bit

*Estos tipos no tienen una equivalencia exacta.

NOTA 1: El tamaño por defecto es 80, para otro numero de caracteres se debe especificar en la declaración (str:STRING(35):=’Esto es una declaración String’;). Uso de memoria [BYTE] = Tamaño + 1 Byte para carácter nulo de terminación.

Todos son bit.

Entiendo que en un principio esto puede ser un poco confuso. Para mi la clave está en pensar que todo son bit y lo único que cambia es la forma de interpretar estos bit. Para muestra un botón. En la siguiente figura puedes ver tres tipos diferentes de variables (INT, UINT, TIME) direccionadas a la misma área de memoria y como se visualizan en función del tipo. También he declarado 16 variables del tipo BOOL y los he asignados a cada bit de VarINT.

No todos son bit.

TwinCat, cuando corre en PC guarda los datos boolean en Byte. Si no utilizamos las variables direccionadas (AT %MX) no nos importara pero hay que tenerlo en cuenta cuando se direccionan.

Variables STRING.

Las variables string almacenan en BYTE el código ascii equivalente al carácter en cuestión. En la siguiente imagen puedes ver dos variables, la variable VarVer es un ARRAY (Matriz o vector) de 11 elementos (0 a 10) de tipo BYTE. La variable VarStr es una variable string(10), ambas están direccionadas en el mismo área de memoria, por lo tanto lo que escribimos en una, lo podemos ver en la otra. Como puedes comprobar en la tabla del código ascii, cada BYTE almacena el código ascii equivalente. También podréis ver que el ultimo BYTE se reserva para el caracter NUL(0).

Código ASCII.

Los 32 primeros códigos pertenecen al grupo de los no imprimibles y son utilizados para enviar códigos como retorno de carro, fin de mensaje en protocolos de comunicación, etc.

Tipos de datos de tiempo.

Creo que merecen un post exclusivo que le dedicaré en breve.