Università degli Studi di Catania
Corso di Laurea in Ingegneria dell’Automazione e Controllo dei Sistemi Complessi
Controllo di Processi Sintesi di controllori PID non interi Anno 2009/210
Di Mauro Gianluca Patti Giuseppe Saglimbene Silvana
Prof. Ing. A. Gallo Ing. G. Dongola
Introduzione Il nostro studio è stato incentrato sullo sviluppo di un algoritmo per la sintesi di controllori PID di ordine non intero. Nella fattispecie, le nostre attenzioni si sono dapprima concentrate sul confronto dei tempi di salita, scaturiti da diversi tipi di controllori di ordine non intero. Si è successivamente sviluppato, in funzione di parametri caratteristici quali tempo di salita ed errore al regime, un tool software in Matlab per la sintesi di tali controllori operanti sia su un plant del 1° ordine che su plant rispecchianti sistemi realmente esistenti.
Calcolo Frazionario Accanto all’ormai famoso calcolo differenziale, usato per descrivere attraverso delle equazioni differenziali i più svariati fenomeni naturali, si è sentita l’ esigenza, scaturita, peraltro, dalla sempre più approfondita conoscenza dei fenomeni fisici, di introdurre il cosiddetto calcolo frazionario. Tale calcolo nasce, come accennato poc’anzi, dal fatto che ad un’analisi più approfondita di molti sistemi, come per esempio quelli riguardanti la trasmissione di calore o linee di trasmissione, vengono modellati al meglio da modelli di ordine non più intero ma frazionario. A tale scopo si è quindi sviluppata un’opportuna teoria matematica, che permette di usare così operatori come la derivata e l’integrale (di ordine frazionario ) , indispensabili per l’analisi di tali sistemi. Cenni teorici . La definizione più comune di un integrale d’ordine non intero positivo q è quella introdotta da Riemann-Liouville :
q 1 d q f (t ) 1 t t f ( ) d dt q ( q ) 0
(1.1)
ove Г(.) indica la funzione Gamma di Eulero definita per valori reali positivi della quantità n-α: n
x
n 1
e x dx (1.2)
0
Discretizzando:
d
q
t
f (k ) q
T q ( q 1)
k 1
jo
fi f
j 1
( k
j ) q ( k j 1) q
(1.1.1)
Sfruttando la proprietà che la derivata è la funzione inversa dell’integrale si può ricavare, dalla (1.1), la derivata di ordine non intero q considerando un grado derivativo n (intero) e un grado integrativo α (non intero) tale che n- α sia uguale a q ottenendo così la (1.3):
d
f (t ) d n f (t ) d n d f (t ) 1 dn dt q dt n dt n dt ( ) dt n
q
t
0
(t )
1
f ( ) d
Si deduce dalla (1.3) che la derivata di ordine non intero q è uguale alla derivata di ordine intero n dell’integrale di ordine frazionale α definito dalla (1.1). La relazione (1.3) comunque risulta molto laboriosa da un punto di vista sia analitico che numerico e quindi poco si addice ad uno sviluppo di tipo digitale. Pertanto risulta più utile riportare la definizione di derivata di ordine non intero α nota come relazione di Grunwald-Letnikov:
D KT f ( t )
K
1 j f j
j0
(K j)
(1.4)
Dove possiamo indicare C j ( 1) j j
1 1 j
C j 1
(1.5)
Per lo studio dei sistemi di ordine non intero si impiegano modelli matematici dinamici e, finché l’approssimazione è accettabile, lineari come nel caso classico dei sistemi di ordine intero seguendo degli algoritmi di approssimazione. I più utilizzati sono: approssimazione nel dominio della frequenza; approssimazione nel dominio del tempo; metodo inverso; algoritmo genetico. Approssimazione nel dominio della frequenza
Il metodo più utilizzato è quello di approssimazione nel dominio della frequenza. Per approssimare un sistema di ordine non intero viene utilizzata la somma di tanti sistemi di ordine intero: N 1
H (s)
1 p
s T
1
m
1
s zi
1
s pi
i 0 N
i 0
(1.6)
Un modo per scegliere la coppia di poli e zeri è basato su una sorta di algoritmo “riverse best fit” , giungendo al calcolo del primo polo e del primo zero della funzione H(s) secondo le seguenti relazioni: p z
0
0
p p
0
y
* 10
T
/ 20 m
[ y / 10 ( 1 m )]
* 10
(1.7) ove y si ricorda essere il grado di accuratezza dell’errore (o anche detto gap massimo accettabile in db). Ora non rimane altro che trovare i rimanenti N-1 poli espressi dalle seguenti uguaglianze: p z
i i
z p
i 1
* 10
i
y
* 10
[ y / 10
/ 10
m
( 1 m )]
. p
z
N
N 1
* 10
y
/ 10
m
(1.8)
giungendo a calcolare quanto vale N . Se si imponesse lo scarto tra poli e zeri successivi sempre costante e le quantità numeriche 10[y/10(1-m)] = a e 10[y/10m] = b si otterrebbe: z0 p0
z1 p1
.........
z n 1 p n 1
a
p1 z0
p2 z1
.........
pn z n 1
b
(1.9)
Così facendo, i poli e zeri delle espressioni (1.8), insieme a p0 e z0, possono essere riscritti secondo la (1.9):
p z
i
( ab
i
i
)
( ab
)
i
p
0
ap
0
(1.10)
Considerando infine la banda massima ( ab )
N 1
( ab )
N 1
p0
( N 1 ) log( ( N 1) N INT
( ab )
0
max
log( log( log(
p
)
0
p
0
ab )
segue che:
p0
max
p
0
) N log(
ab )
N
ab ) max
N
N
ab ) log(
log(
( ab )
max
max
p
)
1
(1.11) dove INT sta ad indicare la parte intera del blocco dentro la parentesi quadra.
Figura 1.1 Risposta in frequenza di F(s) = 1/ (s+1)0.3 comparata con la sua approssimazione per tre differenti valori di y
Si può notare infine in Figura 1.1 che, mantenendo costante ωmax = 106, il numero di poli e il numero di zeri si incrementa al decrescere di y.
2 – PID di ordine non intero I regolatori PIλDµ di ordine non intero rappresentano un caso più generale dei regolatori PID interi, essi garantiscono la funzionalità data dai classici controllori/regolatori di ordine intero, tuttavia aggiungono importanti vantaggi sia per quanto riguarda la sintonizzazione che il raggiungimento dei requisiti di controllo. Nei PIλDµ, esattamente come nei controllori di ordine intero, la variabile di controllo u(t) viene generata dalla somma di tre contributi: azione proporzionale, azione integrale e azione derivativa. I coefficienti reali λ e µ stanno ad indicare rispettivamente il grado dell’azione integrale e il grado dell’azione derivativa.
Figura 2: Schema a blocchi di un regolatore PIλDµ con λ=µ=1
L’equazione d’uscita di un controllore PIλ Dµ nel dominio del tempo è:
u (t ) K p [ e (t )
1 D e(t ) TD D e(t )] TI
2.1
in cui TI è detto tempo integrale mentre TD è detto tempo derivativo. Considerando i rapporti
e
, la (2.1) può essere riscritta nella
forma:
u (t ) K p e(t ) K I D e(t ) K D D e(t )
(2.2)
Scegliendo λ=1 e µ=1 si ottiene il classico controllore PID ; con λ=1 e µ=0 si ottiene un controllore PI ; con λ=0 e µ=1 si ottiene un controllore PD mentre con λ=0 e µ=0 si ottiene semplicemente un guadagno.
Il PSO La tecnica del Particle Swarm Optimization (PSO) è stata originariamente sviluppata nel 1995 da uno psico - sociologo di nome James Kennedy e da un ingegnere elettrico Russel Eberart. Tale algoritmo rientra nella categoria degli algoritmi evoluzionistici basati su popolazioni di individui, ma diversamente degli algoritmi genetici, la popolazione viene aggiornata senza l’utilizzo degli operatori genetici quali il crossover e la mutazione. Ciò accade perché il PSO nasce dall’ analisi dei meccanismi di interazione tra gli individui che fanno parte di un branco e che devono raggiungere un obbiettivo comune come la ricerca del cibo o la semplice convivenza.
Un esempio in tal senso può essere ricercato nello studio delle regole del volo di uno stormo, da cui si evince come un individuo leghi il suo comportamento a quello degli altri membri del gruppo. Infatti ,un individuo che nel suo movimento scorge una fonte di cibo si trova di fronte a due alternative: o allontanarsi dal gruppo per raggiungerlo (individualismo) o rimanere nel gruppo (socialità). Nel caso in cui più individui si dirigono verso il cibo, anche altri membri possono cambiare la loro direzione per sfruttare la stessa fonte di nutrimento e il gruppo, così, cambia gradualmente direzione verso le zone più promettenti, ovvero l’informazione gradualmente si propaga a tutti. Da qui l’analogia con il problema di ottimizzazione , che può essere definito come: individui: configurazioni di tentativo che si spostano e campionano la funzione obiettivo in uno spazio reale a N dimensioni (applicazione floating point); interazione sociale: un individuo trae vantaggio dalle ricerche degli altri dirigendosi verso la regione del punto migliore globalmente trovato.
Mentre la strategia di ricerca può essere espressa come bilanciamento tra exploration ed exploitation: exploration: legato all’individualità del singolo che ricerca la soluzione; exploitation: legato alla socialità ,ovvero allo sfruttamento dei successi di altri individui.
Una caratteristica che risulta essere importante nella ricerca e’ legata al concetto di vicinanza. Gli individui sono influenzati dalle azioni degli individui ad essi più vicini (sottogruppi) e quindi la circolazione dell’informazione e’ globalmente garantita. I sotto-gruppi non sono legati alla vicinanza fisica delle configurazioni nello spazio dei parametri, ma sono definiti a priori e possono tenere in conto di spostamenti anche notevoli tra gli individui.
Pensando ora ad un’applicazione si intuisce, da quanto detto poc’anzi, che il PSO è adatto a risolvere con relativa facilità implementativa ed efficienza,
problemi
multidimensionali non lineari e non differenziabili come appunto quelli riguardanti la sintesi di controllori FOPID; in quanto da come si può evincere dalla figura sottostante
Tale algoritmo, prendendo in ingresso l’errore, riesce a decretare i parametri necessari per il funzionamento del suddetto controllore.
PSO IN DETTAGLIO
Il PSO consiste in uno sciame di particelle che si muovono in uno spazio a D dimensioni in cui deve essere ottimizzata la funzione di interesse. Ogni particella ha sia
una posizione che una velocità e queste ultime vengono rispettivamente
rappresentate dal vettore posizione Xi=(xi1,xi2,…,xiD) e da quello della velocità Vi=(vi1,vi2,…,viD),
(limitato
da
un
vettore
di
velocità
massima
)
Vmax=(vmax1,vmax2,…,vmaxD)). Ogni particella ricorda la propria posizione migliore grazie all’utilizzo di un vettore Pi=(pi1,pi2,…,piD) (dove i indica l’indice della particella), mentre il vettore dove vengono conservate le migliori posizioni tra tutte quelle vicine è rappresentato da Pg=(pg1,pg2,…,pgD).
(9) (10)
Dove w rappresenta un’inerzia il cui simulazione da
valore decresce linearmente durante una
un wmax (0.9) a un wmin (0.4) ; per settare tale parametro
generalmente si usa la seguente equazione: (11)
Dove itermax generazione).
rappresenta il max num di iterazioni e iter quello corrente (o
Un elevato valore di w facilita l’esplorazione globale (cercando in nuove aree), mentre un valore più basso facilita l’esplorazione locale, permettendo una ricerca migliore nell’area locale. Per quanto riguarda i parametri c1 e c2, chiamati apprendimento cognitivo, sono le costanti di accelerazione che influenzano la velocità di convergenza di ogni particella (e spesso sono settati a 2 in accordo con esperimenti già condotti).? Per finire r1 e r2 sono ,invece ,dei numeri casuali generati nell’intervallo [0,1]. OSS Nel caso di problemi D-dimensionali, poiché lo spazio delle soluzioni avrà D dimensioni, ogni particella dovrà avere un vettore di posizione e velocità di D dimensioni. Se Vmax è troppo piccolo le particelle potrebbero non esplorare lo spazio ,quindi si suggerisce di settare Vmax dimensione ,cioè vdmax=xdmax
con lo stesso range
delle variabili per ogni
IMPLEMENTAZIONE
Per l’implementazione del PSO Sia
la fitness multidimensionale che vogliamo ottimizzare. Sia n il
numero di particelle , ad ognuna delle quali vengono associati i vettori posizione , e velocità
,
corrente di ogni particella e
Si inizializzano
. Sia inoltre
la migliore posizione
la migliore posizione globale.
e
per tutte le particelle (i). Una scelta comune è quella
di prendere
e
, dove aj,bj
per tutte le i e
sono i limiti del dominio di ricerca in ogni dimensione, e U rappresenta una distribuzione uniforme.
e
.
Prima della convergenza: o
Per ogni particella
Creiamo un vettore random j,considerando
: ,
:
e
f per tutti i
per
si aggiornano le velocità delle particelle: .
Si aggiornano le posizioni delle particelle :
.
Si aggiornano le migliori posizioni locali : se
,
.
Si aggiorna la migliore posizione globale: se
,
.
è la soluzione ottima con fitness
.
Riassumendo quindi passi principali sono: 1) inizializzare una popolazione di particelle (posizione e velocità) 2) aggiornare le velocità 3) aggiornare le posizioni.
Tutto ciò in pseudo codice diventa
# Initialize the particle positions and their velocities X = lower_limit + (upper_limit - lower_limit) * rand(n_particles, n_dimensions) assert X.shape == (n_particles, n_dimensions) V = zeros(X.shape) # Initialize the global and local fitness to the worst possible fitness_gbest = inf fitness_lbest = fitness_gbest * ones(n_particles) # Loop until convergence, in this example a finite number of iterations chosen for k in range(0, n_iterations): # evaluate the fitness of each particle fitness_X = evaluate_fitness(X) # Update the local bests and their fitness for I in range(0, n_particles): if fitness_X[I] < fitness_lbest[I]: fitness_lbest[I] = fitness_X[I] for J in range(0, n_dimensions): X_lbest[I][J] = X[I][J] # Update the global best and its fitness min_fitness_index = argmin(fitness_X) min_fitness = fitness_X[min_fitness_index] if min_fitness < fitness_gbest: fitness_gbest = min_fitness X_gbest = X[min_fitness_index,:] # Update the particle velocity and position for I in range(0, n_particles): for J in range(0, n_dimensions): R1 = uniform_random_number() R2 = uniform_random_number() V[I][J] = (w*V[I][J] + C1*R1*(X_lbest[I][J] - X[I][J]) + C2*R2*(X_gbest[J] - X[I][J])) X[I][J] = X[I][J] + V[I][J]
Tools Software I tools software da noi sviluppati, come accennato pocanzi, consentono la sintesi di controllori PID di ordine frazionario. Il primo, permette un confronto sul tempo di salita sia a livello grafico che numerico, tra un PID classico, cioè di ordine intero, e una serie di FOPID (fractional order PID). Il secondo, invece, sfruttando l’algoritmo evoluzionistico introdotto precedentemente, calcola a partire da un plant del primo ordine e dal tempo di salita desiderato i parametri caratteristici del nostro FOPID, come le costanti KP,KI e KD e i coefficienti di integrazione e derivazione. Mentre il terzo, che non è altro che una rielaborazione del secondo, si occupa della sintesi di un PID su un plant modellanti un sistema reale.
Confronto tempi di salita dei PID Come si può notare dalla figura sottostante al fine di determinare il confronto tra i suddetti PID bisogna impostare diversi parametri quali: il plant, che in questo studio è del primo ordine, il range di variazione dei PID non interi e i parametri caratteristici come Kp tempo di campionamento, di assestamento e di salita.
I risultati, come mostrato in fig. ,sono sia in forma numerica ,e in questo caso mostrano i diversi tempi di salita per ogni variazione dell’ordine del controllore, che in forma grafica, dove le diverse risposte sono sovrapposte per mettere in risalto la differenza tra il PID intero (verde) e quello non intero (blu). Analisi del codice Analizzando il codice, è possibile rintracciare il fulcro di tutto nel modello simulink , che permette di calcolare entrambe le tipologie di PID.
Infatti da quest’ultimo si estrae di volta in volta ,sia il tempo di salita, che la risposta al gradino del FOPID, che verrà poi rappresentata graficamente. dim=size(PIDout); dim=dim(1); for i=1:dim valore=PIDout(i,1); if(valore>0.9) break end end %-----------------------%Calcolo del valore a 0.1 (PI_ni) valoreni_min=valore for psi=1:dim valore_min=PIDout(psi,1); if(valore>0.1) break end end
Sintesi del FOPID Osservando l’interfaccia relativa a questo secondo tool, si nota la presenza di due aree ben distinte. Nella prima, racchiusa all’interno della sezione “Parametri del PSO” è possibile settare i parametri dell’algoritmo di ottimizzazione quali: numero di particelle, iterazioni massime consentite, C1 e C2 . Mentre nella seconda “Parametri FOPID” ,si setta il tempo di salita desiderato.
Alla convergenza del software i risultati ottenuti sono i guadagni Kp, Ki e Kd ordine di integrazione e di derivazione.
Analisi del codice Prima di analizzare in dettaglio i risultati ottenuti è bene introdurre il modo di operare del codice, presente in questa sezione e le scelte da noi prese per effettuare questo studio. Infatti ,poiché per il tuning di un PID di ordine frazionario si è scelto di ricorrere all’algoritmo di ottimizzazione chiamato PSO, è stato necessario implementare sia una funzione obbiettivo da ottimizzare , sia un criterio di stop che ci permettesse di ottenere i risultati voluti.
Funzione obbiettivo La funzione obbiettivo, chiamata FOPI, si occupa di ricalcolare, ogni qualvolta l’algoritmo PSO lo richieda, dapprima i parametri del FOPID attraverso il blocco simulink mostrato in fig.
e successivamente il funzionale da minimizzare per ottenere la fitness, attraverso il codice TT=(ts_PI_ni-Tsdes)^2; alpha=10;beta=10; out=e*beta+TT*alpha;
Il pso Per quanto riguarda l’algoritmo, le nostre modifiche rispetto alla versione originale, sono state incentrate in primis sull’incremento del numero di dimensioni del problema da trattare dim = 5; … …
% Dimension of the problem
R1 = rand(dim, n); % valori random di inizializzazione R2 = rand(dim, n);
… … current_position = 10*(rand(dim, n)-.5); %posizione inz random velocity = .3*randn(dim, n); %velocità iniz random
… velocity = w *velocity + c1*(R1.*(local_best_positioncurrent_position)) + c2*(R2.*(globl_best_positioncurrent_position));% velo per ogni particella …
e successivamente sulla definizione di un criterio che ci permettesse di fermare il tutto a convergenza avvenuta. while
… ….
( (oout>= 0.2 )&&(iter<bird_setp))
x=fitness(:,1); [Y,I] = min(xx); CC=current_position(:,I) ; tss = FOPI_test2(abs(CC(1)),abs(CC(2)),abs(CC((3))),coeff1,coeff2,b,k) % controllo del tempo di salita attuale Kp, ki, kd, deriv_ni , interg_ni ,b,k oout=abs(Tsdes-tss) end
Sintesi DEL FOPID su un sistema reale Quest’ultimo tool che si occupa di effettuare la sintesi di un FOPID per un sistema realmente esistente non è altro che una rivisitazione del precedente e pertanto gli unici cambiamenti che si hanno sono concentrati nel codice. Prima di descriverne il funzionamento è opportuno però introdurre il sistema che si intende controllare. Modello Il plant che verrà controllato è rappresentato da un attuatore creato tramite un cantilever IPMC (Ionic Polymer Metal Composities).
Tale sistema può essere modellato da due diversi tipi di plant: uno frazionario
o uno del 6° ordine: Saranno quindi questi i due plant che verranno usati per la sintesi. Analisi del codice Le modifiche principali sono state effettuate sullo schema Simulink ottenendo per il plant di ordine frazionario:
E per il plant del 6° ordine
Successivamente, si è agito sul funzionale che ora implementa l’ITAE
e =alpha* sum(T*abs(e1)*time);%ITAE %calcolo del funzionale da ottimizzare
Risultati Confronto PID /FOPID Le immagini sottostanti si riferiscono al confronto del tempo di salita tra un PI intero e uno non intero, con il coefficiente di integrazione che varia tra 0.2 e 2.5 e plant 1/1+2s
Per quanto riguarda i valori numerici e l’andamento che questi ultimi assumono
Lamba 0,3 0,4 0,5 0,6 0,7 0,8 0,9 1 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9 2 2,1 2,2 2,3
1/(2s+1) Kp=10 Ts PI ni TS PI 0,29 0.41 0,31 0,41 0,33 0,41 0,34 0,41 0,36 0,41 0,38 0,41 0,39 0,41 0,41 0,41 0,43 0,41 0,44 0,41 0,46 0,41 0,48 0,41 0,49 0,41 0,51 0,41 0,53 0,41 0,55 0,41 0,56 0,41 0,58 0,41 0,59 0,41 0,61 0,41 0,63 0,41
0,7 0,6 0,5 0,4 0,3
Serie1
0,2 0,1 0 1 3 5 7 9 11 13 15 17 19 21 23
2,4 2,5
0,64 0,66
0,41 0,41
Considerando ora altri casi si ottengono i seguenti risultati:
Lamba 0,3 0,4 0,5 0,6 0,7 0,8 0,9 1 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9 2 2,1 2,2 2,3 2,4 2,5
1/(s+5) Kp=10 Ts PI ni TS PI 0,24 0.46 0,26 0,46 0,28 0,46 0,3 0,46 0,33 0,46 0,36 0,46 0,4 0,46 0,45 0,46 0,49 0,46 0,53 0,46 0,58 0,46 0,62 0,46 0,66 0,46 0,71 0,46 0,75 0,46 0,79 0,46 0,84 0,46 0,88 0,46 0,92 0,46 0,96 0,46 1,01 0,46 1,05 0,46 1,09 0,46
Lamba 0,3 0,4 0,5 0,6 0,7 0,8 0,9 1 1,1 1,2 1,3
1/(s+3) Kp=10 Ts PI ni TS PI 0,23 0.36 0,24 0,36 0,26 0,36 0,27 0,36 0,29 0,36 0,31 0,36 0,33 0,36 0,35 0,36 0,38 0,36 0,41 0,36 0,44 0,36
1 0,9 0,8 0,7 0,6 0,5 0,4 0,3 0,2 0,1 0
Serie1
1
3
5
7
9 11 13 15 17 19 21 23
1,2 1 0,8 0,6 Serie1 0,4 0,2 0 1 3 5 7 9 11 13 15 17 19 21 23
1,4 1,5 1,6 1,7 1,8 1,9 2 2,1 2,2 2,3 2,4 2,5
0,47 0,51 0,55 0,59 0,63 0,68 0,72 0,76 0,81 0,85 0,89 0,93
0,36 0,36 0,36 0,36 0,36 0,36 0,36 0,36 0,36 0,36 0,36 0,36
Valori ottenuti con il FOPID su un plant del 1° ordine I risultati ottenuti da questa sezione, considerando 100 particelle C1 = C2 =1.2 sono presentati dalla seguente tabella 1/(s+2) Coeff1(Derivatore) Coeff2(Integratore) Ts Desiderato Ts Ottenuto Kp Ki Kd
1/(s+2)
0,5 0,5 1,50 1,3 2,3755 12,32 3,27
1/(s+2)
0,7 0,5 1,5 1,4 5,26 12,69 2,7
1/(s+2)
0,5 0,7 1,5 1,3 6,53 12,65 2,85
1/(s+5)
0,7 0,7 1,5 1,4 3,67 5,35 0,48
0,5 0,5 1,5 1,5 14,97 31,85 6,87
1/(s+5)
Coeff1(Derivatore) Coeff2(Integratore) Ts Desiderato Ts Ottenuto Kp Ki Kd
0,5 0,7 1,5 1,3 21,99 30,85 4,24
1/(s+5) 0,7 0,5 1,5 1,4 11,34 30,98 2,82
1/(s+5) 0,7 0,7 1,5 1,3 25,08 23,02 1,31
1/(s+5) 0,7 1,1 1,5 1,5 6,03 13,63 0,425
1/(s+5) 0,7 1,2 1,5 1,4 1,32 10,39 0,44
Risutati ottenuti applicando il FOPID all’attuatore IPMC Prima di analizzare i risultati ottenuti è bene fare alcune precisazioni. Infatti analizzando il plant del 6° ordine si è visto che presenta dei poli instabili
Ciò significa che per poter provare a controllarlo bisogna portare quei poli nel semipiano sinistro. Si è pensato allora, avendo effettuato delle analisi perlopiù qualitative, che un PID con un’azione derivativa al cubo possa migliorare la situazione
Ragion per cui le nostre analisi, nel caso del plant di 6° ordine si sono limitate ad impostare il valore dell’integratore uguale ad uno e far variare quello del derivatore tra uno e tre
Da come si evince osservando i risultati ottenuti non è stato possibile controllare questo sistema Plant frazionario Mentre per il plant di ordine frazionario osservando il luogo delle radici
Si è scelto come range di variazione quello tradizionale ottenendo:
Da come si può notare solo per i valori di integrazione e derivazione di 0.5 si è avuta la convergenza
Appendice Prima sezione File PI_ni.m function pushbutton1_Callback(hObject, eventdata, handles) global Tr Ts x0 global coeff1 coeff2 T cc y1 H Kp Kd Ki ts_PI_ni_strr=zeros(2,1); ts_PI_strr=zeros(2,1); tt=1; k=str2num(get(handles.edit1,'string')); b=str2num(get(handles.edit2,'string')); T=str2num(get(handles.edit3,'string')); coeff2=str2num(get(handles.edit4,'string')); % coefficiente di integrazione iniziale Kp=str2num(get(handles.edit5,'string')); Ts=str2num(get(handles.edit6,'string')); Tr=str2num(get(handles.edit7,'string')); time=str2num(get(handles.edit8,'string')); coeff2_final=str2num(get(handles.edit9,'string')); % coefficiente di integrazione finale ax= axes('position',[.45 .3 .5 .4]) s=('C:\PID_NI\val.txt'); filem=fopen(s,'w'); nuovo_indice=1; for ind=coeff2:0.1:coeff2_final set(handles.text12,'string',ind) coeff2=ind x0=[1,1]; optionss=optimset('Display','iter'); % Option to display output [x,fval] = fsolve(@myfun,x0,optionss) % Call optimizer zet=real(x(2)) omega=real(x(1)) if((zet>0) && (zet<=1)) Kd=(Kp+k-2*b*zet*omega)/(2*zet*omega); Ki=(Kd+b)*omega^2; options = simset('SrcWorkspace','current');
sim('feedback_mar',time,options) % manda in simulazione il blocco simulik cosi prima inizializziamo e poi simuliamo else disp (st) end if ((PIDout((Ts/T)+50)<1.1) && (PIDout((Ts/T)+50)>0.9) && (PIDout((tout(1000))*1/T)>0.9) && (PIDout((tout(1000))*1/T)<1.1)) set(handles.text11,'string','SODDISFA LE SPECIFICHE'); else set(handles.text11,'string','NON SODDISFA LE SPECIFICHE'); end dim=size(PIDout); dim=dim(1); for i=1:dim valore=PIDout(i,1); if(valore>0.9) break end end valoreni_min=valore for psi=1:dim valore_min=PIDout(psi,1); if(valore>0.1) break end end indice_min=psi; valoreni=valore; ts_PI_ni=(i-psi)*T ts_PI_ni_vett(nuovo_indice)=ts_PI_ni; nuovo_indice=1+nuovo_indice; valore_ni=0; for i=1:dim valore=PIDout(i,3); if(valore>0.9) break end end %-----valoreni_min=valore for eta=1:dim valore_min=PIDout(eta,3); if(valore>0.1) break end end indice_minpi=eta;
%------valore_i=valore; ts_PI=(i-indice_minpi)*T indice=num2str(ind); fprintf(filem,indice); fprintf(filem,' ts_PI_ni=') ts_PI_ni_str=num2str(ts_PI_ni); ts_PI_ni_strr(tt)=ts_PI_ni; indd(tt)=ind; fprintf(filem,ts_PI_ni_str) fprintf(filem,' ts_PI='); ts_PI_str=num2str(ts_PI); ts_PI_strr(tt)=ts_PI; fprintf(filem,ts_PI_str); fprintf(filem,'\n'); hold off x=1:1:4004; %newFig=figure plot(x,PIDout(:,1),'b') hold on plot(x,PIDout(:,2),'r') plot(x,PIDout(:,3),'g') carat=num2str(ind); c=('immagine'); d=('.jpg'); nomeim=strcat(c,carat,d);
newFig =figure; axesObject2 = copyobj(ax,newFig); set(axesObject2,'Position',[.1 .1 .8 .8]);
set(newFig,'Position',[15 10 30 10]); saveas(gcf,nomeim); close(newFig)
tt=tt+1; end hold off coeff3=coeff2:0.1:1.2; nomeim1=('andamento.jpg');
set(handles.text16,'string',ts_PI_ni_strr); set(handles.text17,'string',ts_PI_strr); set(handles.text18,'string',indd); plot(indd,ts_PI_ni_strr,'r') %procedura di salvataggio del grafico che compare nella GUI newFig =figure; axesObject2 = copyobj(ax,newFig); set(axesObject2,'Position',[.1 .1 .8 .8]); set(newFig,'Position',[15 10 30 10]); saveas(gcf,nomeim1); close(newFig)
simulink
Seconda parte File PI_niott.m function pushbutton1_Callback(hObject, eventdata, handles) % hObject handle to pushbutton1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) %clear clc global k b coeff2 Tsdes coeff1 T coeff2=str2num(get(handles.edit2,'string')); % coefficiente di integrazione Tsdes=str2num(get(handles.edit1,'string')); % tempo si salita desiderato k=str2num(get(handles.edit4,'string')); b=str2num(get(handles.edit5,'string')); n=str2num(get(handles.edit3,'string')); %numero di particelle bird_setp=str2num(get(handles.edit6,'string')); % massimo numero di iterazioni c1=str2num(get(handles.edit8,'string')); % parametri del PSO c2=str2num(get(handles.edit7,'string')); coeff1=str2num(get(handles.edit10,'string')); % coefficiente di derivazione %% inizializzazione dell'algoritmo T=0.1; oout=0.3; dim = 3; % Dimensione del problema da ottimizzare w =0.9; % inerzia fitness=0*ones(n,bird_setp); % inizializzazione dei parametri R1 = rand(dim, n); %creo dei vettori di numeri random dimesione uguale a quella del problema R2 = rand(dim, n);
current_fitness =0*ones(n,1); %ogni particella assegno una fitness che inizialmente sara uguale a zero %Inizializzazione di posizione e velocità delle particelle
current_position = 10*(rand(dim, n)-.5); %per ogni particella inizializzo in manienra random le posizioni velocity = .3*randn(dim, n); % stessa cosa per la velocitĂ local_best_position = current_position; % rinomino la posizione iniziale come la posizione locale mgliore
for i = 1:n % per ogni particella calcolo la fitness la current fitness e inserendola nel vettore current_fitness(i) = FOPI(current_position(:,i)) ; current_position(:,i); end
trovando
local_best_fitness = current_fitness; % copio tutto nel vettore local best... [global_best_fitness,g] = min(local_best_fitness); % trovo il minimo e la sua posizione global_best_fitness; for i=1:n globl_best_position(:,i) = local_best_position(:,g); %trovo la posizione della particella che mi ha fornito il min e la inserisco in glob.. end velocity = w *velocity + c1*(R1.*(local_best_positioncurrent_position)) + c2*(R2.*(globl_best_positioncurrent_position));% do una vel per ogni part %aggiornamento della posizione con la velocitĂ current_position = current_position + velocity ;
%% Main Loop iter = 0 ; % contatore per le iterazioni while ( (oout>= 0.2 )&&(iter<bird_setp))% il ciclo si ferma o se la differenza con il tempo di salita desiderato è di %0.2 oppure dopo 50 iterazioni iter = iter + 1 iiter=num2str(iter); for i = 1:n current_fitness(i) = FOPI(current_position(:,i)) ; % ricalcolo della fitness per ogni particella dalla funz da ottim end
for i = 1 : n %controllo se la local_best_fitness ĂŠ > della current fitness, in tal caso ne prende il posto
if current_fitness(i) < local_best_fitness(i) local_best_fitness(i) = current_fitness(i); local_best_position(:,i) = current_position(:,i) end
;
end
[current_global_best_fitness,g] = min(local_best_fitness);
if current_global_best_fitness < global_best_fitness global_best_fitness = current_global_best_fitness; for i=1:n globl_best_position(:,i) = local_best_position(:,g); end end % calcolo della velocitĂ e posizione velocity = w *velocity + c1*(R1.*(local_best_positioncurrent_position)) + c2*(R2.*(globl_best_positioncurrent_position)); current_position = current_position + velocity;
%calolo del criterio xx=fitness(:,1); [Y,I] = min(xx); CC=current_position(:,I) ; % calcolo del tempo di salita attuale tss = FOPI_test2(abs(CC(1)),abs(CC(2)),abs(CC((3))),coeff1,coeff2,b,k) % kp,ki,kd,deriv_ni,interg_ni,b,k oout=abs(Tsdes-tss) end
kkp=num2str(abs(CC(1))) kki=num2str(abs(CC(2))) kkd=num2str(abs(CC(3))) beep ts=num2str(tss); set(handles.text8,'string',iiter); set(handles.text13,'string',ts); set(handles.text5,'string',kkp); set(handles.text6,'string',kki); set(handles.text20,'string',kkd);
Â
File FOPI.m function [out] = FOPI(pid) Kp = pid(1); Ki = pid(2); Kd=pid(3); global T coeff2 k b Tsdes coeff1 b; k; Tsdes; T=0.1; coeff1; coeff2;
% richiamo del modello simulink dove è implementato il FOPID time=40; options = simset('SrcWorkspace','current'); %options = simset('solver','ode5','SrcWorkspace','Current','DstWorkspace','Cu rrent','AbsTol',1e-100); sim('feedback_martest',time,options); % manda in simulazione il blocco simulik cosi prima inizializziamo e poi simuliamo % calcolo del Tempo di salita dim=size(PIDout); dim1=size(PIDout); dim=dim(1);
for i=1:dim valore=PIDout(i,1); if(valore>0.9) break end end for psi=1:dim valore_min=PIDout(psi,1); if(valore>0.1) break end end %tempo di salita ts_PI_ni=(i-psi)*T; %calcolo del funzionale da ottimizzare TT=(ts_PI_ni-Tsdes)^2; alpha=10;beta=10; out=e*beta+TT*alpha;
modello simulink feedback_martest
File FOPI_test2.m function [ts_PI_ni] = FOPI_test2(Kp,Ki,Kd,coeff1,coeff2,b,k)
T=0.1; coeff2; coeff1; Kd; Kp; Ki;
%calcolo del tempo di salita attraverso il simulink time=40; options = simset('SrcWorkspace','current'); sim('feedback_martest2',time,options) % manda in simulazione il blocco simulik cosi prima inizializziamo e poi simuliamo
nuovo_indice=1; dim=size(PIDout); dim=dim(1); for i=1:dim valore=PIDout(i,1); if(valore>0.9) break end end %-----------------------%Calcolo del valore a 0.1 (PI_ni) valoreni_min=valore; for psi=1:dim valore_min=PIDout(psi,1); if(valore>0.1) break end end indice_min=psi; %-----------------------%Calcolo del valore a 0.9 valoreni=valore; ts_PI_ni=(i-psi)*T; ts_PI_ni_vett(nuovo_indice)=ts_PI_ni; nuovo_indice=1+nuovo_indice; valore_ni=0; for i=1:dim valore=PIDout(i,2); if(valore>0.9) break end end %plotting della risposta x=1:1:dim; plot(x,PIDout(:,1),'g')
modello simulink feedback_martest2
File myfun.m function F = myfun(x) global Ts Tr F = [x(1)*(sqrt(1-x(2)^2))*Tr-pi+atan((sqrt(1-x(2)^2)/x(2))); (Ts*x(2)*x(1)-4)]; end
File Calc_I_G.m function Int = Calc_I(f) global coeff2 T H; coeff2; T; H; sigma = coeff2; h =round(f(1)/T); %il fix permette di prendere la parte intera del singolo campione f %visto che un ingresso è la rampa avrò k=1, k=2 ...... k=n. In questo modo %capisco quale campione è entrato: si ricordi che questa funzione è richiamata %ogni qual volta si riceve una coppia di valori. H(h+1)=h; global x % questa definizione permette di salvare il contenuto di y in % memoria perchè ad ogni chiamata della funzione sono necessari i valori % precedentemente salvati. %adesso salvo la prima coppia di valori x(1) = 0; x(h+1) = f(2); % il campione relativo al segnale c = 0; for j=0:h-1;
a = x(j+1)+x(j+2); b = (h-j)^sigma - (h-j-1)^sigma; c = c + 0.5*a*b; end Int = (((T)^sigma)/gamma(sigma+1))*c;
File Calc_D_Petras_G.m function Der = Calc_D_Petras_G(h) % la funzione richiede in ingresso il vettore h % h rappresenta il segnale di ingresso da derivare % % definizione parametri globali : % % - coeff = ordine della derivata (non intero) % - T = intervallo di campionamento % - cc = vettore degli ingressi % - y1 = vettore delle uscite global coeff1 T cc y1; T; cc; y1; coeff1; lambda = coeff1; % k= arrotondamento di h(1)/T , dove h(1) è il primo valore del vettore di % ingresso che passiamo alla funzione (rampa) % k numero di campioni k = round(h(1)/T); % s = minimo tra k e 1/T s=min(k,(T^-1)); % il primo valore dell'uscita è posto pari a zero y1(1) =0; % il valore k+1 dell'uscita è posto pari ad h(2) % è uguale ad h(2) y1(k+1) = h(2); % inizializzazione di c a zero c = 0; % primo valore degli ingressi è posto pari a 1 cc(1)=1; % il valore k+1 degli ingressi è pari a cc(j+1)=cc(j)*( cc(k+1)=cc(k)*(1-(1+lambda)/(k));
for j=0:k; c=c+cc(j+1)*y1(k-j+1); end % for j=1:k; % % cc(j+1)=cc(j)*(1-(1+lambda)/(j)); % c=c+cc(j+1)*y1(k-j+1); % end Der=(T^(-lambda))*c;