(FB in SCL) Simulazione Processo Primo Ordine

Creazione di una FB in SCL per la simulazione di un processo del primo ordine.

Può essere utile simulare il processo che dobbiamo controllare per aver modo di testare in fase di progettazione la logica di controllo (che nella maggior parte dei casi per un sistema del primo ordine sarà un controllore PI o PID).
Ovviamente per poter simulare il processo dobbiamo conoscerne il modello matematico oppure la risposta al gradino.

Come sappiamo un sistema del primo ordine è caratterizzato da una costante di tempo, da un tempo di ritardo e da un guadagno. La risposta al gradino per un processo del primo ordine è la seguente (supponendo nullo il tempo di ritardo):

 

Grafico

 

Dopo un tempo pari a 4 – 5 volte la costante di tempo il sistema può considerarsi a regime. Nell’esempio sopra il guadagno del processo è pari ad 1.

La maggior parte dei processi industriali possono essere modellati come dei sistemi del primo ordine, e tra questi possiamo prendere l’esempio più classico del riscaldamento (o raffreddamento) di un fluido all’interno di un serbatoio.

Supponiamo quindi di avere una resistenza che viene usata per riscaldare un liquido all’interno di un serbatoio. Il passaggio della corrente nella resistenza avviene con la chiusura di un relè a stato solido SSR. Questo processo, che noi vogliamo simulare presenta la seguente risposta al gradino (ovvero la risposta del sistema partendo dalla temperatura ambiente, fino alla temperatura a regime, alla chiusura del relè per un tempo molto lungo, cioè superiore ad almeno 5 volte la costante di tempo):

sistema_da_simulare

Da questa risposta possiamo ricavare il tempo di ritardo, la costante di tempo e il guadagno. In questo caso abbiamo:

  • Tempo di ritardo = 0
  • Costante di tempo = 300 sec
  • Guadagno = 100

Quindi la risposta del sistema al gradino può essere scritta come:

y(t) = (Y0)*exp(-t/T) + (G)*(1-exp(-t/T))

dove y(t) rappresenta la temperatura all’istante di tempo t, Y0 rappresenta il valore dell’uscita (e quindi come detto della temperatura) per t=0, G il guadagno e T la costante di tempo.

Mentre invece quando non è applicato alcun ingresso la risposta sarà:

y(t) = (Y0 – Temp_ambiente)*exp(-t/T) + Temp_ambiente

Quindi sostituendo i valori avremmo che la risposta al gradino sarà:

y(t) = (Y0)*exp(-t/300) + 100*(1-exp(-t/300))

invece l’evoluzione libera:

y(t) = (Y0 – Temp_ambiente)*exp(-t/300) + Temp_ambiente

Adesso possiamo simulare il processo direttamente nel dominio del tempo creando la seguente FB  in SCL:

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
FUNCTION_BLOCK "Simulazione_processo"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      ingresso_gradino : Bool;   // corrisponde in questo caso alla chiusura del ssr
      costante_di_tempo : Real;   // costante_di_tempo del processo che stiamo simulando
      guadagno : Real;   // guadagno del processo che stiamo simulando
      temp_ambiente : Real;
   END_VAR
 
   VAR_IN_OUT 
      out_processo : Real;
   END_VAR
 
   VAR 
      valore_iniziale_processo : Real;
      R_Trig_Instance : "R_Trig";
      F_Trig_Instance : "F_Trig";
      timer1 {OriginalPartName := 'TON'; LibVersion := '1.0'} : TON;
      timer2 {OriginalPartName := 'TON'; LibVersion := '1.0'} : TON;
      tempo1 : Real;
      tempo2 : Real;
      tmp_real : Real;
   END_VAR
 
 
BEGIN
	#R_Trig_Instance(input:=#ingresso_gradino);
	#F_Trig_Instance(input:=#ingresso_gradino);
 
	IF #R_Trig_Instance.out OR #F_Trig_Instance.out THEN
	    #valore_iniziale_processo := #out_processo;
	END_IF;
 
	#timer1(IN:=#ingresso_gradino,
	        PT:=T#10h);
	#timer2(IN:=NOT #ingresso_gradino,
	        PT:=T#10h);
 
	//tempo in secondi dopo che attivo il timer1, mi serve per avere
	//una variabile temporale quando applico un ingresso a gradino
	#tempo1 := DINT_TO_REAL(TIME_TO_DINT(#timer1.ET / 1000));
 
	//tempo in secondi dopo che attivo il timer2,mi serve per avere
	//una variabile temporale quando NON applico alcun ingresso
	#tempo2 := DINT_TO_REAL(TIME_TO_DINT(#timer2.ET / 1000));  
 
	//a questo punto posso subito simulare la risposta del sistema di primo ordine
	//con una determinata costante di tempo e un determinato guadagno
 
 
	IF #ingresso_gradino THEN
	    #tmp_real := EXP(#tempo1 / #costante_di_tempo);
	    #out_processo := (#valore_iniziale_processo) * (1 / #tmp_real) + #guadagno * (1 - 1 / #tmp_real);
	ELSE
	    #out_processo := (#valore_iniziale_processo -#temp_ambiente) * (1 / EXP(#tempo2 / #costante_di_tempo)) + #temp_ambiente;
	END_IF;
 
END_FUNCTION_BLOCK

e richiamando un istanza di questa FB in un “Cycle time Interrupt”(**) OB35:

istanza_simu_processo2

**Nota: Bisogna rispettare il teorema del campionamento, e quindi la frequenza di esecuzione del Cycle time Interrupt deve essere almeno doppia alla banda del sistema che stiamo simulando. In questo caso (processo del primo ordine) significa che il periodo del Cycle time Interrupt deve essere minore della metà della costante di tempo del processo. In questo esempio non ci dobbiamo preoccupare in quanto la costante di tempo è molto grande e sicuramente il periodo di esecuzione sarà molto più piccolo della metà della costante di tempo.

You may also like...


Warning: count(): Parameter must be an array or an object that implements Countable in /membri/fabioplc/wp-includes/class-wp-comment-query.php on line 399
Menu Title