Archive for septiembre, 2010

Tipos de datos V. Pointer.

Esto es lo que dice el manual de Beckhoff:

En los punteros se guardan las direcciones de variables o bloques de
funciones para el tiempo de ejecución de un programa.
Las declaraciones de
puntero tienen la siguiente sintaxis:

: POINTER TO
función>;

Un puntero puede indicar cualquier tipo de datos y bloque de funciones,
incluso de definición propia.

Con el operador de dirección ADR se asigna al
puntero una dirección de una variable o bloque de función.

La desreferenciación de un puntero se produce mediante el operador de
contenidos “^” tras el identificador del puntero.


 

Please note: A pointer is counted up
byte-wise ! You can get it counted up like it is usual in the C-Compiler by
using the instruction p=p+SIZEOF(p^);.

Y esto es lo que digo yo:
Un puntero nos permite cambiar, en tiempo de ejecución, la variable que queremos leer. Por ejemplo, si tenemos un variador de frecuencia que funciona con diferentes parámetros,  lo que todos llamamos recetas. Pues bien, podemos crear una estructura con esos valores, por ejemplo:

  • Velocidad.
  • Tiempo de aceleración.
  • Tiempo de deceleración.

y mediante un puntero cambiar la receta con la que vamos a trabajar, como muestra el ejemplo:

Como podemos ver en la figura, tenemos dos variables de tipo estructura que serán las dos recetas:

  • Conf1
  • Conf2

Y una tercera variable de este tipo (ConfActual),  será la que reciba la receta actual para enviarla a los variadores. Mediante la variable Selec1, seleccionamos la receta a utilizar.

El puntero V1 almacena la direción de la variable, y con el operador de desreferenciación (la ostia que palabra, tú) ^ la pasamos a ConfActual.

De este modo el proceso es el siguiente:
Mediante ADR pasamos la dirección de la variable a el puntero.

1
V1 := ADR(Conf1);

Mediante ^ pasamos el valor de la variable apuntada.

1
ConfActual := V1^;

Código completo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(*ZONA Variables*)
PROGRAM MAIN(*                         ---xxX POINTER Xxx---*)
VAR
	Conf1:Conf;
        Conf2:Conf;
        ConfActual:Conf;
        V1:POINTER TO Conf;
	Selec1:BOOL;
END_VAR
(*ZONA Programa*)
IF Selec1 THEN
	V1 := ADR(Conf1);
ELSE
	V1 := ADR(Conf2);
END_IF;
ConfActual := V1^;

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 II. Arrays.

Antes de continuar deciros que podéis ampliar información en la ayuda de Plc Control, en Information System.

Arrays.

En Plc Control se pueden crear arrays de hasta tres dimensiones.

Ejemplos de declaración Codesys.

Array1 :ARRAY [0..9] OF INT;
 
Array2 :ARRAY[0..9,0..9,0..9] OF INT;

Ejemplo de declaración de array en Vb.net.

Dim Array1(10) As Short
 
Dim Array2(10,10) As Short

Programa ejemplo para Codesys.

(*ZONA DE DECLARACIÖN*)
PROGRAM MAIN
VAR
	Memo :ARRAY[0..9] OF INT;
	Suma:INT;
	Valor:INT;
	MemoValor:INT;
	Media:INT;
	Indice:INT;
	i: BYTE;
	conf :BOOL;
END_VAR
(*ZONA DE PROGRAMA*)
(*En este ejemplo calculamos la media de la variable valor. En lugar de hacerlo en un tiempo
determinado lo haremos por cambio de valor de la variable de proceso. De esta manera la media
se actualiza mas rápido cuando los cambio son rápidos. Pero TIENE EL GRAN INCONVENIENTE
QUE SI NO CAMBIAN EL VALOR NO CAMBIARA LA MEDIA. Es solo un ejemplo*)
 
(*Configuración para el primer ciclo de scan
cuando la variable Valor es distinta de 0 llenamos la matriz con ese valor *)
IF NOT Conf AND Valor <> 0 THEN
	FOR i := 0 TO 9 DO
		Memo[i] := Valor;
	END_FOR;
	Conf := TRUE;
	MemoValor := Valor;
END_IF ;
(*Si cambia la variable Valor llenamos el siguiente registro de la matriz*)
IF Valor <> MemoValor THEN
	Memo[indice] := Valor;
	Indice := Indice + 1;
	IF Indice > 9 THEN Indice := 0; END_IF;
	MemoValor := Valor;
END_IF;
(*Calculamos la media*)
Suma := 0;
i:= 0;
FOR i := 0 TO 9 DO
	Suma :=Suma +  Memo[i];
END_FOR;
IF Suma <> 0 THEN Media := Suma / 10; ELSE Media := 0; END_IF;
(*FIN*)

Programa ejemplo para Vb.net

Public Class Form1
    Dim Memo(10) As Short
    Dim MemoValor As Short
    Dim Conf As Short
    Dim Indice As Byte
 
    Private Sub buActualizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buActualizar.Click
        Dim Valor As Short = TextBox1.Text
        Dim Media As Short
        Dim Suma As Short
        Dim i As Integer
        'Configuración para la primera actualización
        If Not Conf And Valor <> 0 Then
            For i = 0 To 9
                Memo(i) = Valor
            Next
            Conf = True
            MemoValor = Valor
        End If
        'Si cambia la variable valor llenamos el siguiente registro de la matriz
        If Valor <> MemoValor Then
            Memo(Indice) = Valor
            Indice += 1
            If Indice > 9 Then Indice = 0
            MemoValor = Valor
        End If
        'Calculamos la media
        For i = 0 To 9
            Suma += Memo(i)
        Next
        'Comprobamos que la  suma no sea 0 para no dividir por 0
        If Suma <>  0 Then Media = Suma / 10 Else Media = 0
 
        laMedia.Text = Media
 
    End Sub
End Class

NOTA: He modificado el programa de las cajas de código para poder ver el ST, aun quedan algunos detalles pero espero ir retocándolo (cuando tenga un poco de tiempo).