Archive for the ‘ Function block ’ Category

FB Derivada

Continuando con los FB que componen un FB PID,  hoy toca la derivada.

FUNCTION_BLOCK FT_DERIV

VAR_INPUT
in : REAL;
K : REAL := 1;
run : BOOL := 1;
END_VAR

 

VAR_OUTPUT
out : REAL;
END_VAR


VAR
old: REAL;
tx: DWORD;
last: DWORD;
init: BOOL;
MaxValue : REAL;

END_VAR

(* lee system time *)
tx := T_PLC_US();

(* init para inicializar  *)
IF NOT init THEN
init := TRUE;
last := tx;
old := in;
ELSIF run AND tx – last > 0 THEN
out := (in – old) / DWORD_TO_REAL(tx – last) * 1000000.0 * K;
last := tx;
old := in;
ELSE
out := 0;
END_IF;

Init se utiliza para hacer una configuración inicial del FB. En programación leader, probablemente utilizariamos un flanco ascendente.

 

Realmente, este Fb nos recuerda bastante al Fb Integral, con la diferencia de que ahora no sumamos al valor anterior. En esencia lo que hace es calcular un valor proporcional a la desviación entre dos lecturas consecutivas. Cada ciclo de scan se lee el valor PV (por ejemplo la temperatura actual) y la compara con el valor en el anterior ciclo de scan. Pero esto tiene un gran inconveniente y me explico. Si leemos una temperatura, normalmente tendremos un decimal. A efectos prácticos, esto se traduce en que la temperatura parecerá estable hasta el instante en que aumente una décima y será en ese instante en el que la derivada nos de un valor > 0. En realidad esto no es cierto y sabemos que la temperatura está aumentando porque en el trancurso de un tiempo, varios minutos, sí se puede observar un incremento más o menos paulativo.

 

Como podemos ver en el grafico, la evolución de la temperatura en el tiempo. La temperatura es la Serie1 en ºC x 10 que suele ser la medida en un entrada analógica de 12 bit. Supongamos que el eje x son los sucesivos ciclos de scan. La linea azul muestra la evolución real de la temperatura.

La derivada esta definida como la variación de temperatura (Y1 – Y0) partido la duración del ciclo de scan T.

(Y1 – Y0) / T.

Analizando las derivadas en cada ciclo de scan con un tiempo de ciclo de 200ms.

1º Ciclo de scan. Se guardan los datos pero no se calcula. Momento actual y valor actual. last y old.

2ºCiclo de scan (100 – 100) / 200 = 0.

3ºCiclo de scan (100-100)/200 = 0.

4ºCiclo de scan (100 – 100) / 200 = 0.

5ºCiclo de scan (101 -100) / 200 = 0,005.

6º y sucesivos ciclos de scan (101- 101)/200 = 0.

Como vemos, la derivada, sólo nos devolverá un valor en el momento del cambio. Pero realmente el cambio se produce continuamente, aunque la resolución de la entrada analógica hace que este cambio se realice en escalones. Si nuestra entrada de temperatura tiene algo de ruido, el resultado en la derivada será totalmente erróneo. Por estos motivos la derivada se suele poner  Tv = 0,  para este tipo de procesos.

La derivada devuelve un valor proporcional a la aceleración en PV.

Con el símil de un coche. La aceleración es la derivada de la velocidad = (V- V0)/t.

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.