Archive for the ‘ Conceptos basicos ’ Category

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 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).

Vb.net 1 y 3/4

Capturando excepciones.

Como decíamos en el anterior post, tenemos un superinformático en el PC, también conocido como Framewoks y al que cariñosamente llamamos Marcos. También, decíamos que era capaz de saber si lo que le pedíamos en el código era lógico o imposible de realizar. Bueno pues hay una forma de establecer un diálogo con Marcos, de manera que nos informe de errores para buscar un camino alternativo y que la aplicación siga funcionando.

La estructura es la siguiente:

Try
'Aqui el codigo que queremos que supervise
Catch ex As Exception
'Aquí el codigo alternativo por si falla el anterior
End Try

Cuando Marcos  lee la palabra Try sabe que tiene que estar atento, en caso de producirse un error: error de comunicación, salirse de los índices de una matriz, etc; abandona el código que está leyendo, guarda el nombre del error en la variable ex y continúa leyendo el código  situado debajo de Catch.

Trabajando con consola. Un ejemplo de excepción.

Este tipo de aplicaciones están muy bien para hacer pruebas puesto que nos permite olvidarnos de la interface gráfica.

Crea una nueva aplicación y haz doble click sobre aplicación de consola. Copia y pega el siguiente código. Y dale al play. Cuando te pide un numero prueba a introducir una letra.

1: 'Pedimos un numero'
Console.WriteLine("Introduce un numero?")
'Inicializamos una variable de tipo integer'
Dim Respuesta As Integer
Try
'Cogemos el valor introducido y lo volcamos a la variable Respuesta'
Respuesta = Console.ReadLine()
'Le damos animos al usario por que sabe lo que es un numero'
Console.WriteLine("Bien, bien")
Catch ex As Exception
'Recogemos la excepción en caso de que el usuario sea un negao'
Console.WriteLine("Que nohhhhh. ¡Un numero!")
End Try
Console.WriteLine("Escribe 1 para continuar")
'vemos lo que ha escrito si es uno se va a la etiqueta 1: al principio del programa'
If Console.ReadLine = 1 Then
GoTo 1
Else
'en caso de no ser 1 salimos del programa'
Console.WriteLine("Pulsa intro para salir")
Console.Read()
End If

Depurando.

Los BreakPoint.

El IDE tiene algunas funciones para poder depurar nuestra aplicación.

Si hacemos click en el área gris a la izquierda del código, aparece un punto rojo. Cuando se ejecute la aplicación se detendrá al llegar a ese punto. Esto nos permite conocer el valor de las variables en ese instante. O por ejemplo saber si el programa entró en esa línea.

Si pasamos el ratón por una variable nos mostrará su valor.

Tenemos varias ventanas para saber más. Por defecto se encuentran en la parte más inferior del IDE.

Si el IDE no muestra estas ventanas podemos activarlas desde la barra de herramientas.

Para que el programa se detenga donde se ha colocado el breakpoint, tenemos que haber introducido un valor no válido para una variable integer. Si introducimos un valor válido Marcos no leerá esa línea de código.

Si queremos que la aplicación no vuelva a parar en el punto hacemos click en el BreakPoint para borrarlo.

También podemos mover el punto donde está detenido el programa, por ejemplo para saltar o volver a cargar.

Con este código:

Debug.WriteLine(“El valor de la variable es “ & Valor)

podemos escribir en la ventana inmediato.

Entradas analógicas.

Las entradas analógicas son utilizadas para leer valores como temperatura,  presión, intensidad, etc. Este valor se almacena  en una variable del PLC.  Por ejemplo:

TempCam1 AT %I* :INT;

El prefijo AT es utilizado para asignar la variable en una posición fija de memoria. En este caso I representa las entradas. En otros plc las variables siempre están asignadas a posiciones pero en este entorno de programación no es necesario y podemos simplemente declarar las variables con el tipo (Var:INT; ). Otros área de memoria son:

Entradas %I

Salidas %Q

Marca internas %M

El asterisco le dice al programa que esta entrada la queremos asignar mediante System manager. En el caso de Beckhoff, lo normal es que las entradas/salidas no tengan una dirección fija y se asignan mediante  system manager.

INT es integer, una variable de 16 bit con  signo.

¿Como almacenamos valores en bit?.

Supongamos que tenemos dos bit. Cada bit almacena dos estados (0 y 1) ó (True, False). Con estos dos bit podemos tener 4 combinaciones:

00 : 0

01 : 1

10 : 2

11 : 3

El resultado es que según el número de bit podemos tener 2 ^ (numero de bit)  posibilidades. 2 ^2 = 4. Por lo tanto, con dos bit podríamos almacenar un numero del 0 al 3. Para un valor con 16 bit podemos almacenar un valor comprendido entre 0 y 65535 (2^16 = 65536). Este tipo de dato se llama UINT integer sin signo. En el primer ejemplo utilizamos una variable llamada INT, integer 16 bit con signo. El primer bit se utiliza para el signo y los 15 restantes para el valor, por lo tanto 2^15 = 32768. De esta manera en una variable INT podemos almacenar valores desde -32767 hasta +32767.

El módulo de entradas analógicas del PLC, será el encargado de transformar una señal eléctrica en un valor que se almacena en la variable asignada. Normalmente utilizaremos para este tipo de entradas una variable de tipo INT.

Los tipos mas comunes de entradas analógicas son 0-10v, 4- 20 mA y sondas de temperatura, como: PT100, Pt1000 y termopares.

La principal característica de las entradas es que deben ser lineales (salvo casos especiales que no voy a tratar aquí). Es decir que esta señal aumentará proporcionalmente al valor físico medido.  El cálculo mediante el cual se transforma una entrada analógica en una magnitud física que se llama escalado.

Ejemplo de escalado con sonda de presión 0 – 10 bar y entrada analógica 4-20mA.

Presión AT %I*:INT;

La variable presión tendrá un valor entre -32767 y +32767, las entradas analógicas 4-20 mA siempre devuelven valores positivos  y el resultado es que la variable devolverá un valor entre 0 y 32767. Por lo tanto:

4 mA = 0 bar     => Presión = 0

20 mA = 10 bar => Presión = 32767

En realidad el valor de la presión lo convertiremos multiplicado por 100. De esta manera tendremos dos decimales aunque en programa lo veamos con Bar * 100.

Como podemos ver en el FB para un valor de la entrada de 32767 nos devuelve una presión de 1000 = bar*100 = 10,00 bar.

DifReal = ValorA20 – ValorA4

Factor = DifReal / NºPuntos

Presión = (Puntos * Factor) + ValorA4  + OffSet.

La Resolución de una entrada analógica.

La resolución de una entrada analógica esta determinada por el numero de bit. El módulo encargado de leer una entrada analógica nos devuelve el valor al PLC. En esta conversión, e independientemente del tipo de variable utilizada en el programa para almacenarla, la entrada es convertida a un valor digital con unos bit de resolución que están determinados por el módulo en concreto, es una de las características a la que habremos de prestar atención.

Si contamos con un modulo de 8 bits, tendremos 2^8 valores = 256. Para la lectura de una sonda de presión de 0 a 10 bar tendremos:

1000 / 256 = 3,9

Por lo tanto, por cada punto de variación en la entrada analógica, tendremos 0,04 bar de variación en la variable interna del plc. Para una entrada de 12bits (1000/4096 = 0,24 => 0,0024 bar). Es común, en una entrada analógica, que existan pequeñas variaciones. Dependiendo de la resolución estas variaciones pueden ser mas  o menos molestas, puesto que no es lo mismo estar variando 0,04 bar que 0,0024.  Yo, particularmente utilizo entradas de unos 12 bit de resolución para la mayoría de las aplicaciones.

TEXTO LITERAL EXTRUCTURADO

He pensado que una buena manera de empezar es con unas nociones generales de este lenguaje, puesto que será uno de los idiomas que hablemos aquí. Realmente no es complicado, pese a lo que pueda parecer, en un principio y cuando hablamos de ciertas operaciones con palabras resulta ser la mejor opción.

Hay ciertas diferencias en función de la marca pero los principios son los mismos. En esta primera entrada haré un repaso rápido para ver un poco las posibilidades.  Los ejemplos están realizados con PLC CONTROL de beckhoff. Este software es gratuito y esta basado en CoDeSys. Lo podeis descargar desde aquí. Este software cumple la norma IEC 61131-3 de programación. Para este caso he declarado todas las variables como globales.

VAR_GLOBAL

(* Ejemplos lógica *)
Var1:BOOL;
Var2:BOOL;
OutSerie:BOOL;
OutParalelo:BOOL;
(* Ejemplos marcha paro *)
Pmarcha:BOOL;
Pparo:BOOL;
Motor:BOOL;
(* Ejemplo termostato *)
TempCam1:INT;
SetPoint:INT;
SetPointAlto:INT;
Termostato:BOOL;
(* Ejemplo de media *)
Matriz: ARRAY[0..9] OF INT;
Indice: INT;
i:INT;
Suma:INT;
Valor:INT;
Media:INT;
(* Ejemplo CASE *)
Error := INT;
Resistencia1:BOOL;
Resistencia2:BOOL;
Resistencia3:BOOL;

END_VAR

Red serie:

OutSerie := Var1 AND Var2;

1.1. Ejemplo de red serie en leader

Red paralelo:

OutParalelo := Var1 OR Var2;

1.2. Ejemplo red paralelo en leader

Marcha paro con pulsador:

Motor := Pparo AND (Pmarcha OR Motor);

1.3. Ejemplo de secuencia marcha paro en leader

Comparaciones. Una funcion termostato:

Termostato := TempCam > SetPoint AND (TempCam > SetPoint + 20 OR Termostato);

La misma función con IF THEN ELSE

IF TemCam > SetPoint +20 THEN Termostato := TRUE;

IF TemCam < SetPoint THEN Termostato := FALSE;

1.4. Ejemplo funcion termostato en leader

Media de un valor:

Y aquí empieza a cobrar sentido este lenguaje de programación. Cada ciclo de scan almacenamos el valor actual en una matriz de manera que se mantengan los diez últimos. La media, claro esta, será la suma de todos los elementos de la matriz dividido entre el número de registros.

(* Sumamos 1 al índice para avanzar el registro de la matriz a escribir *)

Indice := Indice +1;

(* es importante poner limites a los índices para evitar un error. Tambien nos sirve para volver al registro 0 de la matriz cundo la recorremos por completo *)

IF Indice < 0 THEN Indice := 0;END_IF;

IF Indice > 9 THEN Indice := 0;END_IF;

(*Asignamos a la matriz el valor actual en el registro actual *)

Matriz[Indice] := Valor;

(* Ponemos a 0 la variable suma para volver a calcular la suma *)

Suma:= 0;

(* Recorremos la matriz para calcular la suma de todos los registros *)

FOR i := 0 TO 9 DO

Suma:= Suma + Matriz[i];

END_FOR;

(* Calculamos la media procurando no dividir nunca el valor 0 *)

IF Suma = 0 THEN Media := 0; ELSE Media:= Suma / 10;END_IF;

Condicional CASE:

(*Ejemplo CASE*)
(* Activar tres resistencias en función de la diferencia entre la temperatura y el setpoint *)

Error := TempCam1 – SetPoint;
IF Error < 0 THEN Error := 0;END_IF;

CASE Error OF
0:  Resistencia1:= FALSE;
Resistencia2:= FALSE;
Resistencia3 :=FALSE;

1..3: Resistencia1:= TRUE;
Resistencia2:= FALSE;
Resistencia3 :=FALSE;

4..6: Resistencia1:= TRUE;
Resistencia2:= TRUE;
Resistencia3 :=FALSE;

ELSE;  Resistencia1:= TRUE;
Resistencia2:= TRUE;
Resistencia3 :=TRUE;
END_CASE;

Aquí podeis descargar  el programa con los ejemplos. Para programar PLC según la norma IEC 61131-3 es importante tener un conocimiento básico de éste.

Un saludo y hasta la próxima. !Ah¡  y espero algún comentario.

Editado 23-Enero.

Aquí dejo una recopilación de manuales.