Archive for enero, 2010

Posibilidades

Esta entrada la quiero dedicar a comentar un poco por donde me moveré en posteriores post. En la anterior entrada vimos un programa que hacía de simulador y control. Tenemos más posibilidades, claro cientos. Pero yo quiero centrarme en dos ideas principales, a saber: control y visualización. Como es obvio el control esta constituido principalmente por un PLC que actuará sobre los equipos. Para este fin yo he elegido PLC Control de Beckhoff por una serie de razones que iremos viendo. Para la parte de visualización, y cuando hablo de esto me refiero a todas las posibilidades, visualización pura, registro en texto plano, registro en bases de datos, servidores web, etc. Como decía, para esto he elegido vb.net, pero como veremos mas adelante esto es solo el principio puesto que esta será la base para saltar a las bases de datos, etc.  Y todo esto con software gratuito.

¿Por qué Beckhoff?.

La respuesta es sencilla, podemos probar cuánto queramos sin gastar un duro. Lo que hagamos luego, es cuestión de cada uno. Pero esta claro que los conceptos y en muchas ocasiones el código será valido para otras marcas. Aunque el PLC, propiamente dicho, esta limitado a 30 dias, podemos volver a instalarlo y volverá a funcionar sin problemas. El hecho de poder tener un PLC corriendo en el PC es una gran ventaja en cuanto que no necesitamos, ni cables ni equipos. Teniendo este PLC corriendo podremos probar tanto los programas de PLC como aplicaciones en VB.net leyendo y escribiendo variables en éste. Por lo tanto, la filosofía a partir de ahora será que el PLC sea control puro y la parte de simulación y visualización será por parte de vb.net. De esta manera tendremos tres aplicaciones a las que iremos añadiendo funcionalidad. PLC, simulador en vb.net y visualización en vb.net.

¿Por qué en tres partes ?.

Bien, una de las cosas que tenemos que tener muy presentes es la posibilidad de reutilizar el código que generamos. Es una buena forma de ahorrar tiempo, aunque tenga sus inconvenientes. De esta manera el código generado en la parte de PLC podrá ser reutilizado , añadiendo los “seguros” que precise para aplicaciones reales. Los UserControl en vb.net, igualmente. Imaginemos por un momento que generamos un UserControl en vb.net encargado de simular una cámara, otro encargado de simular un compresor. Teniendo esto, nos sera fácil y rápido generar un simulador de 3 cámaras y 4 compresores. Así podemos probar nuestras aplicaciones antes de una puesta en marcha real, probar nuebos Fb de una forma algo mas realista o explicar y probar conceptos en este blog. Para todo lo que exponga aquí dejaré el codigo fuente y el compilado. De esta manera, quien no quiera entrar en los entresijos de vb.net, simplemente podrá utilizar el ejecutable.

¿Por dónde empezamos ?.

En las últimas entradas he hecho un avance rápido y ahora toca rebobinar. Así que la respuesta es: desde el principio. La idea es volver a retomar los FB`s PID, y seguir poquito a poco. El tema de TwinCat lo abordaremos un poco por encima,  lo justo para poder poner las aplicaciones en marcha.

Fb PID y simulador

He preparado un simulador con el que poder probar el bloque de función PID y comparar con una función termostato. Ademas he añadido la posibilidad de utilizar el PID mediante una Fb Pwm (Modulación en ancho de pulsos). Esto nos llevará algunos post para explicar como funciona   pero creo que es mejor poder ir haciendo pruebas desde el primer momento. Es importante destacar que muchos de los Fb utilizados en este programa estan extraídos de la libreria libre Oscat. Veamos un vídeo y seguimos con los detalles. 

   

Pantalla de visualización.

El gráfico nos muestra la evolución de la temperatura y lo que he llamado “valor equipo” que sería, en una aplicación real, la potencia suministrada por los equipos de frío y calor. 

  

 

Simulador cámara.

K camara es una constante utilizada para simular el los cambios de temperatura dentro de la cámara. Los valores positivos serán entradas de calor a la cámara, y los negativos cesión de calor por la cámara. Pot equipo se utiliza para simular la potencia del equipo frigorífico o la fuente de calor (resistencias, bomba de calor, etc). Intervalo, mediante este parámetro podemos modificar las condiciones de inercia de la cámara, el valor es en mseg. 

Parametros Pid.

Kp o constante proporcional, TN o tiempo integral y TV o tiempo derivativo. 

Selectores.

Mediante los tres botones podemos activar cualquiera de las posibilidades, Pid directo, termostato o Pid a traves de PWM. Si existen mas de dos botones activados solo se tiene en cuenta el primero en orden de Izq a Drcha. 

Para ponerlo en marcha solo hay que conectar al PLC, poner a RUN. Para que cambia K cámara por ejemplo con 3.0 y activa una de las funciones, PID, termostato o PWM. 

(A) RUN (B) STOP (C) Conectarse a PLC (D) Desconectar de PLC.

 

 Desde aquí podeis descargar el archivo. Y aquí hay teoria del Pid.

Algo más de integrales

En la anterior entrada hicimos un FB para calcular la integral de una matriz de 100 elementos. Dicho de otra forma: la integral de lo que paso en los últimos 50 seg. (la matriz se actualizaba cada 500 mseg.).  En esta entrada voy ha comentar el FB integral que se incluye en la librería OSCAT. Esta libreria podeis descargarla desde aquí. Para ver los FB solo teneis que abrir la librería como library (*.lib).

FUNCTION_BLOCK INTEGRATE
VAR_INPUT
E : BOOL := TRUE;
X : REAL;
K : REAL := 1;
END_VAR
VAR_IN_OUT
Y : REAL;
END_VAR
VAR
X_last : REAL;
init: BOOL;
last: DWORD;
tx: DWORD;
END_VAR
(*read system time *)
tx := T_PLC_MS();
IF NOT init THEN
 init := TRUE;
 X_last := X;
ELSIF E THEN
Y := (X + X_LAST) * 0.5E-3 * DWORD_TO_REAL(tx-last) * K + Y;
X_last := X;
END_IF;
last := tx;
(*
hm  3. nov. 2008 rev 1.0
original version
 
*)

Analizando el FB.


Lo que calcula este FB es la integral de un valor en cada ciclo de scan y lo suma al valor acumulado.  De esta manera Integral = IntegralAnterior + [(Error + ErrorAnterior) * 0.5  * 0.001 * Tiempo trancurrido en ms * Constante proporcional ]
La función T_PLC_MS(), nos devuelve el momento actual en una doble palabra (DWORD) .  El proceso en palabras es el siguiente:

1º Ciclo de SCAN

Leemos el tiempo actual y lo guardamos en Tx.
Como Init = FALSE, guardamos el valor de X en X_Last (Valor del error anterior). Ponemos Init a True para que no vuelva a entrar.
Guardamos tx en last.

2º y posteriores Ciclos de SCAN

Leemos el tiempo actual y lo guardamos en Tx.
Si E = TRUE ( E es la activación del cálculo, como vemos en la declaración de variables esta inicializada a TRUE).
Calcula la integral
Guarda el valor de X en X Last
Guarda tx en Tx-Last.
Aquí os dejo un proyecto con un pequeño programa que simula un cambio en la temperatura y calcula la integral. He añadido la misma función modificada para que sea mas fácil de  entender. En posteriores entradas, me gustaría  mejorar el simulador para que realmente podamos probar una función PID. Por el momento es solo para que se pueda ver la integral en funcionamiento.

User Function block

En esta entrada vamos a realizar un User Function block o bloque de función de usario. Y esto, no es nada más que un poco de codigo, realizado por nosotros, y  encapsulado para poder reutilizarlo. En este caso tambien vamos a utilizar algun Function Block  (en adelante FB)  y Function (en adelante F) de la librería standar de Beckhoff. La diferencia entre éstos es: en el primero el resultado de las salidas, depende de las entradas y del valor de las variables internas. En el segundo caso F, la salida sólo depende del valor de la entrada. Un ejemplo de F es  FDoble = In * 2.

Concretamente vamos a realizar un FB que calcula la integral numérica  por la regla del trapecio. La integral la realizaremos de la función del error (SetPoint – Temperatura). Para saber más sobre integrales numéricas.

La integral definida de una función representa el área limitada por la gráfica de la función, con signo positivo cuando la función toma valores positivos y negativo cuando toma valores negativos.

Fuente : Wikipedia.

Veamos un ejemplo del cálculo:

1.1. Tabla de datos de ejemplo

1.2 Representación grafica de la integral.

El cálculo realizado por el programa de plc:

El programa en cuestión:

FUNCTION_BLOCK Integral

VAR_INPUT
Sp:INT;
Pv:INT;
END_VAR
VAR_OUTPUT

Integral: REAL;
END_VAR
VAR
SpReal:REAL;
PvReal:REAL;
Error: REAL;
Matriz:ARRAY [0..99] OF REAL;
esPulso: TON;
Inicio:INT;
i:INT;
h:INT;
k:INT;

END_VAR

(*FB temporizador TON, en este caso la salida es un pulso cada 500 ms*)
esPulso(IN:= NOT esPulso.Q, PT:= T#500ms);
(*Convertimos las entradas en Var REAL con funciones*)
SpReal:= INT_TO_REAL(Sp)/10;
PvReal:= INT_TO_REAL(Pv)/10;
(* Si hicieramos SpReal := INT_TO_REAL(Sp/10) el resultado seria diferentes puesto que el programa analiza (Sp/10) como un entero *)

Error := PvReal – SpReal;

CASE Inicio OF

0: (*Llenamos la matriz en el primer scan *)
FOR i:=0 TO 99 DO

Matriz[i] := Error;

END_FOR;
Inicio := 1;
1: (* Pasamos los registro en h a h-1, retrasamos la matriz en un registro e introducimos el valor actual en el ultimo registro *)
IF esPulso.Q THEN

FOR h:= 0 TO 98 DO

Matriz[h] := Matriz[h+1];

END_FOR;

Matriz[99]:= Error;
END_IF;

END_CASE;
(* Ponemos a 0 el valor de la integral para volver a calcular *)
Integral := 0;
(* Aqui esta realmente el calculo de la integral a partir de una matriz que contiene los últimos 100 registros *)
FOR k:= 0 TO 98 DO

(* Cálculo integral por la regla del trapecio  Calculamos el valor de cada columna   = (B3-B2)*((C2+C3)/2) y los sumamos*)
Integral:= Integral + (    (  (k+1)  – k)   *  (   (Matriz[k] + Matriz[k + 1]) / 2 )    );

END_FOR;

1.4 Apariencia del FB integrado en el programa.

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.