PID digitale (parte 3)

Lo studio del regolatore PID oramai è giunto alla terza. Eravamo rimasti nell’ultima puntata con uno pseudocodice di un regolatore PID partito da una discretizzazione semplice che non teneva conto di molti vincoli, (regolatore PID parte 2).Il primo modello di approssimazione si basa su una trasformazione rettangolare o metodo delle differenze all’indietro o di Eulero.

Quello che analizzeremo oggi è il metodo più usato basato su una trasformazione bilineare o metodo d’ integrazione trapezoidale (di Tustin).

Il regolatore PID in funzione del tempo [tex] C(t) = K_p cdot e(t) + K_d cdot frac{de(t)}{dt} + K_i cdot int_0^t e(tau)dtau[/tex]

e la sua forma approssimata con il metodo di Eulero: [tex] C(k) = K_p cdot e(k) + frac{K_d}{T_c} cdot (e(k)-e(k-1)) + K_i cdot T_c sum_{i=0}^{k} e(i)[/tex]

Sfruttando l’approssimazione trapeziodale che approssima l’integrale, come si può vedere nell’immagine

Tusin

[tex] int_0^t e(tau)dtau simeq T_c cdot sum_{i=0}^{k} frac{e(i)+e(i-1)}{2} [/tex]

Portando la legge di controllo in questa nuova versione:

[tex] C(k) = K_p cdot e(k) + frac{K_d}{T_c} cdot (e(k)-e(k-1)) + K_i cdot T_c sum_{i=0}^{k} frac{e(i)+e(i-1)}{2}[/tex]

Nel campo complesso

Nel campo complesso il discorso è analogo e la trasfromazione equivalente della variabile s è [tex]s = frac{2 }{T_c} frac{z-1}{z+1} [/tex]

Il controllo nella variabile complessa[tex]G(s) = K_p + frac{K_i}{s} + K_d cdot s [/tex] diventa

[tex]G(z) = K_p + K_i cdot frac{T_c}{2 } frac{z+1}{z-1} + K_d cdot frac{2 }{T_c} frac{z-1}{z+1} [/tex]

[tex]G(z) = frac{K_p(z^2-1) + frac{K_i*T_c}{2} (z+1)^2 + frac{K_d*2}{T_c} (z-1)^2}{(z-1)(z+1)} [/tex]

[tex]G(z) = small frac{(K_p + frac{K_i*T_c}{2} + frac{K_d*2}{T_c}) z^2 + (K_i*T_c – frac{4*K_d}{T_c}) z + (frac{K_i*T_c}{2} +frac{K_d*2}{T_c} – K_p)}{z^2-1} [/tex]

Il controllore discreto rispetto a quello analizzato la volta precedente è una funzione propria e quindi fisicamente realizzabile.

Un algoritmo veloce

Un vincolo funzionale di questo tipo di controllo è l’utilizzo di una variabile di accumulo descritta per l’azione integrale, affinché il controllore sia veramente utilizzabile e svincolato da un termine di somma si utilizza un metodo di approssimazione.

Partendo dalla funzione [tex] C(k) = K_p cdot e(k) + frac{K_d}{T_c} cdot (e(k)-e(k-1)) + K_i cdot T_c sum_{i=0}^{k} frac{e(i)+e(i-1)}{2}[/tex]

viene calcolato il passo precedente

[tex] C(k-1) = small K_p cdot e(k-1) + frac{K_d}{T_c} cdot (e(k-1)-e(k-2)) + K_i cdot T_c sum_{i=0}^{k-1} frac{e(i)+e(i-1)}{2}[/tex]

e sottratti membro a membro tutti gli elementi

[tex]small C_{k} – C_{k-1} = K_p cdot (e_{k}-e_{k-1}) + frac{K_d}{T_c} cdot (e_{k}-2cdot e_{k-1}+e_{k-2}) + frac{K_i cdot T_c}{2} (e_{k}+e_{k-1})[/tex]

Giungendo alla forma definitiva

[tex]small C_{k} = C_{k-1} + K_p cdot (e_{k}-e_{k-1}) + frac{K_d}{T_c} cdot (e_{k}-2cdot e_{k-1}+e_{k-2}) + frac{K_i cdot T_c}{2} (e_{k}+e_{k-1})[/tex]

Lo pseudocodice associato

Per poter passare ad una forma utilizzabile dal microcontrollore il controllore può essere nuovamente elaborato e riscritto in questo modo:

[tex]small C_{k} = C_{k-1} + (K_p + frac{K_d}{T_c} + frac{K_i cdot T_c}{2} ) cdot e_{k} -( K_p + frac{2* K_d}{T_c} – frac{K_i cdot T_c}{2} ) cdot e_{k-1} +(frac{K_d}{T_c}) e_{k-2}[/tex]

Che per semplicità è riscrivibile:

[tex]C_{k} = C_{k-1} + p_0 cdot e_{k} + p_1 cdot e_{k-1} +p_2 cdot e_{k-2}[/tex]

con le seguenti costanti definite

[tex]{ p_o = K_p + frac{K_d}{T_c} + frac{K_i cdot T_c}{2} p_1 = -( K_p + frac{2* K_d}{T_c} – frac{K_i cdot T_c}{2} ) p_2 = frac{K_d}{T_c}[/tex]

Da queste funzioni e facilmente implementabile in un pseudo-codice:

#DEFINE TC ...  //Definizione del tempo di campionamento
#DEFINE Kp ...  //Definizione della costante Kp
#DEFINE Ki ...  //Definizione della costante Ki
#DEFINE Kd ...  //Definizione della costante Kd

#DEFINE P0 Kp+Kd/TC+Ki*TC/2       //Definizione della costante P0
#DEFINE P1 -(Kp+2*Kd/TC-Ki*TC/2)  //Definizione della costante P1
#DEFINE P2 Kd/TC                  //Definizione della costante P2

int err1 = 0;        //err1 = y - u
int err2 = 0;        //err2 = y - u
int err3 = 0;        //err3 = y - u
                //y = uscita, u = ingresso
int contr = 0;      //Uscita di controllo
...
//Inizializzazione controllo PID
...
while(true)
{
//Le operazioni devono essere temporizzate con un preciso passo di campionamento Tc
err1 = ... ;                            //acquisizione errore

contr += P0*err1+P2*err2+P3*err3;    //uscita di controllo

//Salvataggio dei valori dell'errore
err3 = err2;
err2 = err1;

//Adattamento segnale di controllo ed invio all'attuatore

...

}

Copyright © 2009. All Rights Reserved.

Leave a Reply