Dispensa PID

115
M ODELLISTICA E PROGETTO DI REGOLATORI PI E PID ORIENTATI ALLO SVILUPPO SU MICRO - CONTROLLORE Calzoni Pietro Francesco Castelli Dezza 17 gennaio 2007

description

DISPENSA PID CONTROLL

Transcript of Dispensa PID

Page 1: Dispensa PID

MODELLISTICA E PROGETTO DI REGOLATORI PI E

PID ORIENTATI ALLO SVILUPPO SU

MICRO-CONTROLLORE

Calzoni PietroFrancesco Castelli Dezza

17 gennaio 2007

Page 2: Dispensa PID

2

Questa dispensa cercherà di modellizzare un regolatore PI e, successivamente, PID per il controllo di unsistema stabile e instabile. L’obiettivo è realizzare i modelli di simulazione tempo-continui, discreti e, infine,digitali. Questi ultimi in particolare verranno anche simulati in modo che si possa studiare il comportamento diun regolatore digitale all’interno della catena di regolazione e il codice scritto sarà in linea di massima quelloriportabile all’interno del micro-controllore.

Per quanto riguarda la modellistica tutto verrà fatto con SIMULINK 6 fornito nel pacchetto MATLAB 7 SP1sotto sistema GNU/Linux Slackware 10.2. Si noti comunque che esistono tools molto simili (gratuiti e opensour-ce) come SHILAB che eseguono esattamente le stesse funzioni. La scelta di MATLAB è ricaduta sul fatto che èpresente nella stragrande maggioranza dei laboratori informatizzati del Politecnico di Milano e che attualmente èlo stato dell’arte per la modellistica dei sistemi.

Tutta la trattazione è orientata alla realizzazione vera e propria del controllore prendendo come riferimentoi micro-controllori di MICROCHIPTM ; la scelta di questi prodotti non è dettata da particolari motivazioni tec-niche, bensì da motivi pratici. Questi processori infatti cono distribuiti con package di tipo DIP ossia possonoessere montati e saldati agevolmente anche su millefori in modo da dare la possibilità a chiunque di effettuaresperimentazioni a basso costo. Inoltre tutti i tools di sviluppo e compilazione sono forniti gratuitamente insiemeall’ambiente di sviluppo direttamente da MICROCHIPTM comune a tutti i processori.

Page 3: Dispensa PID

Indice

1 Problematiche di calcolo digitale 51.1 Basi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.2 Operazioni tra numeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.3 Velocizzare le operazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.4 Flusso del programma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.5 Scrivere un programma C orientato al micro controllore . . . . . . . . . . . . . . . . . . . . . . 9

1.6 Integrazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2 Progetto di un regolatore PI 152.1 Regolatore tempo-continuo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.1.1 Cenni riguardo la trasformata di Laplace . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.1.2 Progetto del regolatore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.1.3 Anti wind-up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.2 Regolatore Discreto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.2.1 Cenni riguardo la trasformazione Z . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.2.2 Mappatura dei poli da s a z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.2.3 Risposta in frequenza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3 Modellistica del regolatore PI 253.1 Regolatore tempo-continuo classico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.2 Regolatore Z ottenuto dal tempo-continuo classico . . . . . . . . . . . . . . . . . . . . . . . . 29

3.3 Regolatore Digitale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.3.1 Modello C-SIMULINK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.3.1.1 Metodo 1: Separazione parte proporzionale e integrale . . . . . . . . . . . . . 34

3.3.1.2 Metodo 2: Rielaborazione del PI ottenuto dalle funzioni z . . . . . . . . . . . 37

3.3.1.3 Metodo 3: Rielaborazione del PI ottenuto dalla configurazione anti wind-up . 40

3.3.1.4 Osservazioni e Confronti . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

3.3.2 Simulazione del Duty-Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

3.3.3 Regolatore Digitale con metodo di integrazione “dei resti” . . . . . . . . . . . . . . . . 47

4 Implementazione di un regolatore PI 494.1 Regolatore PI su processori dsPIC30F . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

4.1.1 Sviluppo del regolatore in codice C . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

4.2 Controllo di tensione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

4.2.1 Progetto e implementazione del regolatore . . . . . . . . . . . . . . . . . . . . . . . . . 61

3

Page 4: Dispensa PID

4 INDICE

5 Regolatore PID 735.1 Regolatore tempo-continuo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735.2 Regolatore Discreto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765.3 Regolatore PID di corrente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

5.3.1 Progetto del regolatore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805.3.2 Simulazione del regolatore digitale . . . . . . . . . . . . . . . . . . . . . . . . . . . . 815.3.3 Implementazione su micro-processore dsPIC30F . . . . . . . . . . . . . . . . . . . . . 86

A Breviario sulla sintassi C 93A.1 Tipi di dati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93A.2 Dichiarazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

B Validità del regolatore PI 103B.1 Discretizzazione del regolatore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107B.2 Modellistica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

Page 5: Dispensa PID

Capitolo 1

Problematiche di calcolo digitale

Prima di affrontare il progetto e la realizzazione del regolatore vero e proprio, verranno affrontate alcune proble-matiche tipiche del calcolo digitale con micro processori dedicati i quali normalmente non hanno potenzialità dicalcolo molto elevate. Prima di proseguire con la trattazione viene brevemente introdotta la tabella dei simboliusati in questo capitolo:

a lettera minuscola: indica il valore reale della grandezza

arif grandezza reale di riferimento

bitbase numero di bit che identifica la base

A indica il valore in per-unità della grandezza

#Ap indica il valore normalizzato in base “p”. Per esempio: #A10 è un valore in base 10bit

# indica il processo di normalizzazione, tipicamente 2bitbase/arif

Verranno poi descritte le linee guida per la scrittura di un programma C.

1.1 Basi

Il micro calcolatore deve in primo luogo effettuare calcoli in un intervallo temporale ben definito. Le ridottecapacità di calcolo normalmente non permettono di operare con variabili di dimensioni e/o struttura complessee non ci si riferisce al formato float o double (doppia precisione), ma, spesso, neppure agli interi a 16bit! Unesempio sono i molti micro controllori PIC di MICROCHIP o HC di FREESCALE che lavorano con parole a 8bit1.

É chiaro quindi che, per rendere l’esecuzione veloce (spesso in modo determinante), occorre fare in modo cheil processore esegua i conti con numeri interi. Per rappresentare numeri reali si rende quindi necessario scegliereuna base. Questo riporto non è complesso da gestire; in linea teorica infatti è sufficiente fissare un valore diriferimento per una determinata grandezza, prendere il valore reale, dividerlo per il riferimento (ossia riportareil valore in per-unità) e quindi moltiplicarlo per la base scelta. Per esempio: si supponga di avere un valore dicorrente reale che al massimo raggiunga i 20A e il processore riesca a gestire parole a 16bit; si ipotizzi di usare

1Si noti che tipicamente riescono a gestire parole a 16bit o multipli al costo di un maggiore carico computazionale.

5

Page 6: Dispensa PID

6 CAPITOLO 1. PROBLEMATICHE DI CALCOLO DIGITALE

una base pari a 4096 (212). Allora, indicando con i la corrente reale e con #I la corrente digitalizzata, si puòasserire che

#I12 = i409620

In questo esempio si è scelto come riferimento della corrente il suo valore massimo. Non è necessario operarein questo modo; infatti il valore di riferimento viene normalmente scelto in funzione delle caratteristiche delsensore.

Per quanto riguarda la base scelta, il numero 4096 non è casuale! Esso è infatti una potenza di 2. Ciò renderàmolto più comodo eseguire operazioni tra basi, come si vedrà in seguito. É però evidente che si è scelto di operarecon variabili a 16 bit e che con tale base si possono rappresentare numeri in [p.u.] compresi tra -8 e 8. Potrebbesembrare esagerato ma tali valori permettono di eliminare il problema dell’overflow a seguito dell’esecuzione dioperazioni. Per esempio se una grandezza a 16bit (ma in base 12bit) viene calcolata come somma di qualchevariabile (per esempio 3) in base 12bit (e supponiamo limitate a 4095) il risultato sarebbe contenuto in 14 bitsenza bisogno di effettuare controlli sulle soglie che costano in termini computazionali e possono quindi esseredifferiti alla fine dei calcoli. Si noti che i bit a disposizione sono sì 16, ma il sedicesimo bit è di segno.

Variabilità della base

Una base non deve necessariamente rimanere la stessa durante tutta l’esecuzione del programma. Essa nonsolo può variare, ma può essere anche diversa tra variabili che concorrono a generare lo stesso risultato, comeper esempio il termine integrale in alcuni PI (sezioni 3.3.1 e 4.1.1); se infatti il termine è molto minore di 1,conviene prevedere degli accorgimenti necessari a non perdere dati significativi. Il problema dell’integrazioneverrà affrontato più avanti, ma per ora basti sapere che spesso (e se possibile) conviene usare una variabile aldoppio della base (pari a 24bit, quindi in una variabile tipo long int) ed effettuare conversioni di base quandoverrà richiesto il valore in una base differente.

1.2 Operazioni tra numeri

Le operazioni di somma e sottrazione tra numeri interi non presentano grossi problemi (escludendo l’overflowdescritto poco prima) e il risultato, qualunque valore abbia, è nella stessa base dei due addendi. Moltiplicazionee divisione invece hanno qualche problema.

Moltiplicazione: la moltiplicazione tra due numeri della stessa base pari al prodotto dei due diviso la base deidue numeri:

#Cbitbase = #(A ·B)bitbase =#Abitbase ·#Bbitbase

2bitbase

ma avendo scelto basi con potenze di 2, l’operazione si semplifica e si velocizza in quanto la divisione perpotenze di 2 equivale a uno shift logico dei bit verso destra:

#Cbitbase = #(A ·B)bitbase = (#Abitbase ·#Bbitbase) bitbase

Questa operazione risulta molto più agevole per il micro processore, mentre una divisione è molto piùpesante. La moltiplicazione tra basi differenti invece avviene all’opposto:

#C10 = #(A ·B)10 =#A12 ·#B9

212+9−10= (#A12 ·#B9) 11

Page 7: Dispensa PID

1.3. VELOCIZZARE LE OPERAZIONI 7

Divisione: la divisione è analoga. In questo caso però conviene premoltiplicare il numeratore per non perdere inprecisione:

#Cbitbase = #(

A

B

)bitbase

=#Abitbase bitbase

#Bbitbase

1.3 Velocizzare le operazioni

Come si è accennato le operazioni matematiche come moltiplicazioni e somme sono molto pesanti per il micro-controllore. Per guadagnare tempo quindi si definiscono una serie di shift, normalmente più veloci da gestire iquali possono aiutare a velocizzare l’esecuzione del programma. Se l’operazione è tra un valore e una costanteconviene riportare tutto all’operazione di moltiplicazione, per esemio #A = #B/0.3125 = #B · 3.2. In questoesempio si vede come il secondo termine non sia un numero intero. Grazie agli shift possiamo tenerne contoscomponendolo: 3.2 ' 21 + 20 + 2−3 + 2−4 + 2−5 da cui ne deriva #A = (#B 1) + (#B) + (#B 3) + (#B 4) + (#B 5).

Le operazioni matematiche però non sono le uniche “pesanti”. Altre operazioni di rilievo sono le chiamate(CALL) di funzione le quali sono tanto più pesanti quanti più parametri vengono passati in quanto vanno nor-malmente salvati nello stack; è evidente quindi che in un sistema a micro-controllore sono da evitare funzionidi tipo ricorsivo. Per ovviare a questo inconveniente può risultare utile definire la funzione tramite la direttiva__inline__ come segue:

void __inline__ callback(int, int, int);

Lo svantaggio di usare questa formulazione è che il codice normalmente diventa molto voluminoso.Una alternativa alla direttiva __inline__ è la definizione di una macro, ma l’utilizzo è consigliabile solo se

le operazioni sono relativamente poche o relative alla analisi di una struttura (ottimi esempi nel codice sorgentedei dispositivi a caratteri del kernel Linux). La definizione di una macro è:

#define NOME_MACRO(var1, var2, varN)(var1*5-(var2>>4)-3*varN)

Da porre attenzione al fatto che la macro non fa altro che sostituire l’espressione che segue la definizionedegli argomenti in parentesi con quanto gli veine passato. Quindi, quando la macro viene chiamata, i parametridevono essere o numerici o contenuti in parentesi per precauzione. Se all’interno del programma la macro venissechiamata nel modo seguente:

x = NOME_MACRO(2-1, 0, 1+1)

x assumerebbe il valore x=2-5-2*1+1=-4 al posto del valore desiderato ossia x=(2-1)*5-2*(1+1)=1.Quindi il metodo corretto per scrivere una macro è ricorrere il più possibile alle parentesi:

#define NOME_MACRO(var1, var2, varN)((var1)*5-((var2)>>4)-3*(varN))

Altri errori di calcolo sono legati al metodo di scrittura degli shift logici i quali come precedenza sono inferiorialla somma, ossia una macro del tipo:

#define MACRO(var1)(var1<<2 + var1>>1)

il primo shift (a sinistra) avrà come numero di bit da shiftare un valore pari a (2 + var1). Per esempio convar1=4 il risultato di MACRO effettua il calcolo (4(2+4))1=128 mentre il risultato atteso è (42)+(41)=18.Per questo anche in questo caso occorre usare il maggior numero di parentesi.

Page 8: Dispensa PID

8 CAPITOLO 1. PROBLEMATICHE DI CALCOLO DIGITALE

Le macro possono introdurre anche un altro problema legato alla castizzazione2; infatti una macro del tiposeguente:

#define NOME_MACRO(var1)((var1)<<10)

se chiamata all’interno del programma in modo che e sia una variabile per esempio di tipo int, ma il risultatosia da porre in una di tipo long int, il valore verrà prima calcolato in int e, se ciò causa un overflow, il risultatoverrà troncato e successivamente assegnato a long int. Questo è un errore frequente quanto grave. Per porvirimedio o si castizza l’argomento della macro quando essa viene chiamata nel programma, o lo si castizza nelcodice della macro.

Le macro che realizzano shift verso destra (ossia divisioni per potenze di 2) hanno un grande inconvenientese lavorano su numeri con segno. Si consideri a tal proposito la seguente macro:

#define SHIFT_DX(e)((e>>4)+(e>>5)+(e>>6))

Si supponga ora che venga passato come ingresso il numero intero (ossia definito int) pari a 10 che in binarioa 16bit si esprime come 0b0000000000001010: il risutltato è chiaramente 0 perché ogni shift sposta i vari bit diuna posizione sostituendo il vecchio valore con il valore del bit più significativo, ossia il bit di segno. Se però ilnumero è -10 (che in binario risulta 0b1111111111110110) il risultato è -3!3 Questo perché gli shift di numerinegativi sostituiscono i bit spostati con il valore 1 ossia il valore del bit di segno. Quindi se la macro ha shiftnegativi (soprattutto se la macro realizza un integrale) la corretta sintassi è la seguente:

if(input>=0) output=SHIFT_DX(input)

else output=-(SHIFT_DX((-input)))

1.4 Flusso del programma

L’esecuzione del programma non è lineare come invece avviene nei normali programmi4. Il programma normal-mente parte chiamando la funzione main la quale provvederà a compiere tutte le inizializzazioni di variabili edispositivi. Fatto ciò il micro passa in un loop infinito. Il programma, quindi, continuerà ad eseguire le opera-zioni definite in questo loop il quale potrà essere interrotto da determinati eventi (interrupt) legati ai dispositivipresenti sul processore e alle condizioni di I/O. Normalmente infatti non si gestisce la richiesta di un eventoin polling (ossia controllando ciclicamente che sia avvenuto un evento) in quanto si perde tempo di CPU pereseguire operazioni che il più delle volte danno risultato nullo (come per esempio la gestione dei pulsanti).

Gli interrupt, però, possono essere asserviti anche ad eventi interni al micro-processore generati da sistemicome timer, PWM, convertitori, ecc. Ciò è fondamentale perché nei sistemi embedded normalmente è richiestoil real-time5, ossia occorre essere sicuri che entro determinate scadenze temporali il sistema abbia effettuato tuttele operazioni necessarie per effettuare la regolazione.

A titolo di esempio si consideri il sistema di controllo della corrente in un regolatore. É prassi fare in modoche la routine di regolazione (per esempio PI) venga asservita alla richiesta di interruzione dovuta all’evento difine conversione del convertitore analogico-digitale. Le temporizzazioni invece possono essere date con timer oPWM (come si vedrà in seguito).

2Questo problema in realtà sarebbe da imputare al compilatore. Si noti che nel compilatore C30 e C18 di MICROCHIP questo problemaesiste, mentre, per esempio, nel compilatore gcc Linux (da cui i compilatori menzionati derivano) non vi è questo problema.

3Si ricorda che 0b1111111111111111 = -1.4Sempre che non ricorrano a fork o thread.5Spesso si intende implicitamente hard real-time ossia che se non vengono garantite determinati risultati entro certe scadenze, viene

compromesso il funzionamento del dispositivo sotto controllo (per esempio i sistemi intrinsecamente instabili); viceversa per il soft real-time.

Page 9: Dispensa PID

1.5. SCRIVERE UN PROGRAMMA C ORIENTATO AL MICRO CONTROLLORE 9

Priorità

Le funzioni di interrupt sono prioritarie ed interrompono l’esecuzione normale del programma, dove per “norma-le” si intende tutto ciò che viene seguito dalla funzione main. Gli interrupt però, vengono a loro volta gestiti condeterminate priorità in funzione del processore. A titolo di esempio si considerino le seguenti famiglie:

PIC16F fino alla versione 16F i pic hanno una sola chiamata di interrupt. Per capire quale dispositivo hainvocato l’interruzione, occorre esaminare specifici flags.

PIC18F sono più evoluti e tra le altre migliorie hanno introdotto anche due funzioni di interrupt: una abassa priorità e una ad alta priorità. In questo caso la funzione di interrupt ad alta priorità è ingrado di interrompere quella a bassa priorità. Rimane comunque da capire quale evento ha scatenatol’interrupt e ciò viene fatto sempre esaminando determinati flags.

dsPIC30F hanno interrupt per ogni dispositivo con una priorità variabile tra 0 e 7. Le routine a più alta prio-rità possono interrompere quelle a più bassa priorità e sono normalmente più veloci per evitare dioccupare troppo tempo di CPU che dovrebbe essere destinato ad altre routines. Infatti questo si-stema di gestione delle priorità è si molto versatile ma può rendere difficoltoso l’analisi del flussodi programma. In questi processori esistono comunque flags che indicano l’avvenuta richiesta diinterrupt, anche se normalmente vengono usati solo dai dispositivi che generano la stessa richiesta diinterruzione a fronte di propri eventi interni differenti (come per esempio la ricezione, trasmissione,generazione errori, ecc nel modulo CAN).

1.5 Scrivere un programma C orientato al micro controllore

Un programma C è costituito normalmente da files .h e .c. I primi sono detti di intestazione (header) e so-no files in cui vengono definite le funzioni, macro, variabili, tipi, ecc; i secondi sono i files che contengonol’implementazione delle funzioni definite nei files .h.

Struttura di un file header

É buona norma che tutto il codice definito in un file header sia posto all’interno di una macro di precompilazione#if come segue:

#ifndef __NOMEFILE_H__# define __NOMEFILE_H__//TODO#endif //__NOMEFILE_H__

il che serve per comunicare al compilatore che durante la compilazione di un file .c se l’inclusione del filenomefile.h viene fatta più volte (per esempio da altri file .h) questo file è gia stato incluso. In caso contrario ilcompilatore restituirebbe dei warnings (o degli error) a causa di definizioni multiple di tipi, define, ecc.

Per quanto riguarda le definizioni di funzioni e variabili all’interno del file header, tipicamente occorredefinirle come extern:

extern void CallBack(int, int); //funzioneextern int error; //variabile

Page 10: Dispensa PID

10 CAPITOLO 1. PROBLEMATICHE DI CALCOLO DIGITALE

Questo implica che esisterà un file .c in cui queste label vengono riprese e, se funzioni, implementate. In casocontrario in fase di linking, il linker restituirà un errore simile al seguente:

/tmp/ccgbPtiF.o(.text+0x16): In function ‘main’:: undefined reference to ‘CallBack’collect2: ld returned 1 exit status

e analogamente per le variabili. La keyword extern ha anche un altro utilizzo, ossia permette al linker di collegarefunzioni che non sono state implementate in un apposito file .c, ma passate tramite dei files oggetto o librerieprecompilate.

Nei files .h vengono spesso definite anche le grandezze const:

const int X[LENGTH_X] = //TODO, x es: 1, 2, 3;

Questa non è la scelta più oculata in quanto potrebbero accadere errori dovuti alla multipla inclusione, ma nor-malemente queste costanti vengono usate solo da uno specifico file quindi incluse una volta sola. Nel microcontrollore la keyword const implica che la variabile andrà scritta nell’area codice (.code) e non nell’area da-ti (.text), quindi non potrà essere scritta in run-time. Un tentativo di scrittura comporta normalmente un resetdel processore. Si noti che normalmente l’area .text è nettamente più piccola dell’area .code. Per maggioriinformazioni su questo argomento si veda [3] o il manuale del compilatore C del processore specifico.

Struttura dei files C

Come detto il file .c più importate è quello che contiene la funzione main. Essistono però i file che contengonol’implementazione delle funzioni C definite negli header files. Tali funzioni non devono ovviamente ripetersi.

Un file C che contiene la funzione main è normalmente strutturato come segue:

#include <p30fxxxx.h> //inclusioni di file contenuti nelle directory del compilatore#include ”localfile.h” //inclusione di un file nella directory di progetto//definizione macro#define MUL2(in)(((int)in<<1))//definizione variabili globalilong int integrale=10, derivata;//definizione di funzioni a visibilità globale, x es:int moltiplicazione(int x, int y);//implementazione del main: definita una volta sola all’interno del progettoint main ()

//TODO

while(1) //loop infinito//TODO

//implementazione delle funzioni localiint moltiplicazione(int x, int y)

return x*y;//Eventuale implementazione delle routine i interrupt.//La sintassi varia da micro a micro; qui è riportata quella per dsPIC30Fvoid _ISR _T1Interrupt()

//TODO

Come si nota all’interno della funzione main deve esserci un ciclo infinito. Questo perché il micro non deveterminare il programma altrimenti si resetterebbe. All’interno del ciclo while non è strettamente necessario che

Page 11: Dispensa PID

1.6. INTEGRAZIONE 11

vengano svolte operazioni. Una volta entrati in questo ciclo tutto il controllo è affidato di norma alle routine diinterrupt; solo routine di minore importanza vengono gestite in polling all’interno del ciclo.

Un ciclo infinito può essere definito anche nei seguenti modi:

• Ciclo do ... while:do // TODO while (1);

• Ciclo FOR:for(;;)// TODO

• GOTO:goto_label:// TODOgoto goto_label;

1.6 Integrazione

L’integrazione in un micro controllore viene tipicamente fatta con il metodo dei rettangoli o con il metodo deitrapezi (detto anche di Eulero) il quale è più preciso del precedente. L’integrazione di una grandezza tipicamenteè problematica in quanto il coefficiente di integrazione è normalmente molto piccolo e ciò implica che spesso il“piccolo errore” non venga valutato. Per esempio si consideri un coefficiente Ki=10 e un tempo di integrazioneTs=50·10−6s. Supponendo ora una variabile errore e intera, la quota parte di integrale all’istante n-esimo saràpari a

KiTs2

(e(n) + e(n− 1)) = 2, 4 · 10−4 (e(n) + e(n− 1))

Non entriamo per il momento nel merito di come si realizzi il parametro floating poit 2.4 · 10−4, ma è noto che ilmicroprocessore elabori variabili intere e perciò il risultato di questa operazione dovrà essere un numero intero.Considerando ora la variabile errore e di tipo intero che, per esempio, assume valori tra 0 e 4096, è chiaro cheperché il risultato della moltiplicazione dia almeno il valore 1 occorre che e(n) + e(n − 1) valga almeno 4000.Per questo occorre gestire opportunamente la grandezza “integrale”. Di seguito sono proposti alcuni metodi.

Il codice che verrà presentato nelle sezioni seguenti è da considerarsi “pseudo codice” nel senso che servesolo per dare un’idea di come tradurre in C il problema formalizzato.

Variabili a 32 bit

Scelta la base di conversione delle grandezze fisiche (per esempio 12 bit) si suppone di lavorare con una basedell’integrale diversa, tipicamente il doppio dei bit della base delle grandezze fisiche (quindi 24 bit). Questovuol dire che il valore del coefficiente Ki

Ts

2 verrà calcolato come KiTs

2 212 = 1, 024. A questo punto è possibilevalutare il piccolo errore “tenendone memoria” nella variabile di integrazione. Chiaramente la variabile risultanteè in base 24 bit quindi occorre un intero a 32 bit per poterla gestire (long int nel micro controllore).

Per quanto riguarda l’implementazione è possibile seguire il metodo degli shift introdotto nella sezione 1.3.Volendo realizzare il parametro 2.4 · 10−4 risulta:

#define INTEGRALE(e)((e>>12))

Page 12: Dispensa PID

12 CAPITOLO 1. PROBLEMATICHE DI CALCOLO DIGITALE

il che implica praticamente la perdita di tutti i valori minori di 4095, come ci si poteva aspettare. Portando inveceil valore di Ki in base 24 nit si ha che la macro può essere definita come:

#define INTEGRALE(e)((e)+(e>>6)+(e>>7)+(e>>11))

il che permette di tenere conto del piccolo errore anche in fase di integrazione. All’interno del programmal’integrale verrà gestito come segue:

long int integrale; //variabile a 32 bit...error_i=error+error_1; //calcolo error_i come l’errore attuale+l’errore precedenteif(error_i>=0)

integrale+=INTEGRALE_L(error_i);else

integrale-=INTEGRALE_L((-error_i));

Pro e contro di questo metodo sono evidenti: è sicuramente favorevole il fatto che tutte le operazioni si riducanoa degli shift le quali sono operazioni di norma eseguite con un bassissimo numero di cicli di clock e quindimolto performanti anche con grandezze di notevole dimensione come le variabili long int. Di contro si hache le operazioni su grandezze di tipo long restano comunque “pesanti” dal punto di vista computazionale perprocessori a 8 bit (come i PIC) perché occorre ricordare che tale grandezza andrà poi riscalata alla base scelta perpoter essere omogenea con le altre grandezze del regolatore per esempio per calcolare l’uscita:

out=proporzionale+derivativo+((int)(integrale>>12));

dove out, proporzionale e derivativo in questo caso sono da considerarsi variabili in base 12 bit.Ciò nonostante in questa dispensa, questo metodo sarà quello più utilizzato.

Gestione dei resti

La gestione dei resti è utile per micro processori con scarse capacità computazionali o in quei casi in cui ilmetodo precedentemente descritto non funzioni correttamente. Un metodo per eseguire ciò può essere quello ditenere in considerazione l’elaborazione del “piccolo errore” e del “ grande errore”; a tal proposito si suppongadi essere nelle condizioni del caso precedente, ossia di avere un Ki=10 e Ts=50·10−6s. Si consideri ora diavere due variabili che tengano conto della componente più significativa e meno significativa di un integrale(rispettivamente indicate con intH e intL). La gestione del resto può quindi essere espressa in questo modo:

#define UNITA_INTEGRALE 4095#define INTEGRALE_H(e)((e))#define INTEGRALE_L(e)((e>>6)+(e>>7)+(e>>11))int intH, intL, error_i; //int è da intendersi a 16 bit, ma i valori sono in base 12bit!...//nella routine si ha

error_i=error+error_1; //calcolo error_i come l’errore attuale+l’errore precedenteintH+=INTEGRALE_H(error_i); //non faccio controlli su error_i perché non ho shift destriif(error_i>=0)

intL+=INTEGRALE_L(error_i);else

intL-=INTEGRALE_L((-error_i));//Controllo del superamento dell’unità (UNITA_INTEGRALE)

if(intL>UNITA_INTEGRALE) intH++; //aumento di 1 la parte integrale più significativa

//riduco di una unità intL che ha superato il valore massimo positivointL-=UNITA_INTEGRALE;

else if(intL<-UNITA_INTEGRALE) intH--; //diminuisco di 1 la parte integrale più significativa

//aumento di una unità intL che ha superato il valore massimo negativo

Page 13: Dispensa PID

1.6. INTEGRAZIONE 13

intL+=UNITA_INTEGRALE;...out=proporzionale+derivativo+intH;

Come di può notare l’integrale è diviso in due e la somma è pari a quella del caso precedente solo che questavolta vengono calcolati separatamente e i risultati posti in variabili in base 12 bit. La parte minore (intL) vienetrattata in modo tale che non superi mai il valore 4095, ossia il valore corrispondente all’unità. Qualora questovalore venisse superato, intL avrà sicuramente il 13 bit a 1 che corrisponde all’unità da aggiungere a intH,operazione che viene fatta subito dopo; quindi intL viene ridimensionata sottraendo il valore 4095. Per quantodetto è evidente che la variabile intL dopo la sottrazione si porta ad un valore minore di UNITA_INTEGRALE.Tutto quello che è stato appena detto è ripetibile anche nel caso in cui la soglia superata sia quella negativa. Siosservi che quando occorre utilizzare la variabile integrale (come per il calcolo di out) è sufficiente utilizzare laparte più significativa del valore dell’integrale espressa nella stessa base delle altre grandezze. Il metodo appenadescritto non ha nessun pregio significativo rispetto al precedente in quanto è evidente che la precisione resta lastessa a fronte di un carico computazionale maggiore.

É possibile introdurre un altro modo per gestire il problema agendo direttamente sulla variabile error_i.Per fare questo si considera il valore reale del termine integrale è Ki

Ts

2 212 = 1, 024 il che è scomponibile comeKi

Ts

2 212 = 1, 024 = 1 + 0, 024 = H + L, do ve chiaramente H = 1 e L = 0, 024. La parte maggiore dizero continuerà ad essere gestita come in precedenza, mentre la parte inferiore verrà gestita in un altro modo.Ora occorre valutare quale valore della variabile error_i fa in modo che si raggiunga l’unità; tale valore è chia-ramente 0, 024−1 = 41, 6 arrotondato sempre per eccesso, quindi 42. Quindi isolando i bit che compongono ilnumero 42 nella variabile error_i e sommandoli ad oni ciclo di integrazione, quando l’integrale intL raggiungerà(o supererà) il valore 42 occorrerà aumentare di una unità il valore intH e ridimensionare intL. Assumendo cheper poter esprimere il numero 42 occorrono 6 bit6, lo stralcio di codice seguente dà un’idea di come realizzarequanto detto:

#define UNITA_INTEGRALE 42#define MASK_INTL 0x3F //maschera separare i 6 bit necessari al calcolo di intL#define INTEGRALE_H(e)((e))#define INTEGRALE_L(e)(((e)&MASK_INTL))int intH, error_i; //int è da intendersi a 16 bit, ma i valori sono in base 12bit!short int intL; //short int è da considerarsi a 8 bit...//nella routine si avrà...

error_i=error+error_1; //calcolo error_i come l’errore attuale+l’errore precedenteintH+=INTEGRALE_H(error_i); //non faccio controlli su error_i perché non ho shift destriif(error_i>=0)

intL+=INTEGRALE_L(error_i);else

intL-=INTEGRALE_L((-error_i));//Controllo del superamento dell’unità (UNITA_INTEGRALE)

if(intL>=UNITA_INTEGRALE) // questa volta devo verificare che sia >=intH++; //aumento di 1 la parte integrale più significativa

//riduco di una unità intL che ha superato il valore massimo positivointL-=UNITA_INTEGRALE;

else if(intL<=-UNITA_INTEGRALE) intH--; //diminuisco di 1 la parte integrale più significativa

//aumento di una unità intL che ha superato il valore massimo negativointL+=UNITA_INTEGRALE;

...out=proporzionale+derivativo+intH;

66 bit ottenuti arrotondando per eccesso il risultato di log2(42); in Matlab: ceil(log2(42))

Page 14: Dispensa PID

14 CAPITOLO 1. PROBLEMATICHE DI CALCOLO DIGITALE

Come si nota non cambia molto nella struttura del programma anche se il carico computazionale si è abbassato.Inoltre intL ora è a 8 bit quindi più facilmente gestibile da micro processori come i PIC. Come si nota laprecisione è aumentata in quanto nei casi descritti precedentemente tutti i valori di error_i minori di 26−1 = 63venivano scartati, mentre ora vengono considerati.

Page 15: Dispensa PID

Capitolo 2

Progetto di un regolatore PI

In questo primo capitolo verrà trattato il progetto di un semplice regolatore PI per il controllo di un sistema delprimo ordine, come per esempio la funzione di trasferimento tra corrente e tensione in un induttore. Verrà quindipresentato come realizzare un regolatore partendo dallo studio delle funzioni continue nella variabile tempo t

(ossia si progetterà il regolatore analogico) per poi portare i risultati nel tempo discreto. Il passo successivo saràrealizzare il codice vero e proprio che un microprocessore possa eseguire. Ciò verrà fatto restando inizialmentein ambiente Simulink.

2.1 Regolatore tempo-continuo

Il regolatore tempo-continuo, come noto, viene definito studiando il sistema da controllare nel dominio dellafrequenza, ossia applicando la trasformazione di Laplace alle equazioni di stato.

Figura 2.1: Retroazione di un sistema con regolatore PI.

Banalmente un sistema controllato con un regolatore PI è rappresentato in figura 2.1; in particolare questoregolatore PI controlla un sistema stabile di tipo R-L. In questo caso il regolatore permette di migliorare la rispostadel sistema cercando di seguire il più fedelmente possibile il riferimento di corrente in ingresso. In questo schemasono volontariamente eliminati i ritardi e le funzioni di trasferimento degli azionamenti e dei sensori. É comunquechiaro che la corrente in un sistema reale dovrà essere retroazionata tramite un sensore apposito e che il regolatoreè comprensivo dell’azionamento vero e proprio (ossia dell’alimentatore ideale1 di tensione).

I due blocchi in figura verranno indicati in seguito come R(s) per quanto riguarda il regolatore PI e G(s) perquanto riguarda la funzione del sistema in esame.

Negli esempi seguenti il regolatore PI verrà applicato su sistemi intrinsecamente stabili.

1Per “ideale” non si intende solo il fatto che i ritardi introdotti siano nulli, ma anche che il sistema può dare un valore di tensione continuoe illimitato istantaneamente.

15

Page 16: Dispensa PID

16 CAPITOLO 2. PROGETTO DI UN REGOLATORE PI

2.1.1 Cenni riguardo la trasformata di Laplace

La trasformata di Laplace è una funzione lineare che permette di studiare una funzione reale (normalmentefunzioni temporali) tramite una corrispondente funzione complessa.

Definita una funzione reale (f : (0, +∞) → R) si ottiene l’integrale di Laplace come

F (s) = Lf (s) = limT→+∞

limτ→0

∫ T

τ

e−stFf(t)dt

o nella foma generalizzata

F (s) = Lf (s) =∫ ∞

0

e−stF (t)dt

Questa relazione è lineare ed è molto comoda per lo studio dei sistemi come regolatori e filtri per i quali nonvi è motivo di effettuarne lo studio per valori temporali negativi.

Per quanto riguarda la convergenza della serie, questa è legata sia alla funzione f(t) sia alla variabile s. Infattise la funzione f(t) è, come precedentemente definito, una funzione reale ed anche s è una funzione reale, si hache la trasformata di Laplace restituisce come risultato un numero reale; quindi indicando con A il dominio dellatrasformata di Laplace

A :=

s ∈ R :∫ +∞

0

e−stf(t)dt

si ha

F : A → R, F (s) =∫ +∞

0

e−stf(t)dt (2.1)

per tanto si ha convergenza se esiste ed è funito l’integrale reale della funzione f(t).

Se invece la funzione s è un numero complesso

B :=

s ∈ C :∫ +∞

0

e−stf(t)dt

come per esempio s = x + iy , allora la trasformata si esprime come

F (s) =∫ +∞

0

e−xt (cos(yt) + i sin(yt)) f(t)dt (2.2)

da cui deriva che la convergenza sia assicurata se convergono i due integrali reali in cui si scompone la funzione.

Il principale vantaggio introdotta da questa trasformazione riguarda la risoluzione delle equazioni differenzialile quali diventano di tipo algebrico e consentono di studiare un sistema fisico come funzione fratta. La stabilitàdel sistema è assicurata dal fatto che le soluzioni che annullano il polinomio a denominatore (ossia i poli) devonoessere tutti a parte reale negativa.

2.1.2 Progetto del regolatore

Il progetto del regolatore PI è normalmente abbastanza semplice in quanto vengono definite due equazioni in dueincognite. Le incognite sono i coefficienti del regolatore, mentre le due equazioni vengono definite fissando ilmargine di fase e banda passante. Il problema è come scegliere tali valori. Il margine di fase si fissa normal-mente pari a 90. Ciò permette di non avere sovra-elongazioni nella risposta al gradino. Per quanto riguarda labanda passante, la cosa è più complessa in quanto dipende tutto da come verrà implementato il regolatore reale.

Page 17: Dispensa PID

2.1. REGOLATORE TEMPO-CONTINUO 17

Infatti per il teorema del campionamento si sa che scelta la massima armonica campionabile senza aliasing, lafrequenza di campionamento dovrà essere doppia di quella di tale armonica. Nei casi pratici, però, questo nonavviene praticamente mai soprattutto se non vengono implementati filtri di ordine elevato in uscita al trasduttore2.Tipicamente quindi si sceglie una frequenza di circa 10÷20 volte inferiore a quella di campionamento la qualeviene decisa in funzione delle capacità elaborative dei micro-controllori e viene data in termini di pulsazione; ciòverrà trattato più avanti nel dettaglio, quindi per ora si consideri la scelta (tipica) di 1000÷1500 rad/s.

Definito il sistema in termini di banda passante (ωt3 ) e margine di fase (φm) è possibile ottenere le dueequazioni di cui sopra esprimendo in modulo e fase la funzione d’anello L(s) :

|R(jω) ·G(jω)| = 1]R(jω) + ]G(jω) = −180 + φm

(2.3)

da cui si può isolare l’espressione del regolatore in termini di modulo e fase:|R(jωt)| = 1

|G(jω)|

]R(jωt) = −180− φm − ]G(jωt) = θ(2.4)

L’uscita di un regolatore PI nel dominio del tempo è funzione dell’errore in ingresso ed è la seguente:

uPI(t) = KP e(t) + KI

∫ t

e(x)dx = KP

(e(t) +

1Ti

∫ t

e(x)dx

)(2.5)

la quale portata nel dominio di Laplace diventa:

UPI =(

KP +KI

s

)E(s) = PI(s) · E(s) = R(s) · E(s) (2.6)

Esprimendo il regolatore in funzione della frequenza si ha:

R(jω) = KP +KI

jω= KP − j

KI

ω= |R(jω)|ejθ = |R(jω)| · (cos(θ) + jsin(θ)) (2.7)

Detto questo, dalle equazioni 2.4, 3.2 e 2.7 si ottengono le due equazioni in due incognite che permettono ladeterminazione i parametri del regolatore:

KP = |R(jωt)| cos(θ) = cos(θ)|G(jωt)|

KI = − |R(jωt)| sin(θ) = − sin(θ)|G(jωt)|ωt

(2.8)

2.1.3 Anti wind-up

Normalmente tutti i regolatori (ma anche i sistemi in esame) vengono muniti di opportune soglie in uscita in mododa impedire che le azioni di un determinato blocco (ossia le loro uscite) raggiungano valori poco realistici a causadei dispositivi fisici a disposizione per realizzare l’azionamento vero e proprio. Ciò però normalmente non bastaad evitare il problema di wind-up. Tale problema è legato normalmente all’azione integrale4 la quale, a frontedi un errore non nullo, tende a divergere anche se l’uscita del sistema viene saturata. Questo causa una notevole

2Tali filtri possono anche essere di tipo digitale implementati sul microcontrollore applicati ai segnali campionati prima che esegua leroutine di controllo e regolazione.

3Si noti che la pulsazione relativa alla banda passante si assume coincidente con la pulsazione di taglio in quanto la funzione d’anellodefinita come L(s) = R(s)G(g) in retroazione, deve restituire una funzione di trasferimento risultante tra ingresso e uscita ( i

irif) di modulo

unitario (0 in dB nel diagramma di Bode) fino al punto di intersezione di L(s) con l’asse 0 dB, ossa fino alla pulsazione ωt.4Si vedrà in seguito che anche la componente derivativa può avere problemi di questo tipo.

Page 18: Dispensa PID

18 CAPITOLO 2. PROGETTO DI UN REGOLATORE PI

perdita di reattività da parte del controllo e, soprattutto, si può incorrere in spiacevoli conseguenze dipendenti daitipi di integratori (sia analogici che digitali). Lo schema tipico di un sistema anti wind-up è riportato in figura2.2.

Non ci si dilungherà oltre in questa descrizione in quanto questo sistema di anti wind-up (come anche altri piùcomplessi) serve solo per modellizare il sistema nel dominio del tempo, mentre nel digitale le cose si risolvonomolto più semplicemente (sezione 3.3). Inoltre in [1] viene descritto dettagliatamente tutto il il processo didigitalizzazione.

Figura 2.2: Schema a blocchi di un tipico sistema anti wind-up per regolatori PI.

2.2 Regolatore Discreto

I regolatori di tipo discreto sono regolatori che elaborano ingressi di tipo reale, discretizzando il tempo, os-sia prelevando le valori ad intervalli regolari. É immediato intuire che questo sistema si avvicina molto alcomportamento del regolatore reale il quale però presenta ulteriori complicazioni che verranno mostrate inseguito.

2.2.1 Cenni riguardo la trasformazione Z

La trasformata z di una sequenza x(n) generica è definita secondo le espressioni seguenti:

x(z) =∞∑

n=−∞x(n)z−n x(z) =

∞∑n=0

x(n)z−n (2.9)

rispettivamente dette bilatera e unilatera, dove la variabile z è una variabile esprimibile in forma polare:

z = rejω

Da ciò ne consegue che la trasformazione si può esprimere come prodotto della trasformata di Fourier per lasequenza esponenziale:

x(reiω) =∞∑

n=−∞x(n)(rejω)−n =

∞∑n=−∞

r−ne−jωn

É chiaro che perché la funzione converga deve risultare finita la sommatoria

∞∑n=−∞

|x(n)r−n| < ∞

Tale espressione deriva direttamente dalla seguente

∞∑n=−∞

x(n)z−n < ∞

Page 19: Dispensa PID

2.2. REGOLATORE DISCRETO 19

dalla quale è immediato intuire che, data la natura della variabile z, la regione di convergenza di questa funzionesia una regione circolare (o anulare) del piano complesso.

Dal punto di vista dei controlli/filtri digitali, lo studio delle funzioni tempo-discrete viene fatto normal-mente ricorrendo alla Z-Trasformata. Con questo tipo di funzioni è normalmente possibile realizzare una ap-prossimazione della funzione regolatore R(s) che permetterà poi di passare alla definizione di un modellodigitale.

(a) schema a blocchi

(b) segnale e(t) (c) segnale capionato e(n)

Figura 2.3: Campionamento di una funzione continua.

In figura 2.3 è rappresentato lo schema di campionamento di una funzione continua (come per esempio lafunzione errore) i cui campioni sono presi a intervalli regolari Ts, da cui e∗(n) = e(kTs) con k ∈ N; e∗(n) è unasequenza di campioni. Un grande vantaggio che deriva da questa formalizzazione è che ogni grandezza variabiledefinita nel dominio z moltiplicata per zn equivale a considerare l’n-esimo campione della sequenza associataalla grandezza; per esempio:

y = xz−1 + 2xz → y∗(n) = x(n− 1) + x(n + 1)

2.2.2 Mappatura dei poli da s a z

Come detto, per ottenere una funzione digitale implementabile su micro controllore, occorre passare per la trasfor-mata z in modo da approssimare al meglio la funzione tempo-continua. Per fare questo occorre quindi mappare ipoli e gli zeri in s nel corrispondente dominio z.

Dalla figura 2.4 è subito chiaro che, essendo le due aree di convergenza una un semipiano e l’altra una zonaanulare, occorre determinare una funzione che degradi il meno possibile la risposta del regolatore in z. Per fare ciòsi ricorre tipicamente alle trasformazioni bilineari le quali derivano dalla considerazione che lo scopo ultimo dellaprogettazione del regolatore digitale è di descrivere il sistema tempo-continuo tramite opportune equazioni alledifferenze ossia discretizzando la funzione continua R(s). Per fare ciò quindi si parte da semplici considerazioniriguardo l’integrazione numerica, la quale deve approssimare quella nel continuo.

Page 20: Dispensa PID

20 CAPITOLO 2. PROGETTO DI UN REGOLATORE PI

Figura 2.4: Dominio di convergenza della funzione s e z.

(a) tempo-continuo (b) discreto

Figura 2.5: Integratori.

Prendendo in considerazione quanto riportato in figura 2.5-a, un puro integratore è costituito da una sempliceequazione di stato

dy(t)dt

= u(t)

Se ora venisse richiesto di realizzare un algoritmo di integrazione della funzione u(t), le soluzioni immediate epiù semplici che probabilmente vengono in mente, una volta definito che la funzione viene campionata a intervalliTs regolati, sono l’approssimare la funzione con una serie di rettangoli identificabili tra due intervalli successivi,ossia

y(kTs) = Ts · u(kTs) + y((k − 1)Ts) (2.10)

o anchey(kTs) = Ts · u((k − 1)Ts) + y((k − 1)Ts) (2.11)

detto appunto metodo dei rettangoli. Questo metodo è chiaramente molto approssimato anche se l’errore com-messo è tanto più piccolo quanto più piccolo è il periodo Ts; ciò fa comprendere che questo metodo è moltocomodo per il controllo quando le potenze di calcolo a disposizione non sono molto elevate e/o i tempi di in-tegrazione sono stringenti. Una soluzione più brillante è il metodo dei trapezi il quale non fa altro che consi-derare rettilineo il tratto tra due istanti (di campionamento) successivi sommando quindi le aree dei vari trapeziidentificabili in ogni istante Ts

y(kTs) =Ts2

(u(kTs) + u((k − 1)Ts) + y((k − 1)Ts) (2.12)

Page 21: Dispensa PID

2.2. REGOLATORE DISCRETO 21

Concentrandosi ora su questa seconda soluzione è immediato formulare il problema in termini di sequenze

y∗(n) = Ts

2 (u∗(n) + u∗(n− 1)) + y∗(n− 1)equivalente a

y∗(n + 1) = Ts

2 (u∗(n + 1) + u∗(n)) + y∗(n)

Come già detto, è chiaro che questo metodo di calcolo è una approssimante del sistema tempo-continuo, quindicercando di utilizzare una formula che approssimi al meglio l’integrazione, si può formulare il problema come in2.5-b, ossia definendo un coefficiente a tale che

y∗(n + 1) = Ts ((1− a) u∗(n) + a · u∗(n + 1)) + y∗(kn) con a ∈ [0, 1]

da cui deriva la funzione di trasferimento dell’integratore che mette in relazione la formulazione tempo-continuacon quella digitale

1s→ Ts

a · z + (1− a)z − 1

e quindi la definizione della variabile s che permetterà di mappare le funzioni tempo-continue nelle corrispettivedigitali:

s =1Ts

z − 1a · z + (1− a)

Dal fatto che la trasformazione sia bilineare deriva una importante considerazione ossia che se la funzioneR(s) è una funzione razionale fisicamente realizzabile (cioè il grado del polinomio a denominatore è maggiore ouguale al grado del numeratore) e senza poli in 1/(aTs) , allora R(z) è razionale con denominatore di grado paria quello di R(s) e maggiore o uguale al grado del numeratore.

A questo punto risulta chiaro che il regolatore digitale possa essere ottenuto sostituendo a s la variabiledefinita in z. Il problema ora è valutare i valori che a può assumere; tipicamente i valori assegnabili sono tre:

a = 0 equivale ad adottare come metodo di integrazione la formula di Eulero detta “in avanti” o “delrettangolo destro”. La funzione di mappatura del piano s diventa quindi

s =1Ts

(z − 1) (2.13)

e sostituendola alla funzione di trasferimento dell’integrale si ottiene

y = uTs

z − 1da cui yz = Tsu− y

e dividendo tutto per z si ottiene

y = Tsuz−1 − yz−1 da cui y∗(n) = Tsu∗(n− 1) + y∗(n− 1)

ossia la stessa relazione definita precedentemente (equazione 2.11).

a = 1 equivale ad adottare come metodo di integrazione la formula di Eulero detta “in indietro” o “delrettangolo sinistro”. La funzione di mappatura del piano s diventa quindi

s =1Ts

z − 1z

(2.14)

Page 22: Dispensa PID

22 CAPITOLO 2. PROGETTO DI UN REGOLATORE PI

ed effettuando le stesse considerazioni del punto precedente si ottiene

y = Tsu− yz−1 da cui y∗(n) = Tsu∗(n) + y∗(n− 1)

ossia la stessa relazione definita precedentemente (equazione 2.10).

a = 12 ossia il metodo di integrazione detto di Tustin o dei “trapezi”. La variabile s si definisce come

s =2Ts

z − 1z + 1

(2.15)

da cui deriva il metodo di integrazione dei trapezi definito in precedenza osservando semplicementei campioni del segnale:

y =Ts2

u(1 + z−1

)+ yz−1 da cui y∗(n) =

Ts2

(u∗(n) + u∗(n− 1)) + y∗(n− 1)

2.2.3 Risposta in frequenza

Per diagrammare la risposta in frequenza di una funzione z, non si può considerare tutto il semipiano dellefrequenze come per il diagramma di Bode per i sistemi tempo-continui; le funzioni in z infatti sono funzioniperiodiche nell’intervallo [− π

Ts, πTs

]. Tuttavia è possibile ottenerne la risposta sostituendo alla variabile z laforma polare ejωTs . Si intuisce però che le trasformazioni bilineari, non essendo trasformazioni lineari, tendonoa distorcere la risposta in frequenza della funzione in z rispetto a quella della funzione tempo-continua in s (siveda [2] per maggiori informazioni).

Dal punto di vista teorico è quindi possibile determinare il minimo valore di frequenza oltre il quale la di-storsione è trascurabile, ma dal punto di vista pratico ciò non è molto significativo in quanto le frequenze dicampionamento sono normalmente molto elevate e comunque dipendenti anche dall’hardware a disposizione. Atitolo di esempio si consideri ora un regolatore con Ki=10 e Kp=0.01 e tempo di campionamento di 1kHz (ossiaTs = 1ms); eseguendo i seguenti comandi MATLAB si ottengono i risultati in figura 2.6. La frequenza a cui èlimitata la funzione in z è chiaramente 1kHz (T−1

s ) che in termini di pulsazione è 3141.6 rad/sec; a questo puntoè facile intuire che se il tempo di campionamento aumenta, anche la distorsione si riduce (figura 2.7); è lecitoquindi aspettarsi che il sistema tempo-discreto risponda in modo pressoché identico al sistema tempo-continuo apatto che le frequenze di campionamento siano molto alte.

Page 23: Dispensa PID

2.2. REGOLATORE DISCRETO 23

Ki=10; Kp=0.01; Ts=1e-3;filtroS = tf([Kp Ki],[1 0]);filtroZ = tf([Ts*Ki/2+Kp Ki*Ts/2-Kp],[1 -1],Ts,’variable’,’z’);bode(filtroS, filtroZ);

Figura 2.6: Diagramma di Bode della funzione del regolatore di esempio s e z con Ts = 1ms.

Figura 2.7: Diagramma di Bode della funzione del regolatore di esempio s e z con Ts = 100µs.

Page 24: Dispensa PID

24 CAPITOLO 2. PROGETTO DI UN REGOLATORE PI

Page 25: Dispensa PID

Capitolo 3

Modellistica del regolatore PI

In questo capitolo verrà modellizzato il regolatore nella forma classica e con anti wind-up. L’obiettivo è diottenere tre regolatori (continuo, discreto e digitale) che restituiscano gli stessi risultati in termini di prestazionidinamiche e precisione statica. Il sistema preso in considerazione è un induttore R-L lineare la cui equazione distato è

d

dti(t) =

1L

(v(t)−Ri(t)) (3.1)

Si consideri a titolo di esempio per le simulazioni successive L = 50 mH e R = 0.11 Ω. La primaformulazione del regolatore sarà quella classica senza strutture anti wind-up.

Si consideri inizialmente un sistema come quello riportato in figura 3.1. Come si nota la relazione è banal-mente un guadagno che moltiplicato per l’ingresso restituisce il valore della tensione applicabile. É chiaro chequesto presuppone una perfetta conoscenza del modello del dispositivo sotto controllo e comunque anche in que-sto caso questa soluzione ha una dinamica legata ai poli dell’induttore. Questo schema permetterà di confrontarei risultati che seguiranno per verificare i miglioramenti apportati da un regolatore PI.

(a) Schema Simulink

(b) Tensione applicata (c) Corrente di riferimento e reale

Figura 3.1: Schema in anello aperto per il controllo della corrente in un induttore.

25

Page 26: Dispensa PID

26 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

3.1 Regolatore tempo-continuo classico

Il sistema in esame è un sistema intrinsecamente stabile. Introdurre un PI quindi in linea teorica non farà altroche modificare la dinamica del sistema. In particolare quello che si vuole fare è accelerare il sistema in esame.Per fare ciò si ipotizza inizialmente che l’attuatore (ossia in questo caso il generatore di tensione) sia ideale,cioè non abbia una uscita teoricamente illimitata; inoltre non deve introdurre nessun ritardo addizionale1, cosìcome il regolatore. Si applichino quindi le considerazioni fatte al paragrafo 2.1. Solo a scopo didattico la bandapassante non verrà posta intorno ai 1000 rad/s, ma pari a 50 rad/s: si ricorda infatti che l’obiettivo è realizzaretre regolatori (tempo-continuo, tempo-discreto e infine C) che abbiano la stessa risposta; lo scopo principaleè infatti quello di mostrare semplicemente che il regolatore migliora l’andamento della corrente. Da ciò perònasce anche una considerazione di tipo pratico: la tensione imposta (almeno in termini di picco) dal regolatoreha un valore tanto più alto quanto più alta è la banda passante. Ciò è abbastanza intuitivo: più il regolatoreè prestante, maggiore sarà la forzante che genererà in ingresso al sistema sotto controllo, chiaramente entro ilimiti dell’alimentatore. Problematiche di questo tipo rientrano nell’ambito della così detta moderazione del

controllo; il caso limite è quello in cui a fronte del più piccolo errore si ha la massima variazione dell’uscita,ossia il raggiungimento istantaneo della soglia di saturazione (superiore o inferiore). Tornando al caso in esame,la pulsazione scelta permette di avere, a fronte di un errore massimo, una tensione massima di poco superiorea 120V. Nel caso in cui il regolatore possa dare tensioni di riferimento in uscita più elevate di quelle gestibilidell’attuatore, si deve necessariamente prevedere una saturazione. Per quanto riguarda il margine di fase, vieneimpostato a 90.

In figura 3.2 è riportato il PI con coefficienti pari a Kp = 2.5 e Ki = 5.5. Come si nota non vi è sovra-elongazione e il sistema risponde più prontamente anche se la tensione applicata è ora molto più alta, quantomenocome valore di picco.

Per quanto riguarda la risposta in frequenza, in fgura 3.3 è rappresentata la risposta del regolatore PI, delcircuito R-L (G(s)), della funzione d’anello (L(s) = PI(s) ·G(s)) e della funzione di trasferimento totale, ossiacon F (s) = L(s)/(1 + L(s)) la quale ha un andamento di tipo passa-basso. Come si può notare la funzioned’anello è una retta di pendenza 20dB/dec e ciò è corretto perché avendo impostato il margine di fase a 90 il PIassume valori tali da avere uno zero in corrispondenza del polo della funzione in esame G(s). Il sistema L(s) siriduce semplicemente ad un integrale moltiplicato per un guadagno.

Applicando come riferimento una sinusoide di pulsazione 10rad/s e una di 100rad/s si deve trovare la primainseguita con un leggero ritardo e poco attenuata in modulo, mentre la seconda attenuata e con sfasamento intornoai 70. Ciò è verificato dalla figura 3.4.

1I regolatori reali infatti possono introdurre ritardi legati ai filtri dei segnali, al campionamento, al tempo di elaborazione, ecc.

Page 27: Dispensa PID

3.1. REGOLATORE TEMPO-CONTINUO CLASSICO 27

(a) Schema Simulink

(b) Correnti (c) Tensioni applicate

I colori sono, rispettivamente per ogni componente del vettore in ingresso al blocco scope, giallo-porpora-azzurro.Il riferimento di corrente è stato messo per ultimo per avere corrispondenza tra i colori relativi a ogni regolatore.I diagrammi sono ottenuti dal modello R_L_01.mdl.

Figura 3.2: PI tempo-continuo.

Page 28: Dispensa PID

28 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

Figura 3.3: Diagramma di Bode dei vari blocchi del sistema tempo-continuo.

(a) Corrente (riferimento a 10rad/s) (b) Tensione (riferimento 10rad/s)

(c) Corrente (riferimento 100rad/s) (d) Tensione (riferimento 100rad/s)

Figura 3.4: PI tempo-continuo con ingresso sinusoidale.

Page 29: Dispensa PID

3.2. REGOLATORE Z OTTENUTO DAL TEMPO-CONTINUO CLASSICO 29

3.2 Regolatore Z ottenuto dal tempo-continuo classico

Anche in questo caso si applicano le considerazioni precedentemente fatte nella sezione 2.2.2. Si ricorda chela trasformata Z discretizza solo il tempo, mentre l’ingresso è reale. Conseguenza di ciò è il fatto che neppureSIMULINK accetta come ingresso ai blocchi in z-trasformata variabili intere (a 16 o 32 bit) se non opportunamentecastizzate.

La funzione di trasferimento del PI è

Vrif (s)E(s)

= Kp +Ki

s=

sKp + Ki

s(3.2)

e applicando la trasformazione bilineare di Tustin si ottiene la funzione di trasferimento del regolatore discreto,ossia

vrif (z)e(z)

= Kp + KiTs (z + 1)2 (z − 1)

=KP (z − 1) + Ki

Ts

2 (z + 1)(z − 1)

= (3.3)

=

(Ki

Ts

2 + Kp

)z +

(Ki

Ts

2 −Kp

)z − 1

(3.4)

Introducendo questo nel modello Simulink si hanno i risultati mostrati in figura 3.5. Si noti che per effettuarela simulazione occorre cambiare le impostazioni settando i parametri di simulazione con passo fisso. In partico-lare è stato fissato un passo di integrazione pari a 50µs. In figura 3.5-a e 3.5-b si osserva che sia la corrente inuscita che la tensione dovuta al regolatore digitale e a quello analogico, si sovrappongono perfettamente.

Page 30: Dispensa PID

30 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

(a) Schema simulink

(b) Corrente. (c) Tensione applicata.

I colori sono, rispettivamente per ogni componente del vettore in ingresso al blocco scope, giallo-porpora-azzurro-rosso.

Figura 3.5: PI tempo-discreto con Ts = 50µs.

In realtà se si ingrandisse notevolmente si noterebbe un piccolo scostamento della funzione discreta rispettoa quella continua. Se alzassimo il valore del passo di integrazione (per esempio a 50ms), questo scostamento sifarebbe più marcato, come mostrato in figura 3.6. Si nota che la risposta è cambiata e sembrerebbe in meglio,ma questo leggero miglioramento lo si è “pagato” in termini di moderazione del controllo. Inoltre il sistema ètendenzialmente più instabile; infatti se si aumentasse oltre una certa soglia il passo di integrazione, il sistemadivergerebbe e, comunque, un aumento del passo di integrazione riduce la prontezza del regolatore. Ad ognimodo il sistema non si è discostato molto dalla risposta che ci si attendeva partendo dal progetto del regolatoretempo-continuo.

Anche in questo caso a fronte di un andamento sinusoidale il riferimento viene seguito con la stessa dinamicacome mostrato in figura 3.7-a. Anche la risposta a 5ms non presenta sensibili variazioni (3.7-b)

NOTA: a queste considerazioni si può giungere anche in termini matematici. Se infatti si osservano i risultaticon uno sguardo al futuro ponendo l’attenzione su come si comporterà il regolatore digitale, diventa chiarofin d’ora che il sistema digitale dovrà effettuare un campionamento e un controllo prima di restituire i

Page 31: Dispensa PID

3.3. REGOLATORE DIGITALE 31

(a) Correnti. (b) Tensioni applicate.

Figura 3.6: Risposta del PI continuo e discreto con Ts = 5ms.

(a) Ts=50us (b) Ts=5ms

Figura 3.7: PI tempo-discreto con riferimento sinusoidale.

risultati e quindi agire sul sistema. Di questo ritardo normalmente se ne deve tenere conto con un tempodi campionamento e uno di elaborazione. Tipicamente però si assume che questi due tempi siano pariall’intervallo Ts in quanto tra un campionamento e l’altro si cercherà di effettuare tutti i calcoli necessari alcontrollo. Si tiene conto di tale ritardo normalmente nella parte tempo-continua del modello definendolocome esTs . É immediato capire che in termini di margine di fase si ha una riduzione pari a

δφm = −ωcTs2

il che equivale a rendere meno robusto il sistema. Ad ogni modo non se ne terrà conto in questi primimodelli.

3.3 Regolatore Digitale

Il modello del regolatore digitale verrà anch’esso sviluppato in SIMULINK, ma ora ci si trova a dover analizzaresu quale struttura hardware il sistema dovrà essere implementato e ciò va oltre alla sola scelta del processore, ma

Page 32: Dispensa PID

32 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

riguarda anche i sensori (e quindi la loro caratterizzazione) e gli attuatori.

La famiglia di processori per la quale verrà plasmato il codice è la dsPIC30F. La scelta del processore è inlinea teorica scorrelata dal codice SIMULINK tranne per alcuni fattori:

1. si deve sempre verificare che il codice SIMULINK reimplementato sul processore scelto rispetti perfetta-mente le scadenze temporali, soprattutto se stringenti (hard real-time)

2. soglie e variabili in SIMULINK vanno espresse tenendo conto dei limiti di calcolo del processore. IdsPIC30F, per esempio, hanno parole a 16bit con ALU, MCU per calcoli come moltiplicazioni e divi-sioni e anche una DSP unit che, anche se non performanti come un vero DSP, permette di eseguire calcolidi somma e moltiplicazione contemporaneamente (multiply and accumulate), mente i PIC12/16 hanno solola ALU (Arithmetic/Logic Unit).

3. occorre riadattare gli ingressi per simulare la perdita di precisione legata ad ADC, PWM (e altre periferichese necessario). Gli ADC sono a 10bit.

Il secondo punto fondamentale è il sensore; prendendo in esame un sensore LEM di corrente e valutando laportata massima da rilevare si sceglie il modello. La caratteristica dei LEM è espressa in figura 3.8.

Vout = 2.5 + 0.625IPmaxIPN

dove IPmax è la corrente passante per ilnumero di spire avvolte.Si noti che il LEM satura a 4.5V

Figura 3.8: Caratteristica LEM.

Dai grafici la corrente da retroazionare ha un valore massimo nominale pari a 50A. La scelta quindi ricadesul LEM LTS-25-NP con una spira. Questo implica che a fronte di una tensione massima in uscita dal sensore di4,5V, la corrente massima che può circolare nel conduttore è pari a 80A. Il LEM inoltre ha una tensione in uscitacon un offset di 2,5V.

Il terzo punto di cui occorre tener presente è l’uscita. Occorre infatti pensare alla tensione massima applicabilela quale sarebbe meglio fosse maggiore (o al più uguale) alla tensione di picco ottenuta dalle simulazioni. Persemplicità si supponga di avere a disposizione una sorgente di tensione continua di valore 150V. Il sistema diparzializzazione della tensione può quindi essere un chopper o un ponte ad H. Per completezza verrà consideratoun ponte ad H in quanto sarà possibile verificare le risposte in frequenza in quanto questo dispositivo permette diavere sul carico sia tensioni positive che negative2.

Da queste considerazioni si procede col modellizzare il regolatore Simulink e quello del micro processore.

2Questa affermazione acquisirà importanza nel momento in cui il codice verrà adattato al micro-controllore, sul quale occorrerà introdurrei registri di PWM ed effettuare i debiti riscalamenti delle grandezze.

Page 33: Dispensa PID

3.3. REGOLATORE DIGITALE 33

3.3.1 Modello C-SIMULINK

In questo esempio il sensore+convertitoreAD verranno sviluppati al di fuori del codice C in modo che il codicescritto sia il più vicino possibile a quello del micro processore. Per quanto appena detto occorre modellizzareprima di tutto il blocco sensore-ADC. Per fare ciò si considera la formula riportata in figura 3.8. Inoltre si sache la conversione digitale ad opera del micro processore ha una sensibilità di 5V/1024. Il blocco di conversioneeseguirà

Vdigit = round((

2.5 + 0.625i

IPN

)1024

5

)Si noti che sia il riferimento che il valore reale vengono campionati, mentre la loro differenza verrà calcolataall’interno del codice C.

Detto ciò, in figura 3.9 è riportato il componente aggiuntivo a cui si farà riferimento per il test del codicedel regolatore riportato in seguito. Come si nota il blocco di campionamento è stato posto al di fuori del bloccoche simula il micro controllore vero e proprio per fare in modo che il codice sia il più possibile simile a quellodel micro controllore. Anche il riferimento viene digitalizzato in questo caso e non implementato sul controllorevero e proprio. Ciò è verosimile se si pensasse di avere la possibilità di settare il riferimento dall’esterno. I dueAD riportati non fanno altro che convertire la corrente in un valore compreso tra 0-512 corrispondenti a 0-80A inquanto, come già detto, il LEM ha un offset di 2.5V e il micro acquisisce ingressi in 0-5V.

Figura 3.9: Blocco PI digitale.

Il blocco “programma C” in figura 3.9 è un S-Function Builder. L’help di MATLAB è completo e spiegaperfettamente tutte le caratteristiche del blocco, ma per poter già scrivere e testare i programmi basti ricordareche:

1. Nella scheda “Initialization”, “Sample mode” deve essere settato su “Discrete” con un passo di 50e-6 (paria Ts). Si sconsiglia di fare ereditare al blocco il tempo di sample impostato in simulazione, anche se questafosse configurata (come deve essere) con un passo di integrazione fisso.

2. Nella Scheda “Data Properties” l’ingresso u0 è un vettore di due elementi, così come l’uscita y0.

3. In “Libraries” nel riquadro “External Function Declaration” verranno settate costanti e variabili globali.

4. In “Outputs” verrà scritto il codice.

Si noti inoltre che la base scelta per i calcoli è 4096 (12bit).

Il resto dell’hardware non è modellizzato per il momento. Si tenga però conto che il regolatore dovrà andarea pilotare delle valvole (per esempio un ponte H) e, in generale, il pic introdurrà dei ritardi. Tutto ciò verrà tenutoin considerazione più avanti.

Page 34: Dispensa PID

34 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

3.3.1.1 Metodo 1: Separazione parte proporzionale e integrale

Il regolatore può essere scritto tranquillamente separando il termine proporzionale e quello integrale secondoquanto riportato nell’equazione 2.12. Secondo molti, compreso chi scrive, questo metodo è molto comodo per lascrittura di un PI perché evitando di mettere in relazione il termine proporzionale e quello integrale, diventa moltopiù agevole modificare i parametri per affinare il controllo in fase di test e collaudo “sul campo” del regolatorestesso.

Algorithm 1 Variabili e definizioni globali.#define I_REALE u0[1]

#define I_RIF u0[0]

#define IUP 8400000

#define IDW -8400000

#define KP(e)((e<<1)+(e>>1))

#define KI(e)((e>>1)+(e>>4))

#define KIS 12 // extra shift per lítergale

int error, error_1=0;

int proporzionale;

int integrale=0;

int first_scan=0;

Algorithm 2 Codice C del regolatore (SIMULINK)int error_i;

error = ((I_RIF - I_REALE)<<3); /* errore riportato a 12bit */

error_i=error+error_1; /*errore da passare alla macro integrale*/

proporzionale = KP(error)

if(error_i>=0) /* calcolo integrale */

integrale += KI(error_i);

else

integrale -= KI((-error_i));

error_1=error; /* memorizzo l’errore per il passo successivo */

/*Ciò che segue è la satrazione dell’integrale, ossia l’anti wind-up. Introdurre ciò a questo punto

è solo per completezza; ai fini dell’esempio è ininfluente in quanto l’anti wind-up verrà trattato in

seguito*/

if(integrale>IUP) /* Limito l’integrale (anti wind-up) */

integrale=IUP;

else if(integrale<IDW)

integrale=IDW;

y0[0]=proporzionale+(integrale>>KIS);

y0[1]=round(y0[0]*100)/4096;

Analizzando il programma si vede che subito i dati in ingresso vanno riportati alla base scelta ossia moltiplica-ti per 8 mediante uno shift logico a sinistra di 3 bit; successivamente viene calcolata la componente proporzionaledel regolatore la quale non viene limitata perché il prodotto dell’errore massimo per il termine proporzionale nonpotrà mai dare un overflow della variabile intera a 16bit3: per comprendere meglio quanto appena detto si con-sideri che l’errore massimo teorico di corrente è pari a 511 (=29 − 1) che moltiplicato per 8 restituisce 4088che ancora moltiplicato per il coefficiente Kp pari a 2,5 dà come risultato 10220 <215 − 1=32767. L’integrale

315 bit se si considera anche il bit di segno.

Page 35: Dispensa PID

3.3. REGOLATORE DIGITALE 35

invece viene calcolato tramite la variabile error_i data dalla somma dei valori errore attuale (error) ed erroreal passo precedente (error_1); questo farà in modo che la macro sia ottimizzata perché, come detto al capitolo1, una macro tende a riscrivere il codice passatogli come parametro. Quindi la macro definita KI definita nell’al-goritmo 1 prendesse come argomento la somma dei due errori, tale operazione verrebbe richiamata tutte le voltache compare il simbolo e nella macro aumentando il carico computazionale. Oltre a ciò viene fatto un checksulla variabile error_i per evitare il problema legato agli shift logici a destra. Attenzione poi per quanto riguar-da la conversione dell’uscita: la conversione in tensione reale è data dalla costante 100/4096, ossia il reciprocodel coefficiente di conversione analogico-digitale del sensore di corrente. Attenzione quindi a non confondere ilvalore 100A con il massimo teorico della tensione in uscita dal generatore!

La dimostrazione di ciò è relativamente semplice e la si può fare per analogia. L’espressione seguente:

out_i(n) = e(n) ·Kp + KiTs2

(e(n) + (e(n− 1)) (3.5)

rappresenta il valore dell’uscita senza tenere conto del valore accumulato dall’integrale espressa con grandezzereali. Tale funzione è possibile riscriverla digitalizzando l’ingresso; come noto la costante di conversione del con-vertitore AD è 4096/100 da cui si può esprimere che il valore digitale della grandezza sarà E(n) = e(n) 4096

100 =e(n) · kAD. L’equazione 3.5 può quindi essere scritta in digitale come:

OUT_I(n) = E(n) ·Kp + KiTs2

(E(n) + (E(n− 1)) (3.6)

A questo punto non resta da chiedersi qual è il valore della costante che moltiplicata per il valore digitaledell’uscita restituisce il valore reale dell’ingresso:

k =out_i

OUT_I=

e(n) ·Kp + KiTs

2 (e(n) + (e(n− 1))E(n) ·Kp + Ki

Ts

2 (E(n) + (E(n− 1))=

e(n) ·Kp + KiTs

2 (e(n) + (e(n− 1))kAD

(e(n) ·Kp + Ki

Ts

2 (e(n) + (e(n− 1))) =

1kAD

Con questo è dimostrato che per ottenere l’uscita y0[0] reale occorre moltiplicare per il reciproco del fattore diconversione del convertitore analogico digitale.

Si noti che per essere precisi occorrerebbe limitare l’uscita alla tensione massima di DC bus: senza questalimitazione si assume l’alimentatore ideale e in grado di erogare qualsiasi valore di tensione e corrente.

Per quanto riguarda la regolazione vera e propria, i parametri Kp e Ki vengono realizzati tramite una macro. IlKP come si vede resta uguale e pari a 2.5, mentre KI tiene conto anche del tempi di campionamento (KI≡ Ki

Ts

2 ).Così facendo il nuovo coefficiente risulta 1.375·10−4 il quale è troppo piccolo per poter essere applicato ad unavariabile che al massimo raggiunge il valore 4096. Per questo la macro viene applicata ad una variabile a 32bit (int in MATLAB) e limitata a 224 (=212 · 212), mentre il coefficiente verrà moltiplicato per 4096 (il chediventa 0,5632). Ora l’integrale può tenere conto di tutti i valori maggiori o uguali di 2 perché 2·0,5632=1,1264che arrotondato all’intero più vicino è 1, aumentando decisamente la precisione. Mantenendo invece il valoredell’integrale pari a 1.375·10−4 la macro sarebbe stata scritta come KI(e)((e>>13)+(e>>16)) il che implicache perché il risultato di KI sia maggiore di 1, occorre che error_i sia almeno pari a 213. L’integrale peròviene utilizzato per calcolare grandezze in base 12 bit come y0[0] e quindi occorre riportarne il valore nella basecorretta applicando uno shift logico a destra di 12 bit.

La risposta è seguita perfettamente, come mostrato in figura 3.10.

Page 36: Dispensa PID

36 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

(a) Corrente. (b) Tensione

Figura 3.10: Risposta PI digitale (metodo 1).

Anche in questo caso la risposta alla sinusoide segue il comportamento voluto (figura 3.11 e 3.11), ma con unparticolare: infatti osservando le figure 3.11-b e 3.12-b si vede che la forzante appare un po’ frastagliata. I valoriperò sono accettabili come ordine di grandezza e andamento; questi andamenti discontinui sono da imputare allaquantizzazione del segnale in ingresso. E’ chiaro poi che la corrente in uscita abbia un comportamento buono acausa dell’effetto filtrante dell’induttanza.

(a) Corrente (b) Tensione

Figura 3.11: PI digitale con forzante sinusoidale a 10rad/s.

Page 37: Dispensa PID

3.3. REGOLATORE DIGITALE 37

(a) Corrente (b) Tensione

Figura 3.12: PI digitale con forzante sinusoidale a 100rad/s.

3.3.1.2 Metodo 2: Rielaborazione del PI ottenuto dalle funzioni z

Esaminiamo ora un altro modo per ottenere il regolatore PI digitale. Considerando l’equazione 3.3, ne deriva che

(z − 1) vrif =(

KP (z − 1) + KiTs2

(z + 1))

e

e dividento tutto per z e facendo gli opportuni passaggi, si ottiene

vrif =(Kp

(1− z−1

)−Ki

Ts

2

(1 + z−1

))e + z−1vrif

da cuiv∗rif (n) =

(Ki

Ts

2 + Kp

)e(n) +

(Ki

Ts

2 −Kp

)e(n− 1) + v∗rif (n− 1)

e sostituendo K1 = KiTs

2 + Kp e K2 = KiTs

2 −Kp si ottiene una relazione seguente:

v∗rif (n) = K1e(n) + K2e(n− 1) + v∗rif (n− 1)

Prima di scrivere il codice si osservi che il valore assunto dalle due costanti K1 e K2 , per i valori Kp e Ki

precedentemente calcolati e per il tempo di campionamento Ts, è

K1 =∣∣∣∣5.5 · 50 · 10−6

2+ 2.5

∣∣∣∣ = 2.5001375 K2 =∣∣∣∣5.5 · 50 · 10−6

2− 2.5

∣∣∣∣ = 2.4998625

ed è subito chiaro che l’integrale causa una variazione praticamente trascurabile ai due valori i quali risultanoin modulo pressoché identici. Questa affermazione è tanto più vera se ora si procede con la digitalizzazione.Consideriamo subito di creare le macro che con opportuni shift logici realizzino i due numeri K1 e K2. Perraggiungere questo grado di precisione, le due macro diventano

K1(e) ((e1)+(e1))

K2(e) ((e1)+(e2)+(e3)+(e4)+(e5)+(e6)+(e7)+(e8)+(e9)+(e10)+(e11))

L’ultimo shift è pari a 11 perché e, ossia l’errore in ingresso alle due macro, è una variabile in base 12bit e shiftare di 12 darebbe sicuramente contributo nullo. É chiaro che macro come K2 sono da evitare, siaperché il carico computazionale diventa tale da annullare (o ridurre) i benefici derivati dall’introduzione degli

Page 38: Dispensa PID

38 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

shift, sia perché ciò implica che un numero (e) deve valere almeno 212 perché esso venga valutato in modoutile dall’ultimo shift. Tale valore difficilmente verrà raggiunto se si presuppone un corretto funzionamento delsistema di regolazione. Discorso analogo vale per gli altri shift con numero di bit almeno pari a 9. Come se nonbastasse la macro K1 è chiaramente troncata in quanto il contributo del termine Ki

Ts

2 è troppo piccolo. Da questeconsiderazioni è lecito pensare che il sistema non avrà una risposta fedele a quella ottenuta studiando il sistemain s, in z o semplicemente in 3.3.1.1 come dimostrato dalla figura 3.13-a.

Per eliminare i problemi appena esposti riguardanti il calcolo, si potrebbe pensare di approssimare il valore diK1 e K2 al valore 0.5 (ossia (e1)) il che comporterebbe un errore trascurabile dal punto di vista del calcolo delcoefficiente, ma ciò comporterebbe l’annullamento del coefficiente integrale che, anche se piccolo, è fondamen-tale per avere precisione statica. La figura 3.13-b mostra l’effetto legato a questa approssimazione. É chiaro che sipotrebbe agire per tentativi per ridurre l’errore a regime aumentando il coefficiente proporzionale oppure quellointegrale, ma in entrambi i casi il sistema non avrebbe più la risposta ottenuta dal progetto nel tempo continuo.

(a) Approssimazioni di K1 e K2 (b) Annullamento Ki

RiferimentoRisposta libera del sistema

Sistema tempo-continuoSistema tempo-discreto

Sistema digitale

Grafici ottenuti dalla simulazione R_L_04.mdl.

Figura 3.13: Corrente con PI digitale a variabili discrete ossia int (metodo2).

Detto questo, potrebbe sembrare che se il sistema lavorasse con grandezze a più alta precisione (float o double)questo problema potrebbe essere attenuato. Ciò tendenzialmente è vero come mostrato anche in figura 3.14,ma va sempre verificato onde evitare di scegliere processori con potenze di calcolo (e quindi costo) eccessivi.In figura 3.14-b è riportato l’andamento della tensione che come si vede è a gradini in quanto l’elaborazioneviene comunque fatta su un segnale digitale intero proveniente dal convertitore AD. Va comunque notato che leoperazioni compiute sono di moltiplicazione e accumulazione, operazioni che normalmente vengono eseguite damolti processori (anche a basso costo) con tempi di elaborazione non troppo elevati come per esempio i processoridsPIC30F o gli ADuC7000.

Page 39: Dispensa PID

3.3. REGOLATORE DIGITALE 39

(a) Elaborazione in double di ingressi e regolazione (b) Particolera della tensione impostata dal regolatore.

RiferimentoRisposta libera del sistema

Sistema tempo-continuoSistema tempo-discreto

Sistema digitale

Grafici ottenuti dalla simulazione R_L_04.mdl.

Figura 3.14: Corrente con PI digitale a variabili in doppia precisione double (metodo2).

Il codice che permette di ottenere queste risposte è riportato negli algoritmi 3 e 4. Si noti che l’algoritmo 4può sembrare più corto e veloce del precedente algoritmo 3. In realtà ciò è normalmente falso soprattutto permicro-controllori a basso costo in quanto le operazioni sviluppate sono tutte in virgola mobile e quindi possonorichiedere molti cicli di clock.

Algorithm 3 Codice C del regolatore a variabili discrete./***** DEFINIZIONI E VAR GLOBALI *****/

#define I_REALE u0[1]#define I_RIF u0[0]#define IUP 8095 /*occorre aumentare la soglia x avere la stessa risposta*/#define IDW -IUP#define K2(e)((e<<1)+(e>>2)+(e>>3)+(e>>4)+(e>>5)+(e>>6)+(e>>7)+(e>>8)+(e>>9)+(e>>10)+(e>>11))#define K1(e)((e<<1)+(e>>1))int error, error_1=0;int out=0;

/*************************************/

/***** PROGRAMMA *****/

int k1, k2;

error = ((I_RIF - I_REALE)*8);

if(error>=0) k1=K1(error);else k1=-(K1((-error)));if(error_1>=0) k2=K2(error_1);

else k2=-(K2((-error_1)));

out = +out + k1 - k2;error_1=error;if (out>IUP) out=IUP;

else if(out<IDW) out=IDW;

y0[0]=out;y0[1]=round((out)*100)/4096;

/*********************/

Page 40: Dispensa PID

40 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

Algorithm 4 Codice C del regolatore a variabili double./***** DEFINIZIONI E VAR GLOBALI *****/

#define I_REALE u0[1]#define I_RIF u0[0]#define IUP 8095 /* occorre aumentare la soglia */#define IDW -IUP#define K2(e)((e*2.4998625))#define K1(e)((e*2.5001375))int error, error_1=0;double out=0;

/*************************************/

/***** PROGRAMMA *****/

error = ((I_RIF - I_REALE)*8);out = out + K1(error) - K2(error_1);

error_1=error;

if (out>IUP) out=IUP;

else if(out<IDW) out=IDW;

y0[0]=error;y0[1]=(out*100)/4096;

/*********************/

3.3.1.3 Metodo 3: Rielaborazione del PI ottenuto dalla configurazione anti wind-up

Si consideri la figura 2.2. Il sistema così sviluppato serve semplicemente per evitare l’anti wind-up negli schemitempo-continui. Nonostante ciò è possibile definire il regolatore in z e successivamente il regolatore digitale.

Si consideri quindi il blocco della fase integrale (che d’ora in poi verrà indicato con RI )

RI(s) =1

1 + sKi

Kp

riportato nel dominio z applicando il metodo di Tustin

RI(z) =1

1 + 2Ts

z−1z+1

Kp

Ki

= (1− b)12z + 1

2

z − b

doveb = 1− KiTs

12KiTs + Kp

Introducendo i parametri

g =12(1− b) e h =

(1− 1

2(1− b)

)(1− b)

si ottieneRI(z) = g +

h

z − b

Il regolatore quindi può essere rappresentato come in figura 3.15.

Page 41: Dispensa PID

3.3. REGOLATORE DIGITALE 41

Figura 3.15: Ridefinizione del PI con anti wind-up analogico discretizzato con bilineare di Tustin.

Proseguendo si osserva che il blocco g può essere eliminato ponendo un blocco equivalente prima dellasaturazione come mostrato in figura 3.16-a. Successivamente si sposta il blocco 1

1−g prima del nodo sommatore(figura 3.16-b). Considerando quindi che 1− b = h

1−g e introducendo Γ = 12TsKi + Kp si ottiene lo schema in

figura 3.16-c ossia il regolatore in z.

(a) Sostituzione di g con la relativa funzione d’anello

(b) Spostamento del blocco 1/(1-g)

(c) Schema finale del PI discretizzato

Figura 3.16: Riborazioni dello schema 3.15.

Dallo schema riportato in figura 3.16-c è possibile ottenere il regolatore digitale da implementare poi inSIMULINK. Osservando il blocco in retroazione all’anello si può scrivere

xr(z) =1− b

z − bu(z) da cui xr(z)− bz−1 = (1− b)z−1u(z)

Page 42: Dispensa PID

42 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

Ne consegue quindi la formulazione discreta

xr(n) = bxr(n− 1) + (1− b)u(n− 1) (3.7)

Chiaramente l’uscita è definita comeu(n) = xr(n) + Γe(n) (3.8)

la quale poi dovrà essere limitata (saturata).

In figura 3.17 sono riportati i due sottosistemi SIMULINK (file R_L_05.mdl) che realizzano il regolatoretempo-continuo e tempo-discreto in un modello simile a quello della figura 3.5.

(a) PI anti wind-up tempo-continuo (b) PI anti wind-up tempo-discreto.

Figura 3.17: Schemi dei sottosistemi tempo-continuo e tempo-discreto.

Avendo già analizzato il comportamento dei regolatori senza anti wind-up, verrà ora abilitata la soglia chefarà in modo che la tensione in uscita non superi, per esempio, 80V. In figura 3.18 sono riportati gli andamenti dicorrente e tensione nel caso in cui la soglia sia attivata o disattivata. Come si nota la tensione tende a ridurre leprestazioni dinamiche, anche se la precisione statica non è alterata.

(a) Tensione (b) Corrente.

Grandezza non limitata Grandezza limitata

Figura 3.18: PI con e senza anti wind-up.

Basandosi sulle equazioni 3.7 e 3.8 e sostituendo i valori dei coefficienti del regolatore si ottiene

b = 0.99989 1− b = 1.0999 · 10−4 Γ = 2.5001375

Page 43: Dispensa PID

3.3. REGOLATORE DIGITALE 43

Approssimando i coefficienti come segue

b = 1 1− b = 0 Γ = 2.5

sembra che non si commetta un grande errore. Ne deriva il codice riportato nell’algoritmo 5.

Algorithm 5 PI anti wind-up: Codice C SIMULINK./*** MACRO E VARIABILI GLOBALI ***/#define I_REALE u0[1]#define I_RIF u0[0]#define IUP 3277 /* 80/100*4096 */#define IDW 0#define B 1 /* 0.99999*/#define B_1 0 /* 1-B=0.00001 */#define GAMMA(e)((e<<1)+(e>>2)) /* 2.5001 */int error, error_1=0;int xr=0, out=0;/************************************//*** PROGRAMMA ***/error=((I_RIF)-(I_REALE))<<3;

xr=B*xr+B_1*out;if(xr>IUP) xr=IUP;else if(xr<IDW) xr=IDW;

out=xr+(GAMMA(error));if(out>IUP) out=IUP;else if(out<IDW) out=IDW;

y0[0]=out;y0[1]=round(out*100)/4096;/*************************************/

Ne derivano quindi i risultati in figura 3.19. Come si nota vi è un errore statico a regime, il che era prevedibileperché osservando il codice si nota che il termine integrale è tenuto in conto dal parametro “1 − b” il quale inquesto caso è nullo. L’unico modo per avere una risposta uguale a quella in fase di progetto è utilizzare variabiliad alta precisione come float, double o comunque intere ad almeno 32 bit come long int4.

(a) Corrente (b) Tensione

Figura 3.19: Risposta PI digitale relativa all’algoritmo 5.

4Si ricorda che per MATLAB le variabili definite int hanno la stessa dimensione dei long int in quanto il compilatore è quello didefault del sistema ossia il gcc (per Linux) il quale assegna la “parola” a 32 bit. Nei PIC, dsPIC e altri microcontrollori da 8 a 16 bit, intequivale a 16 bit, mentre long int a 32.

Page 44: Dispensa PID

44 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

Ridefinendo le variabili in base 24 bit per poi riportarle a 12 bit nel calcolo dell’uscita, si ottiene il codiceriportato nell’algoritmo 6. Da questo codice si ottengono i risultati riportati in figura 3.20. Si osservi subitouna cosa molto importante: dovendo lavorare con grandezze a 24 bit, l’unico parametro da dover far variare èil termine Γ (ottenuto con la macro GAMMA) il quale verrà moltiplicato per 4096; questo fa in modo che l’uscitaout24 sia a 24 bit. Per quanto riguarda il valore delle macro B e B1, non devono essere moltiplicati per 4096perché xr dipende da out24 che è già in base 24 bit; in altre parole xr “eredita” la base di out24. Infine out èottenuto dividendo per 4096 il valore di out24 (effettuato tramite shift di 12 bit).

Algorithm 6 PI anti wind-up con variabili a 32bit./*** MACRO E VARIABILI GLOBALI ***/#define B(e)((e)-(e>>13)) /* 0.99989*/#define B1(e)((e>>14)+(e>>15)+(e>>16)) /* (1-b)*/#define GAMMA(e)((e<<13)+(e<<11)+(e>>1)+(e>>4)) /* 2.5001*4096 */#define RDI 12int error, error_1=0;long int xr=0, out24=0, out=0;/************************************//*** PROGRAMMA ***/error=((I_RIF)-(I_REALE))<<3;if(xr>=0) xr=B(xr);else xr=-(B((-xr)));if(out>=0) xr+=B1(out24);else xr+=-(B1((-out24)));out24=xr+(GAMMA(error)); /* shift a SX, quindi non servono controlli */if(out24>IUP) out24=IUP; /* Calcolo di out24 */else if(out24<IDW) out24=IDW;out=out24>>RDI;y0[0]=out;y0[1]=round(out*100)/4096;

(a) Corrente (b) Tensione

Figura 3.20: Risposta PI digitale relativa all’algoritmo .6.

3.3.1.4 Osservazioni e Confronti

Premesso che la soluzione ottima non esiste e che ogni regolatore andrebbe analizzato per ogni specifica ap-plicazione, è comunque possibile trarre delle conclusioni. Il primo metodo (§3.3.1.1) realizza del codice ten-denzialmente molto voluminoso in quanto se vengono previsti degli shift logici (soprattutto se negativi) occorreeffettuare un controllo sulla variabile in ingresso ad ogni macro. La macro di integrazione, poi, deve essere gestitadefinendo una variabile di appoggio che occorre passargli per evitare che prima di ogni shif della macro venga

Page 45: Dispensa PID

3.3. REGOLATORE DIGITALE 45

calcolata continuamente la somma dell’errore al passo attuale e al passo precedente. Infine, per evitare il sovrac-carico dell’integrale, occorre limitare il valore dell’uscita e dell’integrale stesso5. Questo sistema ha però deigrandi vantaggi: permette infatti di modificare semplicemente i parametri del regolatore e le grandezze in esamepossono essere gestite a 16bit (a parte l’integrale che spesso va gestito con variabili a 32, anche se le operazionisvolte su di esso sono semplici somme o shift, ossia operazioni “leggere” in termini computazionali) generandoquindi del codice tendenzialmente molto veloce.

Il secondo metodo (§3.3.1.2) presenta fondamentalmente gli stessi inconvenienti del primo, con la differenzache tutte le grandezze vanno gestite (se necessario) con variabili maggiori di 16bit. Inoltre la modifica di uncoefficiente interviene su entrambi i coefficienti K1 e K2 rendendo più complessa l’affinazione dei parametri sulcampo.

Il terzo metodo (§3.3.1.3) è forse il più usato anche se, a detta di chi scrive, non è il migliore. É innegabile cheprogettare il regolatore tempo-continuo anti wind-up è una soluzione brillante e, dalla teoria sia dei controlli chedei filtri digitali, si è ereditato il fatto che se possibile si progetti il regolatore digitale partendo da quello tempocontinuo. Ma ciò obbliga a ricalcolare tutto per arrivare a un risultato non differente dal caso 3.3.1.2. Inoltrei coefficienti sono 3 appesantendo l’esecuzione del codice, soprattutto se venissero realizzati con degli shift.Inoltre i valori calcolati devono necessariamente avere grande precisione anche a livello digitale per avere unandamento il più fedele possibile al progetto. D’altro canto questo sistema ha il grande vantaggio di effettuare unasola saturazione sulla variabile di uscita; infatti limitando quest’ultima si ottiene automaticamente la saturazionedell’integrale (ossia l’anti wind-up) risparmiando una comparazione.

3.3.2 Simulazione del Duty-Cycle

Le simulazioni così progettate e implementate fino ad ora non tengono conto precisamente del duty-cycle. Infattil’uscita del sistema anche se deriva da valori digitali, ossia ha un andamento a gradini discreti, non simula ap-pieno il fatto che il duty-cycle è una grandezza digitale con un preciso valore indipendente dalla base scelta per iconti, funzione del clock del sistema e della frequenza di PWM che si vuole generare in uscita. Si consideri a talproposito un ponte ad H i cui gate vengono controllati con driver i quali ricevono un solo segnale in ingresso dalmicro-controllore (PWM), ma pilotando entrambe le valvole di un ramo (come si vedrà nella sezione 4.1) sempli-cemente negando il segnale destinato al gate della valvola bassa rispetto a quello della valvola alta. La frequenzadi PWM viene comandata con la variabile PDCx con x pari a 1 o 2 in funzione del ramo da controllare. Non cisi vuole addentrare ora nelle problematiche relative all’implementazione su micro processore, quindi si assumache una volta eseguiti i debiti calcoli indicati sul datasheet del processore, si ottenga che la variabile PDCx possaassumere per esempio valori compresi tra 0 e 736: essendo un ponte ad H si ha che quando PDC1=PDC2=368 latensione media sul carico è pari a 0. A questo punto occorre prevedere che il sistema reale abbia un massimo valo-re di tensione di DCbus, per esempio 150V. Ciò vorrà dire che la tensione sul carico varierà in modo “quantizzato”con una risoluzione legata a PDCx pari a 150V/368=0,476V/digit. Detto questo, prendendo in considerazione unodei metodi analizzati (per esempio il Metodo 1), nel programma di simulazione è quindi opportuno apportareuna modifica tale per cui venga calcolata la tensione vera (ossia si moltiplica l’uscita per 100/4096) e riportata alvalore digitale di duty-cycle moltiplicando la tensione vera per 368/150, si divide la tensione vera per il massimovalore di tensione ammissibile in uscita (ottenendo così il duty-cycle in per-unità) e quindi moltiplicando per ilmassimo valore digitale del duty-cycle accettato dal micro-controllore. Si ottiene quindi la seguente costante:

dc =1004096

368150

= 0, 0599

5In alcuni casi occorre anche limitare il proporzionale se molto alto.

Page 46: Dispensa PID

46 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

il che si traduce nella macro GET_DC indicata nel codice riportato di seguito:

#define I_REALE u0[0]#define I_RIF u0[1]#define VMAX 150#define VMAXD 6144#define DCMAX 368/*MACRO*/#define KP(e)((e<<1)+(e>>1))#define KI(e)((e>>1)+(e>>4))#define KIS 12#define GET_DC(v)((v>>5)+(v>>6)+(v>>7)+(v>>8)+(v>>10))short int error, error_1=0, proporzionale;int integrale=0;/********************************/short int error_i, out, dc;error = ((I_REALE - I_RIF)<<3);proporzionale = KP(error);error_i=error+error_1;if(error_i>=0)

integrale += KI(error_i);else

integrale -= KI((-error_i));error_1=error;out=proporzionale+(integrale>>KIS);if(out>VMAXD) out=VMAXD;

else if(out<-VMAXD) out=-VMAXD;if(out>=0) y0[0]=(GET_DC(out));else y0[0]=-(GET_DC((-out)));

y0[1]=y0[0]*VMAX/DCMAX; /* Grandezza reale *//**** Nel codice del micro ci sarà scritto circa quanto segue ***** PDC1=DCMAX+GET_DC(out);

* PDC2=DCMAX-GET_DC(out);

******************************************************************/

In questo caso il sistema deve necessariamente prevedere una saturazione dell’uscita6 perché non è possibile dareun valore negativo o troppo elevato della grandezza PDCx. Il valore massimo digitale dell’uscita è chiaramente ilvalore arrotondato all’intero minore di 150V/100*4096 ossia 6144. Questa volta l’uscita reale y0[1] è ottenutamoltiplicando per l’inverso della nuova scala cioè per 150/368. Per quanto riguarda il commento finale, per ilmomento non si entrerà nel merito in quanto verrà ripreso più approfonditamente nel capitolo 4 in fase di sviluppodel codice C per micro controllore.

I risultati ottenuti con il codice di cui sopra sono pressoché identici a quelli ottenuti nelle simulazioni pre-cedenti. Si nota comunque un “degrado” dell’informazione (tensione) in uscita come mostra il confronto tra lefigure 3.21-a e 3.21-b. Ciò si traduce nell’avere delle oscillazioni leggermente più marcate (ma sempre trascu-rabili come entità) nell’intorno del valore di corrente di regime a causa del fatto che la minima variazione dellatensione in uscita è aumentata (figura 3.22).

6Le saturazioni fino ad ora sono state trascurate per motivi puramente didattici. Di norma dovrebbero sempre essere previste.

Page 47: Dispensa PID

3.3. REGOLATORE DIGITALE 47

(a) Tensione i uscita senza l’introduzione del duty-cycle (b) Tensione in uscita senza introducendo il duty-cycle

Figura 3.21: Confronto tra tensioni in uscita dal regolatore.

(a) Tensione a regime senza considerare il duty-cycle. (b) Tensione a regime considerando il duty-cycle.

Figura 3.22: Confronto tra tensioni in uscita dal regolatore a regime.

3.3.3 Regolatore Digitale con metodo di integrazione “dei resti”

Il metodo di gestione dell’integrale utilizzato nella sezione 3.3 si basa sull’utilizzo di variabili a 32 bit e di macroche scompongono i coefficienti reali in potenze di due. Nel capitolo 1, però, è stato menzionato un secondometodo di gestione dell’integrale che si basa sulla gestione dei resti (a pagina 12). Per completezza ora si vuolerisolvere il medesimo problema con un metodo che tenga conto di un diverso sistema di integrazione basatoappunto sulla gestione dei resti per vedere le differenze anche dal punto di vista computazionale. L’algoritmo cheverrà presentato è quello relativo al Metodo 1 (§ 3.3.1.1). In questo caso però si considera il coefficiente integralepari a KI

Ts

2 = 1, 375 · 10−4 senza maggiorarlo di 4096. Rifacendosi all’implementazione vista nel capitolo 1riguardo la gestione dei resti, occorre definire due macro di integrazione come INTEGRALE_H e INTEGRALE_L.In questo caso il primo è chiaramente nullo, in quanto KI

Ts

2 è minore di 1, e il secondo deve tenere conto deidecimali. Detto ciò, per fare incrementare di una unità la variabile intH occorrerebbe che la variabile intL

raggiunga il valore 2 (KITs)−1 = 7272, 7: tutto ciò rende per tanto inutile anche la definizione della macro

Page 48: Dispensa PID

48 CAPITOLO 3. MODELLISTICA DEL REGOLATORE PI

INTEGRALE_L a causa del fatto che occorre valutare “tutta la somma” error+error_1 ossia senza effettuaremascheramenti e/o shift. Il codice proposto è il seguente:

#define I_REALE u0[0]#define I_RIF u0[1]#define INT_UNIT 7273 /* minimo valore corrispondente al superamento dell’unità*/#define KP(e)((e<<1)+(e>>1))short int error, error_1=0, proporzionale;short int intH=0, intL=0; /* short int in Simulink sono 16 bit *//---------------------------/short int out, dc;error = ((I_REALE - I_RIF)<<3);proporzionale = KP(error);intL += error+error_1;if(intL>=INT_UNIT)

intH++;intL-=INT_UNIT;

else if(intL<=-INT_UNIT)

intH--;intL+=INT_UNIT;

error_1=error;y0[0]=proporzionale+(intH);y0[1]=round(y0[0]*100)/4096;

Analizzando il codice si vede che le variabili sono tutte a 16 bit. intL non è altro che l’integrale dell’errore attualepiù il precedente; quando intL supera il valore di +7273, la variabile intH deve incrementarsi di una unità,mentre se intL è minore di -7273, allora intH si decrementerà. Nel momento in cui si calcolerà l’uscita y0[0],la variabile intH non viene più shiftata perché rappresenta già il valore corretto nella base scelta. I risultati sonoriportati in figura 48; la risposta è perfetta, senza sovra-elongazioni e con errore a regime trascurabile (figura48-b).

Il codice così scritto sembra più semplice e veloce di quelli scritti in precedenza e ciò è tendenzialmentevero, ma solo in questo caso. In generale infatti si potrebbero avere più operazioni per ottenere la variabile intH(per esempio nel caso in cui il coefficiente di integrazione sia maggiore di 1) il che comporta un aumento anchenotevole del carico computazionale. In altre parole ciò dimostra che non esiste una soluzione migliore o peggiore,ma tutte le strategie proposte andrebbero studiate e valutate in ogni specifico caso.

(a) Risposta al gradino (b) Dettaglio della risposta al gradino

Figura 3.23: Integrazione con il metodo dei resti.

Page 49: Dispensa PID

Capitolo 4

Implementazione di un regolatore PI

L’obiettivo è sviluppare un regolatore PI su micro-controllore affrontando le varie problematiche relative allescelte hardware e software.

4.1 Regolatore PI su processori dsPIC30F

Il processore che verrà utilizzato è il dsPIC30F4012. Il codice che verrà scritto, comunque, potrà essere tranquil-lamente usato su tutti gli altri dsPIC, salvo il fatto che devono esserci le stesse periferiche.

Hardware del sistema di controllo

Per prima cosa occorre conoscere il sistema che si vuole controllare e realizzarne il modello. Supponiamo persemplicità che il modello sia come quello trattato al capitolo 3, ossia un carico R-L e che si voglia tenere sottocontrollo la corrente in detto induttore. L’azionamento che ci permette di fare ciò può essere per esempio unponte ad H o più semplicemente un chopper. In questo esempio sceglieremo un ponte ad H in quanto richiedequalche accorgimento in più rispetto al chopper. Inoltre il ponte H permetterà di valutare la risposta in frequenzae di seguire riferimenti sinusoidali (o comunque riferimenti che possono essere anche negativi). Ad ogni modotutta la trattazione può essere portata semplicemente anche su un chopper.

Le potenze in gioco sull’azionamento sono normalmente molto più elevate rispetto a quelle dell’elettronicadi controllo la quale si dovrà interfacciare con le valvole1 del ponte H (o del chopper) con opportuni sistemi dettidriver i quali pur ricevendo un segnale normalmente in logica TTL a 0-5V riescono a generare un impulso dicorrete sul gate delle valvole tale da attivarle in un tempo ragionevolmente basso e portarle in conduzione. Latensione dei driver è spesso diversa sia da quella dell’elettronica che da quella del circuito di potenza (nel casoseguente 15V). Questa tensione è legata alla caratteristica di gate della valvola da controllare.

Infine vi è il micro controllore e i sensori i quali normalmente sono alla stessa tensione pari a 5V.

L’hardware scelto è quindi il seguente:

MDA 990 Ponte raddrizzatore a diodi (MOTOROLA). Dovrà essere alimentato da un variac monofase. Si vuoleraggiungere la tensione media a vuoto di 100V sul DC-bus.

1Per “valvole” si intendono dispositivi generici a semiconduttore che possono essere controllati come interruttori. In questo caso siassumono come valvole gli IGBT ossia dispositivi che permettono una rapida interruzione di valori anche molto elevati di corrente come leSKM100GB di SEMIKRON.

49

Page 50: Dispensa PID

50 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

SKM100GB IGBT SEMIKRON da 1200V 100A alla frequenza di commutazione di 10kHz ad una temperaturadi giunzione pari a 25C. Per come è stato pensato il circuito (anche in relazione al tipo di driver)occorre considerare un tempo morto tra la commutazione delle due valvole di uno stesso ramo noninferiore a 2,5µs 2. In figura 4.1 è riportato lo schema di un ponte H.

Figura 4.1: Ponte H.

IR21844 Driver International Rectifier che permette di generare impulsi di corrente in attivazione dell’ordinedi 1,4A. Inoltre è possibile agire sul tempo morto da dare alle valvole senza bisogno di agire viasoftware andando ad agire sulla resistenza connessa tra il pin DT e Vss. Lo schema in figura 4.2mostra la tipica connessione di questo driver il quale richiede un circuito di bootstrap. Il circuitoreale presenta anche dei diodi in parallelo alla resistenza posta tra il gate della valvola e il driver inmodo da poter avere un impulso di entità maggiore in fase di spegnimento. Questo tende a ridurremolto i tempi morti.

Figura 4.2: Tipica connessione del driver IR21844.

LTS25NP Sensore a effetto HALL le cui caratteristiche sono state descritte nella sezione 3.3.

Le figure 4.3-a e 4.3-b riportano la scheda realizzata (completa di ponte raddrizzatore e valvole) il cui schematicoè rappresentato in figura 4.4, utile per capire quali dispositivi sono collegati al microcontrollore e facilitare lalettura del programma. Chiaramente la scheda riportata ha molti altri dispositivi i quali non verranno esaminatiin questa sede.

2Valore ottenuto dalle prove sulla valvola interrompendo correnti di circa 30A a 20kHz

Page 51: Dispensa PID

4.1. REGOLATORE PI SU PROCESSORI DSPIC30F 51

(a) Ponte H

(b) Scheda di controllo

NOTA: i diodi e i pulsanti sono gestiti in logica inversa ossia 0 = ON, 1 = OFF.

Figura 4.3: Dispositivo realizzato.

Page 52: Dispensa PID

52 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

Figura 4.4: Schematico della scheda di controllo.

Page 53: Dispensa PID

4.1. REGOLATORE PI SU PROCESSORI DSPIC30F 53

Strategia di controllo

Per prima cosa si consideri il riferimento impostato direttamente all’interno del processore (quindi non da di-spositivi esterni ai quali il processore sia eventualmente interfacciato) pari a un valore costante. L’obiettivo è diottenere sul carico un valore di corrente costante pari al riferimento. Questo implica che il ripple deve essere ilpiù ridotto possibile. Per ottenere questo, il ponte H verrà controllato in modo che i due duty-cycle dei due ramidel ponte siano tali per cui δ1 = 1− δ2 come indicato in figura 4.5.

Figura 4.5: Controllo PWM con portante triangolare.

Ciò permette di avere sul carico una frequenza pari al doppio di quella di commutazione delle valvole.

Periferiche richieste

Le periferiche necessarie per effettuare il controllo di corrente sono:

PWM (Pulse Width Modulation) è l’impulso che attiva o disattiva le valvole e permette la regolazione dellatensione media sul carico.

ADC (Analog to Digital Converter) convertitore analogico-digitale per poter acquisire le grandezze.

PORTx (Porte) Porte I/O digitali (o analogiche se ingressi per ADC) per usi generali.

TIMERx (Temporizzatori) eventuali temporizzatori per gestire alcuni eventi. Non dovrebbero servire in questaprima applicazione.

Altre periferiche come Seriale UART, CAN, Output Compare, ecc non verranno analizzate, anche se possonoessere molto utili per prelevare informazioni dal micro-processore e quindi effettuarne il monitoraggio e il debug.

4.1.1 Sviluppo del regolatore in codice C

Il codice che si andrà a implementare è scritto in C orientato al compilatore C30 fornito da MICROCHIP.

Prima di procedere alla scrittura del codice occorre inizializzare le periferiche precedentemente elencate.Tutte le informazioni sulla famiglia dsPIC30F sono ottenibili dal manual family [4]. Si osservi infatti che ildatasheet del singolo processore è approssimativo e documenta esclusivamente il comportamento delle varie

Page 54: Dispensa PID

54 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

periferiche. Ciò che invece serve in questo momento è conoscere tutti i flags e registri che occorre settare perimpostare il corretto funzionamento delle periferiche integrate3.

Il programma verrà strutturato nei seguenti file:

global.h definisce le principali variabili e definizioni di costanti comuni a tutti i files.

init.h file di intestazione delle funzioni di inizializzazione. Contiene le dichiarazioni delle funzioni diInitPORT(), InitPWM(), InitADC() ed eventuali macro.

init.c file C di implementazione delle funzioni di inizializzazione.

pi.h file di intestazione contenente le dichiarazioni e macro necessarie per effettuare la routine di regola-zione.

main.c file C principale. Contiene la funzione main e le funzioni di interrupt.

Temporizzazioni e dead-line

Una fase molto importante è decidere le temporizzazioni e scadenze temporali. Ciò è fondamentale perché pergarantire il real-time occorre essere certi che le operazioni vengano eseguite correttamente e nei tempi stabiliti.Ora occorre scegliere la frequenza di commutazione delle valvole. Da datasheet la frequenza nominale è 10kHz,ma possono funzionare anche a frequenze molto più alte a patto che la corrente da interrompere sia inferiorealla nominale. Si sceglie una frequenza di 20kHz. Per essere precisi occorrerebbe valutare anche la frequenzaammissibile del driver, la quale normalmente è molto alta (nell’ordine dei 100kHz) e non costituisce un problema.

A questo punto occorrerebbe valutare quanto il sistema impiega per eseguire le operazioni basilari (shift,moltiplicazioni, somme, if..else, ecc). Si consideri in linea del tutto indicativa che un dsPIC30F con un quarzoda 7,37228 MHz difficilmente supera i 2,4µs/PLL4 per operazioni su variabili int a 16 bit. Questo permette distimare i tempi di calcolo.

Detto questo, dato il quarzo da 7,37228 MHz posto sulla scheda si sceglie di lavorare con un PLL di 8che porta la frequenza di clock a 58,9MHz (figura 4.6). Frequenze più alte fanno assorbire molta corrente alprocessore5 il quale tende a scaldarsi e spesso a degradare le prestazioni.

Rimangono ora da definire le scadenze temporali. Sicuramente il sistema di controllo vero e proprio verràasservito all’ADC, ossia la routine di controllo dovrà essere eseguita ogni volta che l’ADC avrà campionato unnuovo valore. A sua volta il convertitore sarà asservito al PWM il quale andrà ad attivare il convertitore AD ad in-tervalli regolari di 50µs (pari al reciproco della frequenza di commutazione delle valvole) o multipli: ciò definiscela base dei tempi di integrazione. Questa gestione dell’ADC e PWM con portante triangolare è particolarmentevantaggiosa perché permette di andare a campionare il valore della corrente nel punto centrale dell’intervallo ONo OFF del PWM; questo valore è pari al valore medio nell’intervallo della corrente. Rifacendosi alla figura 4.5si noti che è possibile fare scatenare gli eventi di ativazione dell’ADC e/o gli interrupt a uno o entrambi dei duevertici della triangolare.

A questo punto occorre valutare che la routine che si vuole implementare (definita nelle simulazioni) abbiaun carico computazionale minore o al più uguale all’intervallo di tempo che avviene tra l’evento di fine con-versione dell’ADC e l’istante di aggiornamento del duty-cycle del PWM. Per fare ciò il metodo più semplice èimplementare il codice, eseguirlo senza collegare l’hardware di potenza alla scheda e misurare per esempio il

3Si noti che ciò non è vero per i pic i quali hanno datasheet completi per ogni processore.4il PLL è un coefficiente moltiplicativo che può assumere i valori x1, x4, x8, x16.5Si consideri che con PLL=1 il dsPIC assorbe “a vuoto” circa 15÷20mA contro i 110÷120mA con PLL=16.

Page 55: Dispensa PID

4.1. REGOLATORE PI SU PROCESSORI DSPIC30F 55

cambiamento di stato di un pin con un oscilloscopio. Si noti che indicativamente il tempo di elaborazione di unPI implementato con questo processore, a queste frequenze e con le modalità descritte, impiega dai 4,5 ai 6 µs

per essere eseguito.

Configurazione delle periferiche

Per la configurazione delle periferiche, in funzione di quanto detto in precedenza e in funzione del layout dellascheda (figura 4.3-b), le porte B (PORTB) devono essere configurate come ingressi analogici per permettere al-l’ADC di effettuare il campionamento in modo corretto; le porte D (PORTD) sono invece configurate come input(collegate ai pulsanti), mentre le porte E (PORTE) alle quali sono connessi i diodi led vanno settate come uscite,mentre quelle relative al PWM non ha importanza in quanto se un pin ha una funzione ulteriore oltre a quella disemplice porta I/O, il device ulteriore è “dominante” rispetto a quello di semplice porta.

L’ADC va configurato in modo che venga letto solo un canale (ossia il segnale proporzionale alla correntedato dal sensore) e il risultato posto nel buffer 0 (ADCBUF0) e deve generare un interrupt (_ADCIE=1) alla finedi ogni conversione; la chiamata all’interrupt richiesto dall’ADC (interrupt subroutine _ADInterrupt()) saràla routine di regolazione vera e propria (PI). La temporizzazione del sample&hold+conversione è, come detto,legata al PWM.

Il PWM è configurato per lavorare a 20kHz, ossia occorre definire la variabile PTPER, che identifica il periodo,ottenibile da datasheet come segue:

PTPER =12

(Fosc4

PLL

)1

fdesiderata+ 1 =

737280020000

+ 1 = 368 (4.1)

Il valore così calcolato è per portante triangolare e il numero deve essere l’intero troncato per difetto. Si noti chequesta variabile è a 15bit, mentre il duty-cycle è a 16bit (_PDCx dove x è 1, 2, o 3) e il valore massimo impostabileè doppio rispetto a _PTPER. I tre moduli PWM devono essere indipendenti. Infine si noti che il PWM sul micro-controllore può controllare sia la valvola alta che quella bassa di un ramo di inverter. La logica del segnale PWMin uscita dai pin specifici è condizionata dai flag High-side/Low-side PWM Output Polarity di configurazione difigura 4.6.

Figura 4.6: Configuration bits del dsPIC30F4012.

Page 56: Dispensa PID

56 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

Codice C

Si consiglia di leggere il codice seguente tenendo sempre a portata di mano [4], quanto meno per capire qualisono le procedure necessarie per la configurazione e la gestione delle periferiche.

=======================

global.h

#ifndef __GLOBAL_H__# define __GLOBAL_H__#include <p30f4012.h>#define ON 1#define OFF 0/* Logica di controllo dei LED inversa */#define LED_VERDE_ON _RE5=0b0#define LED_VERDE_OFF _RE5=0b1#define LED_ROSSO_ON _RE4=0b0#define LED_ROSSO_OFF _RE4=0b1#define CLOCK 7372800 //7372800 Clock esterno, come slle schede di valutazione#define NBIT 12#define NBIT2 13#define NBASE 4095#define NBASE2 8191#define NBASE3 16383#define NBASE24 16777000 //in realtà 2^24=16777261#define FREQ 20000 //20KHz#define PER 0.00005 //Periodo#define PERIODO (int)368#define DUTYCYM (int)736 //DC massimo in unipolare singola gamba#define DUTYCY PERIODO //DC massimo in unipolare doppia gamba#define OFFSET_I 512 //Offset delle correnti per riportarle allo 0#define CORRENTEP ADCBUF0 //Primo buffer contenente il valore della corrente digitalizzato#endif // __GLOBAL_H__

=======================

init.h

#ifndef __INIT_H__# define __INIT_H__#define TRIGGER_AD_PWM 0b011#define TRIGGER_AD_TMR3 0b010#define TRIGGER_AD_AD 0b000#define CHANNEL4 0b11#define CHANNEL2 0b01#define CHANNEL1 0b00extern void InitTIMER(unsigned int nStep);extern void InitPORT();extern void InitPWM(int nleg, unsigned char interrupt_enable);extern void InitAD(unsigned char trigger_AD, unsigned char ADCS_delay, unsigned char ingresso, unsigned char channel);#endif // __INIT_H__

=======================

init.c

#include "init.h"#include "global.h"#include <p30f4012.h>

/** InitPORT **/void InitPORT()

TRISD=0x0000;PORTD=0xFFFF;TRISB=0xFFFF;

Page 57: Dispensa PID

4.1. REGOLATORE PI SU PROCESSORI DSPIC30F 57

TRISE=0x0080; //setto come input solo il pulsantePORTB=0xFFFF;PORTE=0xFFFF; //Sulle mie schede i led e i pulsanti sono in logica inversaADPCFG=0x0000; //Specifica che PORTB, se configurato come input, è analogico

/** Inizializza il PWM **Il parametro in ingresso nleg determina quante gambe voglio abilitare in modo indipenden-te, mentre interrupt_enable indica se voglio abilitare l’interrupt************************/void InitPWM(int nleg, unsigned char interrupt_enable)

PTPER=PERIODO; //PWM Time Period register 15bit (Fquarz/4*PLL8)/(2*Freq desiderata). Attenzione _PTMOD influenza PTPER se >= 0b10PTCONbits.PTMOD=0b10; //Free Running Mode=00, Continuous Up/Dw=10. Attenzione: il periodo complessivo raddoppia se _PTMOD>=0b10PTCONbits.PTOPS=0b0000; //PostscalerPTCONbits.PTCKPS=0b00; //PrescalerPTCONbits.PTSIDL=0b0;PTCONbits.PTEN=0b1; //Abilitazione (e attivazione) del PWMPWMCON1=0x0000; //Inizialmente azzero tutto il registro per precauzioneif(nleg>0)

PDC1=0; //duty cycle per PWM1 16bit, quindi duty=50%->PDCx=PTPERPWMCON1bits.PMOD1=0b1; //Indipendent mode 0=off, 1=onPWMCON1bits.PEN1H=0b1; //Abilito la gamba altaPWMCON1bits.PEN1L=0b1; //Abilito la gamba bassa

if(nleg>=2)

PDC1=DUTYCY; //se ’2’ è perché controllo il ponte ad HPDC2=DUTYCY; //duty cycle per PWM1 16bit, quindi duty=50%->PDCx=PTPERPWMCON1bits.PMOD2=0b1; //Indipendent mode 0=off, 1=onPWMCON1bits.PEN2H=0b1; //Abilito la gamba altaPWMCON1bits.PEN2L=0b1; //Abilito la gamba bassa

FLTACON=0x0000;_PWMIF=0;_PWMIE=(interrupt_enable&0x1); //Abilito o no l’interrupt

/** Inizializza l’ADC **/void InitAD(unsigned char trigger_AD, unsigned char ADCS_delay, unsigned char ingresso, unsigned char channel)

/* Le tabelle di configurazione sono da pagina 420 in poi del Manual Family. */

ADCHS=0;ADCHSbits.CH0SA=ingresso&0x0F; //numero di ingressi da campionare AN0->CH1=>ADCBUF1, AN1->CH0=>ADCBUF0_SIMSAM=0b1; //se 1 -> simultaneous sampling_SMPI=0b000; //0=Interrupt dopo ogni campionamento e si riparte dal buffer 0 a scrivere, 1=interrupt dopo 2 campionamenti, eccswitch(trigger_AD)

case TRIGGER_AD_PWM:_SSRC=TRIGGER_AD_PWM; //gestito da PWM = 011break;

case TRIGGER_AD_TMR3:_SSRC=TRIGGER_AD_TMR3; //gestito dal timerbreak;

default:_SSRC=TRIGGER_AD_AD; //tutto gestito dall’AD=111,

_ASAM=0b1; //Automatic sample_CSCNA=0b0; //Disabilito lo scanning dei sample/hold se 0_ALTS=0; //Alternate MUX Sampling: se 0 il multiplexer è sempre impostato si AADCON2bits.CHPS = channel&0x03; //Scelta del canale: 00=S/H su CH0, 01=S/H su CH0 e CH1, 1x=CH0,1,2,3//---Questi sono flag del PWM---//SEVTCMPbits.SEVTCMP=0;SEVTCMPbits.SEVTDIR=0b0;_SEVOPS=0b0000; //0=Evento per l’ADC ogni intervallo di PWM, 1=conversione AD ogni 2 PWM, ecc//------------------------------//ADCON3bits.SAMC = 1; //tempo minimo di sampleADCON3bits.ADCS = ADCS_delay&0x3F; //Setta il minimo tempo per la conversione A/D.ADPCFGbits.PCFG0 = 0;ADPCFGbits.PCFG1 = 0;ADPCFGbits.PCFG2 = 0;_ADIE=1; //Abilito l’interrupt_ADIF=0;

Page 58: Dispensa PID

58 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

_ADON=0b1; //Attivo l’ADON

=======================

pi.h

#ifndef __PI_H__# define __PI_H__/********** REGOLATORE DI CORRENTE ***********/#define CURRENT_BASE 100 //lem da 25A con una spira ->100A teorici, 80 in saturazione#define OFFSET_CURRENT 512#define INITIAL_CURRENTR 0 //eventuale valore iniziale dell’integrale#define CURRENT_RIF 2048 //2048->50A/***** PI di corrente *****/#define INTEGRALEI(e)((e>>1)+(e>>4))#define RID_IP 12#define TKIUPI NBASE24 // sarebbe più corretto +13422000#define TKIDWI -NBASE24 // sarebbe più corretto -13422000//----------------------------//#define PROPORZIONALEI(e)((e<<1)+(e>>1))#define TKPUPI NBASE //KP threshold up#define TKPDWI -NBASE //KP threshold down#define VDUP 3276 // limito superiormente l’uscita a ~ 80V#define VDDW -3276 // limito inferiormente l’uscita a ~ -80V/********** CHECK DUTY-CYCLE *************/#define DCUP 699 //perdo il 5% della tensione che perdo x colpa dei tempi morti#define DCDW 37/********** MACRO DI RIPORTO DEL DC **************/#define V_OFFSET 4095#define GET_DC(v_digit)((v_digit>>4)+(v_digit>>6)+(v_digit>>7)+(v_digit>>8))#endif // __PI_H__

In questo file vengono definite le principali costanti relative al regolatore PI. Meritano però una breve consi-derazioni le definizioni delle soglie relative al duty-cycle: si osservi infatti che il valore minimo e il valoremassimo sono rispettivamente il 5% e il 95% del valore massimo della variabile PDCx. Ciò è dovuto al fattoche è bene non far avvenire due commutazioni troppo ravvicinate. Infatti se per esempio il duty-cycle fossedel 99% per più di un ciclo si avrebbe la commutazione di una valvola (per esempio in spegnimento) e dopo50·10−6/736'680 ns si avrebbe un’altra commutazione. Commutazioni troppo ravvicinate possono danneggiareirreparabilmente il driver. Ciò è solo una precauzione nel caso le soglie VDUP e VDDW vengano modificate inav-vertitamente in modo errato. Si noti che per quanto riguarda l’integrale, la soglia corretta da porre sarebbe quelladi 80/100 · 40962=13422000.

=======================

main.c

#include <p30f4012.h>#include "global.h"#include "init.h"#include "pi.h"/***** Global *****************/int errorI,errorI_1; //errore ed errore precedenteint riferimentoIp=CURRENT_RIF;long int integraleIp; //24bit+1bit di segnoint correnteIp; //12bit+1bit di segnolong int vd_out; //variabile in base 12bit+1bt di segno/**********************************

MAIN

**********************************/int main()

Page 59: Dispensa PID

4.1. REGOLATORE PI SU PROCESSORI DSPIC30F 59

InitPORT(); //Inizializzo le porteInitPWM(2,OFF); //Abilito due gambe del PWM, ma senza abilitare l’inerruptLED_VERDE_ON;while(_RE8); //Fino a che resta tutto in stop o non premo RE8 non fare nullaNop();while(!_RE8); //Se rilascio il pulsante parte il sistemaLED_VERDE_OFF;InitAD(TRIGGER_AD_PWM,10,0,CHANNEL1); //Abilito l’AD asservendo l’evento di conversione al PWM e campiono un solo canaleLED_ROSSO_ON;while(1); //Entro nel ciclo infinito per evitare il reset del micro. Tutto il controllo verrà gestito in interrupt

/****************************

Interrupt SubRoutine

****************************/void _ISR _ADCInterrupt() //Sintassi della routine di interrupt dell’ADC

int dc, errorIi;_RD0=1; //Flag per la misura dei tempi di esecuzione. Può essere omesso.

/***************************************************REGOLATORE DI CORRENTE: metodo dei trapezi

***************************************************/correnteIp=((CORRENTEP-OFFSET_I))<<3; //riporto la corrente a 12biterrorI=(riferimentoIp-correnteIp); //calcolo l’errore

//INTEGRALE:errorIi=errorI_1+errorI; //errore x l’integrale=errore attuale + errore precedenteif(errorIi>=0)

integraleIp+=INTEGRALEI(errorIi);else

integraleIp-=INTEGRALEI((-errorIi));//PROPORZIONALE:

vd_out = PROPORZIONALEI((errorI))+(int)(integraleIp>>12);if(vd_out>VDUP) vd_out=VDUP;

else if(vd_out<VDDW) vd_out=VDDW;/***************************************************

USCITA riportata sul DC

***************************************************/vd_out+=V_OFFSET; //porto il valore da 0 a 8191 (->13bit)dc=GET_DC(vd_out);if(dc>DCUP) dc=DCUP; //Controllo precauzionale sul DC

else if(dc<DCDW) dc=DCDW;PDC2=dc;PDC1=DUTYCYM-dc;

/***********************************************TRATTAMENTO FINALE DELLE VARIABILI

***********************************************/if(integraleIp>TKIUPI) integraleIp=TKIUPI;

else if(integraleIp<TKIDWI) integraleIp=TKIDWI;errorI_1=errorI;_ADIF=0;_RD0=0;_RD0=0; //Flag per la misura dei tempi di esecuzione. Può essere omesso.

Osservando il codice si vede che a parte la fase di inizializzazione dei devices del micro processore, il resto èmolto simile a quanto modellizzato in SIMULINK. La parte più importante è la routine di interrupt invocata dalconvertitore AD. Come si vede il sistema calcola l’errore di corrente a 12bit. Il riferimento è pari a 2047 checorrisponde a 50A. Successivamente viene calcolato l’integrale e il proporzionale. Si noti che il primo vienecondizionato tramite opportuni costrutti “if” che servono ad evitare gli errori legati agli shift negativi (sezione1.3), mentre il proporzionale no; questo perché il primo shift del proporzionale è ha sinistra e dello stesso valoredi quello destro, quindi il risultato presenta un errore sensibile solo se il dato in ingresso vale -1. In più ilproporzionale “non ha memoria” e quindi non accumula errori. Inoltre il proporzionale non viene saturato perchél’errore massimo che può essere letto è di 2048 che moltiplicato per 2,5 dà 5120. Ammettendo che l’integrale(opportunamente shiftato) sia pari a 4096, la loro somma è inferiore a 215; in altre parole non vi è l’overflowdella variabile intera con segno a 16 bit. Una volta calcolata l’uscita, essa viene saturata a 3276 che corrisponde a

Page 60: Dispensa PID

60 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

80V (per rispettare la simulazione). Successivamente il duty-cycle viene ottenuto dalla tensione in scala 0-8191(ossia 13 bit) e nuovamente saturato. Questa soglia di saturazione viene posta solo per completezza per evitareche il sistema dia un duty-cycle del 100% (o prossimo al 100%) il che può danneggiare il driver. Conviene quindiprevedere un 5% di tensione in meno del valore massimo e minimo. É chiaro che tutto ciò potrebbe essere tenutoin conto nella saturazione della variabile vd_out. Per riportate la tensione espressa in scala 13 bit sul duty-cycleespresso in scala 0-736 occorrerebbe dividere per 213, moltiplicare per la corrente massima di riferimento (100A),dividere per la tensione massima di DC-bus (100V) e moltiplicare per 736:

δ = vd_out13 ·100213

· 736100

= 0.0898

il che corrisponde alla macro GET_DC. Il numero in ingresso alla macro è sempre positivo e quindi non ha bisognodi controlli sulla variabile.

L’ultima parte della routine di controllo serve per limitare l’integrale. La posizione più corretta per effettuarela saturazione è subito dopo il calcolo dell’integrale. Il fatto che venga posta alla fine è solo a titolo di esempio inquanto si preferisce aggiornare il duty-cycle il più presto possibile. In questo esempio ciò non comporta nessunbeneficio perché i tempi di calcolo sono molto più bassi del periodo del duty-cycle. Potrebbe invece avere effettipositivi se i tempi fossero maggiori di questo periodo, o se il campionamento non fosse sincrono con gli eventi diPWM.

======================

4.2 Controllo di tensione

In questo capitolo verrà affrontato lo sviluppo di un regolatore mediante processore PIC16F684. Premesso quan-to detto nei capitolo precedenti, si cercherà di realizzare un regolatore PI per la simulazione di un controllo dicorrente. Per fare ciò si utilizzerà la demoboard PICKIT2 (e relativo programmatore PICKIT2) di MICROCHIP.Alla scheda verrà connesso un circuito RC (R=1KΩ, C=1µF elettrolitico) il quale viene alimentato direttamentedal PWM del micro controllore retroazionando la tensione sul condensatore la quale verrà acquisita dal conver-titore analogico-digitale. É chiaro che se R e C sono scelti adeguatamente è possibile avere un circuito RC chepresenta la stessa costante di tempo di un circuito RL. Chiaramente ciò che verrà tenuto sotto controllo non èla corrente, ma la tensione sul condensatore in quanto quest’ultima presenta lo stesso andamento della corrente.Scegliendo opportunamente R e C sarebbe possibile anche avere anche la stessa risposta (in termini di dinamica)di un eventuale sistema R-L da simulare.

GRL(s) =1RL

1 + s LRL

≡ GRC(s) =1

1 + sRCse

R = 1C = L/RL

In figura 4.7 è riportato lo schema di connessione del circuito RC alla demo board PicKit2 il cui datasheet è[7] disponibile su [L3].

Il vantaggio principale di ciò è che il micro processore realizza contemporaneamente il sistema di controllo,l’attuatore e il sensore senza bisogno di collegare altri dispositivi esterni. Esaminando [7] si osserva che la schedanon presenta un clock esterno, quindi il micro processore dovrà necessariamente utilizzare il proprio oscillatoreinterno (frequenza nominale 4MHz); questi tipi di oscillatori non sono precisissimi quindi le formule descrittein [8] per il calcolo del PWM potrebbero non essere affidabili. É consigliabile quindi andare a misurare con un

Page 61: Dispensa PID

4.2. CONTROLLO DI TENSIONE 61

(a) Connettore dei pin disponibili (da datasheetdella demo board PicKit2)

(b) Circuito R-C e relative connessionialla demo board.

Figura 4.7: Schema di collegamento del circuito RC ai pin accessibili della scheda di valutazione PICKIT2DEMO.

oscilloscopio la frequenza di PWM che, in questo caso, verrà impostata alla massima possibile e pari a 3,9kHz.Tale frequenza sarà anche quella di campionamento.

4.2.1 Progetto e implementazione del regolatore

Il progetto del regolatore resta pressoché invariato rispetto a quanto detto nei capitoli 2 e 3. Si consideri quin-di un margine di fase di 90 e una banda passante di 1500 rad/s. Ne conseguono KP =1,5 e KI =1500.Implementando il regolatore in digitale si ha che il coefficiente di integrazione KI sarà pari a:

KI = KITS2

= 15001

2 · 3900= 0.1923

mentre KP resta pari a KP . Il codice si sviluppa quindi nei seguenti files:

main.c file principale contenete la funzione main, le macro del regolatore e le funzioni di interrupt

init.h file contenente i prototipi delle funzioni

init.c file di implementazione delle funzioni definite in init.h

Configurazione del processore e relative periferiche

I bit di configurazione del processore devono essere settati come segue: watchdog disabilitati, clock interno(Internal RC clockout) e Master Clear Enabled (figura 4.8).

Per quanto riguarda le periferiche, ciò che serve è la configurazione delle porte I/O le quali vanno definitecome output per le porte C (PORTC) alle quali sono collegati i led della demo board, e come input analogico laporta 1 delle porte A (RA1).

L’ADC dovrà essere configurato in modo da leggere l’ingresso analogico su RA1. Si sceglie di usare solo gli8 bit più significativi quindi il risultato del campionamento dovrà essere “giustificato a sinistra” ossia resettandoil bit ADFM.

Il PWM è gestito tramite il timer 2 grazie al quale è possibile definire il periodo di PWM e il numero di periodiche devono trascorrere perché venga generato l’interrupt. La configurazione è tale per cui si vuole ottenere lamassima frequenza di PWM e un interrupt ad ogni periodo quindi postscaler e prescaler verranno azzerati (almenoinizialmente). Il duty-cycle è una grandezza a 10 bit i cui 8 bit più significativi sono contenuti nella variabileCCPR1L. Gli altri due bit verranno mantenuti a 0.

Page 62: Dispensa PID

62 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

Figura 4.8: Configuration bits per processore pic16f684 (da MPLab).

Codice C

Si consiglia di leggere il codice seguente tenendo sempre a portata di mano [8], quanto meno per capire qualisono le procedure necessarie per la configurazione e la gestione delle periferiche. La base scelta per i calcoli è 8bit.

ESEMPIO N1:

=======================

init.h

#ifndef __INIT_H__

#define __INIT_H__

extern void InitPORT(void); //porteextern void InitTIMER2(void); //x controllo PWMextern void InitPWM(void); //set pin PWM + event trigger ADextern void InitAD(void); //config AD#endif //__INIT_H__

=======================

init.c

#include "init.h"

#include "htc.h"

void InitPORT() ANSEL=0x03;TRISA=0b00000011;TRISC=0x00;PORTC=0;CMCON0=0xFF; //se non metti questo le ANx assumono valori assurdi!!!!

/****************************PWM: Per capire come i tempi impostati nel timer 2 siano correlati al PWM e come configurare le porte, si veda la figura 11-4 di [8]. CPPR1L è la parte + significativa del duty-cycle, mentre DC1B è la meno significativa (10bit in totale). Le porte condivise sono: RC2=P1D, RC3=P1C, RC4=P1B, RC5=P1ASi noti che per fare il ponte ad H occorre settare P1M=0b10 (vedere in [8] figura 11-6)

****************************/void InitPWM() //riferirsi a CCP1CON

CCP1CON=0x00; //azzero tutto per sicurezzaP1M1=0b1; P1M0=0b0; //01=Full bridge foreward. 10=Half bridge (comando 2 valvole)CCP1M3=0b1; //1100=P1A,C,B,D attive alteCCP1M2=0b1; //1101=P1A,C attiveH, B,D attiveB //in altre parole B e D sono negateCCP1M1=0b0; //1110=P1A,C attiveL, B,D attiveBCCP1M0=0b0; //1100=P1A,C,B,D attiveLInitTIMER2();

Page 63: Dispensa PID

4.2. CONTROLLO DI TENSIONE 63

/* TIMER2: Timer a 8 bit. */void InitTIMER2()

T2CON =0x00; //Azzero tutto per precauzioneTOUTPS3 =0b0;TOUTPS2 =0b0; TOUTPS1=0b0; TOUTPS0=0b0; //Postscaler 0000=1:1, 1111=1:16T2CKPS1 =0b0; T2CKPS0=0b0; //Prescaler 00=1, 01=4, 1x=16TMR2IF =0; //Azzero il flag di interruptTMR2IE =1; //Abilito l’interrupt. Verrà usato come interrupt del PWM!TMR2 =0; //Contatore da comparare a PWMPR2 =0xFF; //Con PR2 definisco il periodo del PWMTMR2ON =1; //Attivo il TMR

void InitAD(void)

ADFM=0b0; //0= giustificazione a sinistraVCFG=0b0; //0= tensione di riferimento pari ai 5V di alimentazioneCHS2=0; CHS1=0; CHS0=1; // 000=AN0=RA0, 001=AN1ADCS0=0; ADCS1=0; ADCS2=0; //000=Fosc/2 x la conversione, che con il clock interno a 4MHz sono circa 24.1us (misurati)ADIF=0;ADIE=1;ADON=1; //abilito l’adc

=======================

main.c

#include <htc.h>#include "init.h"//DEFINIZIONI#define RIFERIMENTO 5 //in volt#define RIFD 105 //riferimento digitale#define INTEGRALE(e)((e>>3)+(e>>4)+(e>>8))#define PROPORZIONALE(e)((e)+(e>>1))//GLOBALSshort int error, error_1, riferimento, proporzionale; //8bit con segnoint out, integrale; //16bitvoid main()

GIE=1; //interrup globalo ONPEIE=1; //interrupt delle periferiche ONInitPORT();InitAD();InitPWM();InitTIMER1();GODONE=1; //inizio prima conversionewhile(1); //entro nel ciclo infinito

// INTERRUPT SUB-ROUTINEvoid interrupt isr(void)

int errorI;if(TMR2IF) //se scatta l’interrupt a causa del timer 2 (ossia del PWM) allora...

RC0=RC0^0x1; //lampeggio del primo led (per debug)GODONE=0b1; //Inizio conversione ADTMR2IF=0b0; //azzero il flag di interrupt

if(ADIF)

RC1=0b1; // set di un bit per la misura dei tempi di calcoloADIF=0b0;error=RIFD-(ADRESH); //calcolo dell’erroreerrorI=(int)error+error_1; //cast di error per eseguire i calcoli in intif(errorI>=0) integrale+=INTEGRALE(errorI);

else integrale-=INTEGRALE((-errorI));if(integrale>255) integrale=255; //saturazione positiva dell’integrale

else if(integrale<-255) integrale=-255; //saturazione negativa dell’integraleproporzionale=PROPORZIONALE(error);out=(int)proporzionale+integrale;if(out>255) out=255; //soglia superiore dell’uscita

else if(out<0) out=0; //soglia inferiore dell’uscita

Page 64: Dispensa PID

64 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

CCPR1L=out;error_1=error; //salvo l’errore attualeRC1=0b0 // Reset del bit per la misura dei tempi di calcolo

=======================

In questo primo esempio il codice proposto realizza brutalmente il regolatore gestendo l’integrale a 16 bitin modo da poter avere un valore dell’integrale compreso tra ±255. Si è infatti ipotizzato che la base sia 8 bit(ossia con 255≡5V in ingresso) ed è noto che l’uscita sia ancora una tensione compresa tra 0V e 5V; ciò implicache anche l’integrale debba avere una soglia pari al valore massimo raggiungibile dall’uscita o, per meglio dire,raggiungibile dalla variabile out. Tale considerazione andrebbe fatta anche per il proporzionale il quale, però,viene gestito a 8bit con segno (short int). É evidente che ciò potrebbe dare problemi legati al bit di segnoche il compilatore assegna all’ultimo bit; nonostante questo è ragionevole pensare che non vi siano particolariproblemi di computazione in quanto valori negativi inferiori a -127 (ossia 27-1) non dovrebbero mai verificarsi,soprattutto a regime. Questa scelta può sembrare un’inutile complicazione in quanto se si applicasse la stessaconsiderazione fatta per l’integrale a tutte le variabili questo problema, effettivo o presunto che sia, cesserebbedi esistere. É però necessario tenere presente che la potenza computazionale di questi processori non è rilevantee, unitamente al fatto che si sta lavorando con l’oscillatore interno da 4MHz, si ha che il codice deve essere ilpiù performante possibile; dove possibile è quindi meglio usare variabili con dimensione di memoria pari alla“parola” del processore (8 bit in questo caso).

Detto ciò, esaminando il codice del regolatore dovrebbe essere tutto chiaro fino al calcolo dell’uscita (out). Aquesto punto viene settato il duty-cycle pari all’uscita (CCPR1L=out) e ciò forse richiede una breve spiegazione:da [8] cap˙11 si evince che il duty-cycle è una variabile a 10bit divisa in una variabile da 8 bit più significativi(CCPR1L) e 2bit meno significativi (DC1B<1:0> nel registro CCP1CON). Detto ciò, è noto che il valore delduty-cycle è dato dal valore di OUT moltiplicato per il reciproco del coefficiente di conversione (pari a 256/5V)diviso il valore massimo della tensione di uscita (5V in questo caso), per il valore massimo digitale del duty-cycle(210):

δdigit = out · 5256

· 10245

= out · 22 = out 2

ma essendo OUT un valore compreso nei primi 8 bit, ne deriva che OUT è il valore dei primi 8 bit più significatividel duty-cycle. Gli ultimi due bit sono sicuramente nulli, quindi non è necessario settarli.

Il codice così sviluppato è formalmente corretto, ma esaminando l’uscita con un oscilloscopio si nota che visono dei problemi legati al controllo. Fugati i dubbi legati ai problemi di calcolo, si suppone che il regolatorepresenti dei problemi legati ai tempi di esecuzione. Per valutare ciò occorre misurare i tempi osservando ilcambiamento di stato dei bit RC0, RC1, RC2 e RC3 (i quali sono connessi ai diodi led sulla demo board).Disabilitando il regolatore, tramite RC0 si valutano gli istanti in cui avviene l’interrupt a fronte dell’evento diPWM come si può osservare dalla figura 4.9. Attivando il regolatore è possibile valutare gli istanti in cui laroutine di regolazione comincia e termina e, per differenza, ottenere i tempi di esecuzione della stessa. Setutto funzionasse correttamente, ci si dovrebbe aspettare che l’istante di inizio della routine e quello finale sianocompresi in un singolo periodo di PWM, ma dalla figura 4.10 si osserva che così non è. Infatti il tempo diesecuzione della routine di regolazione è più di 100µs e quindi maggiore del periodo di PWM. Analizzando ilgrafico 4.10-b si osserva che i tempi di esecuzione non sono sincroni con la triangolare (tensione sul condensatore)e pertanto non saranno sincroni con il PWM, ma ciò causa il sovrapporsi degli eventi di interrupt; per esempioè frequente che l’evento di interrupt di PWM scatti durante la regolazione andando così a sfasare anche gli altrieventi (figura 4.10-a); lo sfasamento legato all’evento di PWM crea un ritardo nell’attivazione dell’ADC e ciò si

Page 65: Dispensa PID

4.2. CONTROLLO DI TENSIONE 65

La frequenza di PWM è 3,9kHz (rosso)e ogni evento di PWM (blu) avvienecon la stessa frequenza ed è rappresen-tato da ogni singolo fronte di salita ediscesa.

Figura 4.9: Interrupt di PWM sovrapposto al segnale di PWM con δ al 50%.

(a) Sfasamento degli eventi di interrupt (regolatore disabilitato). (b) Andamento della tensione sul condensatore e misura dei tempidi esecuzione (regolatore abilitato).

Figura 4.10: Sfasamento degli eventi di interrupt.

ripercuote sui tempi di integrazione. Una fotografia della tensione in una finestra temporale più ampia dimostral’andamento irregolare della tensione stessa la quale non ha un valore medio costante6 (figura 4.11).

6Il valore medio è inteso come valore calcolato in ogni singolo intervallo di PWM.

Page 66: Dispensa PID

66 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

Il fatto che l’attivazione della con-versione sia effettuata in ritardo, inlinea teorica comporta che il valorecampionato sia un qualsiasi valorecompreso all’interno del ripple di unperiodo di PWM. Ciò avviene con unacerta frequenza generando un’ondache nel tempo presenta una evidentesub-armonica

Figura 4.11: Andamento reale della tensione sul condensatore.

ESEMPIO N2:Per ovviare a quanto detto le soluzioni sono fondamentalmente tre. La prima è provare a riscrivere il codice

in assembler, cosa che non verrà affrontata in quanto oltre che complesso può anche risultare inutile a causa delfatto che se il compilatore C riesce ad ottimizzare il programma; è molto probabile che la scrittura del codicein assembler non porti i vantaggi sperati. La seconda soluzione prevede di allungare il periodo di PWM ma lacosa non è conveniente perché si rischia di aumentare troppo il ripple. La terza consiste invece nel far avvenirel’evento di interrupt ogni due periodi di PWM sfruttando il post-scaler. Ciò comporta che il PWM ha ancorala stessa frequenza (e quindi ripple più basso possibile), ma la base dei tempi di integrazione è raddoppiata. Ilcodice seguente rappresenta la sola funzione di inizializzazione del PWM e il main file in quanto sono le unichedue cose che variano rispetto al caso precedente.

=======================

init.c

...void InitTIMER2()

T2CON =0x00; //Azzero tutto per precauzioneTOUTPS3 =0b0; TOUTPS2=0b0; TOUTPS1=0b0; TOUTPS0=0b1; //Postscaler 0000=1:1, 1111=1:16T2CKPS1 =0b0; T2CKPS0=0b0; //Prescaler 00=1, 01=4, 1x=16TMR2IF =0; //Azzero il flag di interruptTMR2IE =1; //Abilito l’interrupt. Verrà usato come interrupt del PWM!TMR2 =0; //Contatore da comparare a PWMPR2 =0xFF; //Con PR2 definisco il periodo del PWM

TMR2ON =1; //Attivo il TMR...

=======================

main.c

#include <htc.h>#include "init.h"//DEFINIZIONI#define INTEGRALE(e)((e>>2)+(e>>3)+(e>>7))

Page 67: Dispensa PID

4.2. CONTROLLO DI TENSIONE 67

#define PROPORZIONALE(e)((e)+(e>>1))//GLOBALSshort int error, error_1, proporzionale, riferimento; //8bitint out, integrale; //16bitvoid main()

GIE=1; //interrup globalo ONPEIE=1; //interrupt delle periferiche ONInitPORT();InitAD();InitPWM();InitTIMER1();GODONE=1;while(1); //entro nel ciclo infinito

// INTERRUPT SUB-ROUTINEvoid interrupt isr(void)

int errorI;if(TMR2IF) //se scatta l’interrupt a causa del timer 2 (ossia del PWM) allora...

RC0=RC0^0x1;GODONE=1;TMR2IF=0b0; //azzero il flag di interrupt

if(ADIF)

RC1=0b1;ADIF=0b0;error=RIFD-(ADRESH);errorI=(int)error+error_1;if(errorI>=0) integrale+=INTEGRALE(errorI);

else integrale-=INTEGRALE((-errorI));if(integrale>255) integrale=255;

else if(integrale<-255) integrale=-255;proporzionale=PROPORZIONALE(error);out=(int)proporzionale+integrale;if(out>255) out=255;

else if(out<0) out=0;CCPR1L=out;error_1=error;RC1=0b0;

if(TMR1IF)

RC3=RC3^0b1;TMR1ON=0b0;TMR1IF=0b0;

=======================Il fatto che ora i tempi di integrazione siano doppi (grazie a TOUTPS0=0b1) implica che il coefficiente di

integrazione sia doppio. Ne risulta che la macro INTEGRALE sia definita come:

#define INTEGRALE(e)((e>>2)+(e>>3)+(e>>7))

In figura 4.12 sono riportati gli istanti in cui avviene l’evento di interrupt del PWM e i tempi di inizio edesecuzione correlati alla routine di regolazione. La frequenza con cui si verificano gli interrupt di PWM è di circa1938 kHz (pari a 516µs) e si ha quindi tutto il tempo per eseguire la routine di regolazione.

ESEMPIO N3:Il sistema fino ad ora proposto permette di effettuare la regolazione in modo corretto. Però il valore di tensione

tenuto sotto controllo non è il valore medio, bensì il valore di tensione nel punto più basso della triangolare7 ocomunque in un intorno di questo punto. Scopo di questo terzo esempio è quello di mostrare come risolvere

7Si ricorda infatti che in questo tipo di micro-processore il PWM viene generato da un’onda a dente di sega e non da una triangolare (comeinvece possono fare per esempio i dsPIC), quindi se l’interrupt avviene in un vertice della portante, questo istante non corrisponde a metà deltempo TON (o TOFF ).

Page 68: Dispensa PID

68 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

(a) Periodo di PWM (rosso) e interrupt relativo (blu, uno per ognifronte)

(b) Tensione sul condensatore (rosso), tempo di esecuzione routinePI (blu), interrupt dell’ADC

Figura 4.12: Regolazione in due periodi di PWM.

questo problema. Prima di mostrare il codice è però bene individuare i tempi esatti in cui avvengono i variinterrupt: infatti osservando la figura 4.13 (o anche la figura 4.9) è possibile vedere come tra l’onda di PWM ela rilevazione dell’interrupt di PWM vi sia un ritardo pari a circa 32µs8 di cui necessariamente si dovrà tenereconto.

Figura 4.13: Ritardo tra l’inizio del PWM e l’effettiva rilevazione dell’interrupt.

Per risolvere il problema è quindi intuitivo pensare di sfruttare un timer (o contatore) il quale dovrà attendereil tempo necessario per fare in modo che la conversione AD parta nell’istante corrispondente al punto mediodell’intervallo TON del PWM. I timer a disposizione sono il timer TMR0 e TMR1: il primo non si può utilizzarein quanto non è possibile poterlo attivare via software, quindi la scelta ricade inevitabilmente su TMR1. Il codiceche mostra una possibile soluzione del problema è il seguente:

=======================8Tale ritardo è probabilmente imputabile ad alcuni fattori tra cui la chiamata di funzione di interrupt che deve salvare il contesto del

programma e alla comparazione “if(TMR2IF)” per identificare l’evento di PWM.

Page 69: Dispensa PID

4.2. CONTROLLO DI TENSIONE 69

init.h

#ifndef __INIT_H__

#define __INIT_H__

extern void InitPORT(void); //porteextern void InitTIMER1(void);extern void InitTIMER2(void); //x controllo PWMextern void InitPWM(void); //set pin PWM + event trigger ADextern void InitAD(void); //config AD#endif //__INIT_H__

=======================

init.c

#include "init.h"

#include "htc.h"

void InitPORT() ANSEL=0x03;TRISA=0b00000011;TRISC=0x00;PORTC=0;CMCON0=0xFF; //se non metti questo le ANx assumono valori assurdi!!!!

void InitPWM() //riferirsi a CCP1CON

CCP1CON=0x00; //azzero tutto per sicurezzaP1M1=0b1; P1M0=0b0; //01=Full bridge foreward. 10=Half bridge (comando 2 valvole)CCP1M3=0b1; //1100=P1A,C,B,D attive alteCCP1M2=0b1; //1101=P1A,C attiveH, B,D attiveB //in altre parole B e D sono negateCCP1M1=0b0; //1110=P1A,C attiveL, B,D attiveBCCP1M0=0b0; //1100=P1A,C,B,D attiveLInitTIMER2();

/* TIMER2: Timer a 8 bit. */void InitTIMER2()

T2CON =0x00; //Azzero tutto per precauzioneTOUTPS3 =0b0;TOUTPS2 =0b0; TOUTPS1=0b0; TOUTPS0=0b0; //Postscaler 0000=1:1, 1111=1:16T2CKPS1 =0b0; T2CKPS0=0b0; //Prescaler 00=1, 01=4, 1x=16TMR2IF =0; //Azzero il flag di interruptTMR2IE =1; //Abilito l’interrupt. Verrà usato come interrupt del PWM!TMR2 =0; //Contatore da comparare a PWMPR2 =0xFF; //Con PR2 definisco il periodo del PWMTMR2ON =1; //Attivo il TMR

void InitAD(void)

ADFM=0b0; //0= giustificazione a sinistraVCFG=0b0; //0= tensione di riferimento pari ai 5V di alimentazioneCHS2=0; CHS1=0; CHS0=1; // 000=AN0=RA0, 001=AN1ADCS0=0; ADCS1=0; ADCS2=0; //000=Fosc/2 x la conversione, che con il clock interno a 4MHz sono circa 24.1us (misurati)ADIF=0;ADIE=1;ADON=1; //abilito l’adc

void InitTIMER1()

TMR1L=0xFF; TMR1H=0xFF;T1CON=0;TMR1ON=0b0;TMR1IF=0;TMR1IE=1;

=======================

main.c

#include <htc.h>

Page 70: Dispensa PID

70 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

#include "init.h"#define RIFD (short)80 //riferimento digitale#define INTEGRALE(e)((e>>3)+(e>>4)+(e>>8))#define PROPORZIONALE(e)((e)+(e>>1))//GLOBALSshort int error, error_1, proporzionale, riferimento; //8bitint out, integrale; //16bit//DELCARATIONvoid main()

GIE=1; //interrup globalo ONPEIE=1; //interrupt delle periferiche ONInitPORT();InitAD();InitPWM();InitTIMER1();GODONE=1;while(1); //entro nel ciclo infinito

// INTERRUPT SUB-ROUTINEvoid interrupt isr(void)

int errorI;if(TMR2IF) //se scatta l’interrupt a causa del timer 2 (ossia del PWM) allora...

TMR1ON=0b1; //attivo il timer1RC0=RC0^0x1;TMR2IF=0b0; //azzero il flag di interrupt

if(ADIF)

RC1=0b1; //flag di misura del tempoADIF=0b0;error=RIFD-(ADRESH);errorI=(int)error+error_1;if(errorI>=0) integrale+=INTEGRALE(errorI);

else integrale-=INTEGRALE((-errorI));if(integrale>255) integrale=255;

else if(integrale<-255) integrale=-255;proporzionale=PROPORZIONALE(error);out=(int)proporzionale+integrale;if(out>255) out=255;

else if(out<0) out=0;CCPR1L=out;error_1=error;TMR1H=0xFF; //setto a 255 la parte alta del TMR1TMR1L=0xFF-(CCPR1L>>1)+36; //sottraggo a 255 il tempo necessarioRC1=0b0; //flag di misura del tempo

if(TMR1IF)

RC3=RC3^0b1; //flag per individuare l’eventoGODONE=1; //attivo il campionamentoTMR1ON=0b0; //spengo il timer1TMR1IF=0b0;

=======================

Il codice sostanzialmente non è diverso per quanto riguarda l’inizializzazione e la regolazione se non per il fat-to che è stata aggiunta la funzione InitTMR1. Nella funzione di interrupt si può osservare che l’evento di PWM faattivare TMR1 e non più la conversione. Occorre ora ricordarsi che nei PIC il timer comincia a contare da un valo-re (nel caso di TMR1 comincia dal valore TMR1H·28+TMR1L) per arrivare la massimo (in questo caso 0xFFFF,ossia 65535 in quanto timer a 16 bit), azzerarsi e generare l’interrupt. Ciò implica che se si vuole far “contare” altimer un numero x di impulsi, il valore TMR1H·28+TMR1L deve essere pari a TMR1H·28+TMR1L=0xFFFF-x. La parte di codice che esegue questi passaggi è chiaramente “TMR1L=0xFF-(CCPR1L>>1)+36;” dove(CCPR1L>>1)+36=x. CCPR1L è il duty-cycle ossia il numero di tic che occorre aspettare per attendere untempo pari a TON . per questo viene diviso per 2 (mediante shift). A questo viene poi sommato 36. Questo nu-

Page 71: Dispensa PID

4.2. CONTROLLO DI TENSIONE 71

mero deriva da quanto detto in precedenza in quanto per avere 32µs su un timer senza pre/post-scalatori occorreun numero di tic pari a:

32µs = N

(fosc4

)−1

= N4

4 · 106s⇒ N = 32

Il fatto che sia stato posto 36 è legato al fatto che, una volta programmato il processore, effettuando alcunemisure il risultato è sembrato più preciso; in altre parole si è “affinato sul campo” il dispositivo. I risultati diquesto programma sono visibili in figura 4.14.

Si osserva che il PWM in regolazione (rosso)viene intersecato nel punto medio dall’onda cherappresenta l’istante di inizio conversione AD(blu). Chiaramente anche la tensione sul conden-satore è intersecata nel punto medio.

Figura 4.14: Sincronizzazione dell’istante di campionamento con il punto medio di TON .

Page 72: Dispensa PID

72 CAPITOLO 4. IMPLEMENTAZIONE DI UN REGOLATORE PI

Page 73: Dispensa PID

Capitolo 5

Regolatore PID

In questo capitolo verrà affrontato lo studio di un regolatore PID. Tutta la trattazione è realizzata basandosi sullavoro fatto per stabilizzare il levitatore elettromagnetico studiato in [5] e [6].

5.1 Regolatore tempo-continuo

L’uscita di un regolatore PI nel dominio del tempo è funzione dell’errore in ingresso ed è la seguente:

uPI(t) = KP e(t) + KI

∫ t

e(x)dx + KDd

dte(t) = KP

(e(t) +

1Ti

∫ t

e(x)dx + Tdd

dte(t)

)(5.1)

e, applicando la trasformata di Laplace, si ottiene

UPI =(

KP +KI

s+ sKD

)E(s) =

s2KD + sKP + KI

sE(s) = PI(s) · E(s) = R(s) · E(s) (5.2)

Realizzare un regolatore PID è quindi fisicamente impossibile in quanto il grado del numeratore è maggioredel denominatore. Ciò in teoria non è un problema se si pensa ai regolatori digitali; infatti con un micro controlloreè possibile effettuare i calcoli necessari affinché la routine di regolazione possa essere compiuta. Nonostante ciòè preferibile studiare un regolatore che sia fisicamente realizzabile introducendo un polo in alta frequenza sultermine derivativo. Secondo quanto spiegato in [2] una formulazione interessante è esprimere la parte derivativacome segue:

UD(s) =sKD

1 + sTd

N

(5.3)

dove, secondo [2], N è un numero tipicamente compreso tra 3 e 30, mentre Td è chiaramente pari a KD/KI .

Nonostante ciò il progetto del regolatore PID si sviluppa basandosi sull’equazione 5.2 in quanto più sempliceda trattare. Per il progetto si possono seguire vari metodi; di seguito ne vengono esposti alcuni indicandone pregie difetti.

Metodo di Zigler e Nichols

La via tradizionale è usare il metodo Zigler e Nichols in anello chiuso che si basa sull’osservazione della rispostaal sistema ponendo KD e KI pari a 0 e facendo variare KP partendo da valori molto piccoli non a raggiungereun’oscillazione permanente della risposta. Da questo si determina il periodo di oscillazione e successivamente

73

Page 74: Dispensa PID

74 CAPITOLO 5. REGOLATORE PID

i valori di KD e KI mediante apposite tabelle. Chiaramente questo sistema non permette una determinazioneanalitica della soluzione. Per maggiori informazioni si rimanda a [9].

Metodo analitico

Il metodo analitico è tendenzialmente simile a quello esposto per il regolatore PI (sezione 2.1.2). Anche in questocaso infatti è possibile fissare margine di fase e banda passante, ma occorre aggiungere anche una terza equazionea causa della nuova incognita KD. Per fissare la terza equazione si ricorre al margine di guadagno. Il marginedi guadagno di per sè non dà solo un’informazione sull’asintotica stabilità, ma qualifica anche la robustezzadella stessa; in altri termini indica la sicurezza con la quale possiamo tollerare incertezze sul modello senzacompromettere l’asintotica stabilità ([10]). Per ottenere il margine di guadagno occorre calcolare la pulsazioneωp ovvero quel valore di frequenza per la quale la fase della funzione d’anello L(s)1 risulta pari a 180; ottenutoquesto valore occorre porre il modulo di L(s) maggiore di 1:

km =1

|L(jωp)|> 1 con ∠L(jωp) = −180

Ciò comporta la nascita di una ulteriore incognita (ωp appunto) che si aggiunge alle altre due equazioni sul margi-ne di fase e banda passante: il sistema risulta costituito da quattro equazioni in quattro incognite, ma nonostanteciò non è risolvibile in forma chiusa a causa del fatto che l’equazione per determinare ωp è trascendente. Ilsistema di equazioni è comunque il seguente:

KP = |R(jωt)| cos(θ) = cos(θ)|G(jωt)|

KI + KDω2t = − |R(jωt)| sin(θ) = − sin(θ)

|G(jωt)|ωt

|KP + jωPKD − jωPKI | = 1km|G(jωp)|

∠ (KP + jωPKD − jωPKI) = −180 − ∠G(jωp)

(5.4)

Questo sistema permetterebbe di decidere il tipo di risposta desiderata e calcolare esattamente i vari coeffi-cienti.

Metodo del piazzamento poli

Il metodo del piazzamento poli permette di scegliere i poli e determinare degli opportuni coefficienti per fare inmodo che tali poli siano quelli del sistema. Per fare ciò si ricorre alla funzione place di MATLAB come indicatonell’algoritmo 7. Per poter applicare il metodo seguente occorre ottenere le matrici di stato che descrivono ilsistema in esame G(s). Le matrici che occorrono sono quella di stato A e quella degli ingressi B. La funzioneMATLAB place che permette di ottenere un vettore K dato un fissato vettore P di autovalori che moltiplicata peril vettore B degli ingressi e sottratto ad A permette di ottenere la nuova matrice di stato:

An = A− B · K

A questo punto è possibile ottenere la nuova funzione di trasferimento. Data questa funzione è poi possibile peranalogia confrontarne il denominatore con quello della funzione L(s) espressa nelle incognite KP , KI , KD.

Tutto ciò è valido nell’ipotesi che il sistema sia SiSo o MiSo e lo stato sia accessibile ovvero che tutte legrandezze del sistema siano rilevabili2.

1Si ricorda che con L(s) si intende L(s) = RPID(s) ·G(s)2Nella pratica spesso le grandezze non accessibili vengono stimate aggirando quindi il problema e permettendo sempre, almeno in linea

di massima, di utilizzare questa tecnica.

Page 75: Dispensa PID

5.1. REGOLATORE TEMPO-CONTINUO 75

Algorithm 7 Utilizzo funzione place di MATLAB.sys = tf(num, den); %definizione dela funzione di trasferimento G(s)[A, B, C, D] = tf2ss(num, den); %generazione delle matrici di statoP =[ p1 p2 ... pn]; %definizione del vettore dei poli di lunghezza pari alla dimensione di AK = place(A, B, P); %definizione del vettore KAn = A-B*K; %definizione del nuovo sistema da considerarsi in anello chiuso[num_n, den_n] = ss2tf(An, B, C, D); %calcolo i nuovi denominatorisys_n = tf(num_n, den_n); %calcolo nuovo sistema (in anello chiuso)

Si noti che le incognite sono tre, quindi il sistema in esame deve essere almeno del terzo ordine. Se fos-se di ordine inferiore, la funzione sys nell’algoritmo 7 dovrebbe essere portata al terzo ordine moltiplicandonumeratore e denominatore per s come nell’esempio seguente:

sys=tf(20,[1 10 0]); % NOsys=tf([20 0], [1 10 0 0]); % SI

I due sistemi hanno esattamente la stessa risposta, ma la matrice A risulterà di dimensione 3x3 e non 2x2. Siricorda che per ottenere le matrici A, B, C e D del sistema dati numeratore e denominatore della funzione ditrasferimento, in MATLAB si utilizza la funzione tf2ss3:

[A,B,C,D]=tf2ss([20],[1 10]); % A matrice 1x1[A,B,C,D]=tf2ss([20 0 0],[1 10 0 0]); % A matrice 3x3

Questo metodo permette di determinare un nuovo sistema da considerarsi in anello chiuso (sys_n nell’algoritmo7 che verrà indicata in seguito con F ′(s)) il quale sarà stabile e caratterizzato da una certa risposta dinamica.A questo punto se si calcolasse la funzione di trasferimento in anello chiuso F (s) che comprende il regolatoreR(s) e la funzione G(s) (sys nell’algoritmo 7), si otterrebbe una funzione che come al solito non è altro cheun rapporto tra due polinomi i cui denominatori sono dello stesso grado. Quindi per analogia si otterranno icoefficienti KP , KI , KD del regolatore PID. Questo metodo ha il difetto che la risposta del sistema in anellochiuso calcolato (F (s) = R(s)G(s)) sarà sì stabile, ma diversa dalla funzione sys_n perché il numeratore delledue funzioni non viene valutato per ottenere i coefficienti del regolatore, ma solo il denominatore è considerato(per capire meglio quanto appena detto si consideri l’esempio posto alla fine di questa sezione). Inoltre i polifissati non danno informazioni riguardo al margine di fase e quindi normalmente il sistema calcolato sottopostoad un gradino presenta sovra-elongazioni più o meno sensibili. Inoltre occorre tenere presente che fissando politroppo elevati (in modulo), ossia velocizzando la risposta del sistema, si tende ad avere una elevata reazione daparte del regolatore.

Vi sono però anche grandi pregi come la possibilità di fissare la dinamica a piacimento4 e quindi di stabilizzarei sistemi instabili.

ESEMPIO: si supponga un sistema del primo ordine da controllare e un regolatore PID da cui derivano le relativefunzioni di anello e in anello chiuso:

G(s) =µ

s + aR(s) = KDs

2+KP s+KI

s L(s) = G(s)R(s) = µKDs2 + KP s + KI

s (s + a)

F (s) =L(s)

1 + L(s)=

µ(KDs2 + KP s + KI

)s2 (µKD + 1) + s (µKP + a) + µKI

3Una lista dei comandi principali per lo situdio dei sistemi si può trovare in [11]4Ciò è vero entro i limiti della moderazione del controllo e della risposta libera del sistema se esso è instabile. Infatti se un sistema è

instabile i poli che stabilizzano il sistema devono possibilmente essere scelti in modulo maggiori del modulo maggiore dei poli del sistemada stabilizzare.

Page 76: Dispensa PID

76 CAPITOLO 5. REGOLATORE PID

e si supponga inoltre che il guadagno µ e la costante di tempo a siano pari all’esempio precedente, ossiarispettivamente pari a 20 e 10. Ora si vogliono fissare i poli. Premesso che la funzione place non piazzapoli coincidenti, si supponga di fissare il seguente vettore di poli: poli=-[30 100] tale per cui la funzio-ne MATLAB min(abs(poli)) restituisca un valore maggiore di 10. A questo punto occorre determinarele matrici di stato del sistema. Basandosi su quanto riportato nell’algoritmo 7, si eseguono i seguenti co-mandi:

sys = tf([ 20 0 ], [ 1 10 0 ]); %aggiungo uno 0 per avere un sistema 2x2[A, B, C, D] = tf2ss(num, den); %generazione delle matrici di stato (A è 2x2)P =[ -30 -100 ]; %definizione del vettore dei poli P è 1x2K = place(A, B, P); %ne risulta K=[ 120 3 ]An = A-B*K; %definizione del nuovo sistema da considerarsi in anello chiuso[num_n, den_n] = ss2tf(An, B, C, D); %calcolo i nuovi denominatori

sys_n = tf(num_n, den_n); % questa è F(s)

A questo punto il numeratore vale den_n=[1 130 3000] e la funzione d’anello è F ′(s) = 20ss2+130s+3000 la

quale è evidentemente asintotica a 0 a causa dell’s a numeratore. Quello che però interessa è il denomina-tore il quale per analogia con il denominatore di F(s) si ha:

1 = µKD + 1130 = µKP + a

3000 = µKI

KD = 20−1 = 0.05KP = (130− 10)/20 = 6KI = 3000/20 = 150

Quindi F (s) 6= F ′(s) come anche L(s) 6= L′(s). Da ciò si possono trarre alcune osservazioni. Lafunzione F (s) ha numeratore e denominatore uguali in grado. Ciò implica che sicuramente il sistemapresenterà errore non nullo a regime. Di questo però non si terrà conto in questo esempio che mira soloa far vedere come ottenere i coefficienti5. Si osservi inoltre che se il sistema fosse instabile (per esempioa=-10) questa procedura avrebbe stabilizzato il sistema, ma non per ogni valore di KP . Infatti è chiaroche tutti i coefficienti del regolatore debbano essere maggiori di 0 (o al limite uguali). Quindi si devenecessariamente avere che il coefficiente di s (in questo caso pari a 130) sia maggiore di a. Infine sinoti che la determinazione dei coefficienti (soprattutto di KD) non tiene conto dell’eventuale polo in altafrequenza. Normalmente questo polo è bene prevederlo, ma non in fase di progetto in quanto tende acomplicare anche notevolmente le formule.

5.2 Regolatore Discreto

Anche in questo caso è possibile procedere in più modi per la discretizzazione del regolatore.

Metodo 1: separazione della parte P, I e D

La discretizzazione del regolatore viene fatta seguendo le stesse indicazioni date nella sezione 2.2.2 ossia ap-plicando la trasformazione di Tustin. Sull’analisi vera e propria del sistema si entrerà nel dettaglio più avanti;tuttavia è bene riallacciarsi ad una nota fatta in precedenza riguardante il posizionamento di un polo in altafrequenza (equazione 5.3). Provando ad applicare Tustin alla componente derivativa del regolatore si ottiene:

RD(z) = KD2TS

(z − 1z + 1

)⇒ uD(z) =

2KD

Ts

(1− z−1

)e(z)− z−1uD(z) (5.5)

5Possibili soluzioni per migliorare la risposta potrebbero essere l’aggiunta di un integratore o di un eventuale regolatore in cascata a quelloappena determinato.

Page 77: Dispensa PID

5.2. REGOLATORE DISCRETO 77

Osservando questa relazione è subito chiaro che il termine costante 2KD

Tsè tanto più grande quanto più piccolo

è l’intervallo di campionamento. Molto spesso nella pratica il valore assunto da questo parametro è tale per cuiil micro non riesce a gestirlo con le normali variabili. Inoltre, se sommato alla parte proporzionale e integrale,questo termine è ordini di grandezza più elevato e vanifica l’effetto degli altri parametri.

Studiando invece la funzione con il polo in alta frequenza (equazione 5.3) si ottiene:

RD(z) = KD2Ts

(z − 1z + 1

)1

2Ts

(z−1z+1

)Td

N + 1= KD

2Ts

z − 1

z

(TdN

2Ts

+ 1)

︸ ︷︷ ︸a

+(

1− TdN

2Ts

)︸ ︷︷ ︸

b

= KD2Ts

z − 1za + b

(5.6)da cui si ottiene la relazione

uD(z) =2KD

aTs

(1− z−1

)e(z)− z−1 b

auD(z−1) (5.7)

Ora il termine moltiplicativo della differenza è 2KD

aTsrisulta molto più contenuto in quanto a e T−1

s hanno circalo stesso ordine di grandezza. Ciò rende il sistema più semplice da trattare dal punto di vista numerico anche perun micro processore. Tutto ciò sarà più chiaro in fase di scrittura del codice, ma fin d’ora è possibile sostituirealcuni plausibili valori per vedere le differenze numeriche dei coefficienti. Per esempio supponendo coefficientiKP = 2, KI = 500, KD = 1 e un tempo di integrazione pari a Ts = 50µs si avrebbe nel primo caso2KD

Ts= 40000, mentre nel secondo caso, se per esempio N = 10, Td = KD

KP= 0, 5, a = 2001, b = −1999 e

2KD

aTs= 19, 99; le grandezze sono decisamente più consone al micro processore.

Metodo 2: discretizzazione della funzione Z totale

In questo caso si considera la funzione equivalente che esprime il regolatore PID. Partendo dalla funzione tipica(ossia P+I+D) si ha, trasformando con Tustin, la seguente relazione:

RPID(z) = KP + KITs2

z + 1z − 1

+ KD2Ts

z − 1z + 1

= (5.8)

=KP (z2 − 1) + Ts

2 KI(z + 1)2 + 2Ts

KD(z − 1)2

z2 − 1=

=z2

(KP + Ts

2 KI + 2Ts

KD

)+ z

(TsKI + 4

TsKD

)+

(Ts

2 KI + 2Ts

KD

)z2 − 1

=

(KP + Ts

2 KI + 2Ts

KD

)+ z−1

(TsKI + 4

TsKD

)+ z−2

(Ts

2 KI + 2Ts

KD

)1− z−2

ma anche in questo caso è evidente che se i tre coefficienti non sono di ordine di grandezza paragonabile, itermini di questa relazione sono difficilmente gestibili in quanto tutti i coefficienti moltiplicativi della variabilez, presentano il coefficiente KD diviso per Ts. Ricalcando l’esempio precedente in cui KP = 2, KI = 500,KD = 1 è chiaro che KD

Ts KP TsKI e quindi il termine proporzionale e ancora di più quello integrale per

essere valutati richiederebbero precisioni molto elevate.

Viste le considerazioni fatte per il metodo 1, anche in questo caso si terrà in considerazione il polo in alta

Page 78: Dispensa PID

78 CAPITOLO 5. REGOLATORE PID

frequenza. La funzione tempo-continua diventa quindi la seguente:

R(s) =KP s + KI

s+

sKD

sTd

N + 1=

s2(KD + Td

N KP

)+ s

(KP + Td

N KI

)+ KI

s2 Td

N + s=

s2a + sb + c

s2 Td

N + s(5.9)

Procedendo con la trasformazione di Tustin si ottiene:

RPID(z) =4T 2

s

(z−1z+1

)2

a + 2Ts

(z−1z+1

)b + c

4T 2

s

(z−1z+1

)2Td

N + 2Ts

(z−1z+1

) =4T 2

s(z − 1)2 a + 2

Ts

(z2 − 1

)b + c (z − 1)2

4T 2

s(z − 1)2 Td

N + 2Ts

(z2 − 1)=

=z2

(a 4T 2

s+ b 2

Ts+ c

)+ z

(2c− a 8

T 2s

)+

(a 4T 2

s− b 2

Ts+ c

)z2

(4Td

NT 2s

+ 2Ts

)− z

(8Td

NT 2s

)+

(4Td

NT 2s− 2

Ts

) (5.10)

Anche in questo caso a, b e c (legate ai coefficienti del regolatore) sono confrontabili, quindi tutti i termini chepresentano T 2

s a numeratore sono termini preponderanti.

5.3 Regolatore PID di corrente

Il regolatore PID che verrà presentato, mira a risolvere un problema nato nel sistema di controllo di un levitatoremagnetico EMS con doppia bobina studiato in [5] e [6]. Senza entrare troppo nel dettaglio della macchina inesame, basti sapere che il levitatore è costituito da due espansioni esapolari e su ogni polo è montata una bobinadi polarizzazione e una di regolazione. Tutte le bobine dei sei poli sono connesse in serie. Inoltre per quantoriguarda la polarizzazione gli avvolgimenti di entrambe le espansioni esapolari sono a loro volta connesse in serie.Ovviamente ciò non è stato fatto per la regolazione in quanto essa deve funzionare in modo indipendente per ilcontrollo di ciascun traferro. La bobina di polarizzazione ha il compito di sostenere il flusso magnetico al traferroe il regolatore ha il compito di mantenere costante la corrente in questa bobina. In figura5.1 è rappresentatoun singolo polo e le equazioni relative ai due avvolgimenti. Senza scomodare tutti i modelli studiati in [6], siconsideri un singolo avvolgimento come un induttore accoppiato ad un altro in una configurazione tale per cui ilflusso che si concatena con le spire dell’avvolgimento possa variare a fronte fondamentalmente di due fenomeni:il primo è la variazione di traferro che provoca una variazione di tipo mozionale (infatti l’induttanza è funzionedel traferro δ), mentre il secondo è legato alla regolazione la quale per stabilizzare il sistema deve generare unacorrente che è sì mediamente costante, ma istantaneamente ha variazioni difficilmente prevedibili.

Dei due problemi elencati, il primo è trascurabile perché se il sistema funziona correttamente, il traferro ètendenzialmente costante o comunque i movimenti sono molto piccoli e non troppo rapidi6 e quindi i termini mo-zionali non sono significativi. Il secondo termine è invece complesso da gestire e causa grandi interferenze anchea frequenze maggiori di 1 kHz. Utilizzando un PI questi disturbi sono particolarmente visibili e l’accoppiamentoè tale che tende ad instabilizzare il sistema se il controllo non è fatto adeguatamente.

Per questo motivo si è scelto di utilizzare un PID. Un PID ha tendenzialmente lo svantaggio di amplificarei disturbi sul riferimento. Tali disturbi derivano normalmente dall’accoppiamento dei conduttori che colleganosensore e micro-processore. Nonostante ciò si presuppone che il sistema sia schermato e filtrato adeguatamente.Detto questo, prima di valutare i reali vantaggi di un PID in questo sistema è bene definire il modello (sempli-ficato) del sistema che si vuole controllare. Banalmente il sistema viene analizzato come un semplice circuito

6Oscillazioni stimate intorno alla decina di Hz.

Page 79: Dispensa PID

5.3. REGOLATORE PID DI CORRENTE 79

(a) Polo centrale di una espansione esapolare

A fronte di ragionavoli ipotesi sulla linearitàdel circuito magnetico, un possibile modo didescrivere il sistema è il seguente:

vp = Rpip + ddt

ψp︷ ︸︸ ︷(Lp(δ)ip + Lm(δ)ir)

vr = Rrir + ddt (Lr(δ)ir + Lm(δ)ip)︸ ︷︷ ︸

ψr

Figura 5.1: Singolo polo EMS con bobine di regolazione e polarizazione.

R-L7 al quale però è sommato un disturbo sotto forma di forza elettromotrice (e(t)) variabile con legge ignotanel tempo:

vp = Rpip + Lpd

dtip + e(t) (5.11)

schematizzabile come in figura 5.2.

G(s) =1

Rp + sLp

Rp = 0.42Ω

Lp = 0.0983H

Figura 5.2: Schema a blocchi relativo al controllo del sistema descritto dall’equazione 5.11.

Per studiare l’effetto del regolatore sul sistema visto dall’ingresso e(t), ossia dal disturbo, è sufficiente studiarela funzione di trasferimento seguente:

I(s)e(s)

=G(s)

1 + G(s)R(s)(5.12)

Ora si considerino i regolatori PI e PID classici (ossia senza poli in alta frequenza). La funzione di trasferimentodel disturbo in funzione dei due tipi di regolatori è fondamentalmente la stessa:

ss2LP +s(R+KP )+KI

per regolatore PIs

s2(Lp+KD)+s(R+KP )+KIper regolatore PID

In entrambi i casi si nota una s a numeratore. Ciò implica che il sistema tende a derivare il disturbo. Se ildisturbo fosse a gradino ciò è benefico perché annullerebbe il valore del disturbo a regime, ma se presentasse

7Con L si intende l’auto induttanza di polarizazione equivalente dei dodici poli vista ai morsetti di ingresso e uscita dell’indutore in esamecalcolata al traferro di 4mm.

Page 80: Dispensa PID

80 CAPITOLO 5. REGOLATORE PID

delle armoniche, queste verrebbero amplificate (in quanto derivate) anche se la retroazione tende ad attenuarequesto fenomeno. Fermo restando quanto detto si osservino allora i termini a denominatore: si nota che a pariKP e KI , l’aggiunta del derivativo aumenta l’inerzia (in termini elettrici) del sistema. Ciò implica che a frontedi un gradino, il disturbo si annullerà presentando oscillazioni di durata leggermente superiore, ma più contenutein termini di ampiezza.

5.3.1 Progetto del regolatore

La determinazione di parametri come già accennato in precedenza non è semplice se effettuata in anello chiuso.Quindi in questo caso il metodo di progetto è stato un po’ più spartano. Per prima cosa non si è tenuto conto deltermine in alta frequenza in quanto esso dipende dai termini KP e KD, quindi verrà determinato di conseguenzauna volta trovati gli altri coefficienti. Detto ciò si è proceduto fissando i coefficienti KP e KI (noti già dallapratica per le prove fatte con il regolatore PI) e successivamente si è cercato di scegliere un KD al massimo pari a1 che permettesse di ottenere una risposta con una banda passante maggiore o uguale a 1000 rad/s. I coefficientitrovati sono KP=10, KI=1000, KD=1. Successivamente è stato scelto il coefficiente N necessario per il polo inalta frequenza (equazione 5.3) anche in relazione a come verrà scritto il codice. Si noti fin d’ora che maggioreè N , migliore è il comportamento in quanto il regolatore si comporta da come un PID “puro” in una gamma difrequenze maggiore, ma di contro i numeri da gestire, soprattutto a livello digitale, sono molto più elevati. Insimulazione un giusto compromesso è sembrato i coefficiente N=10.

Il regolatore così realizzato è caratterizzato da un banda passante pari a ωt=1110 rad/s e un margine di faseφm=94. Per valutare meglio il comportamento del regolatore PID così ottenuto, si consideri un regolatore PIottenuto in forma chiusa con la stessa banda passante e margine di fase φm=908. Da ciò si otterrebbero i valoriKIpi=466,2 e KPpi=109,16. Il diagramma di Bode di L(s) = RPID(s)G(s) e LPI(s) = RPI(s)G(s) ossiale funzioni di anello date rispettivamente dal regolatore PID e PI sono riportate in fgura 5.3; in questa figura èriportato anche l’andamento della funzione d’anello ottenuta dal regolatore PI ottenuto dagli stessi coefficientiintegrale e proporzionale del regolatore PID. Si osserva che tutti gli andamenti sono stabili in anello chiuso edin particolare PIpi e PID coincidono in alta frequenza. Osservando poi la risposta in frequenza della funzione ditrasferimento tra uscita e disturbo relativa alla funzione d’anello L(s) ottenuta con regolatore PI e PID (figura5.4) si osserva che per disturbi di qualche decina di Hz il sistema con PID attenua un po’ meglio, ma per le altrefrequenze il regolatore PI sembra nel complesso migliore.

Da questa analisi può sembrare che non vi sia motivo di utilizzare un PID per il controllo, ma che convengaconcentrarsi su un regolatore PI. In realtà così non è perché i problemi reali si hanno quando si va a creare ilregolatore digitale (cioè quando lo si sintetizza in C) nel quale il termine KP di valore superiore a 100 e KI dicirca 450 causano alcuni problemi di calcolo. Il termine proporzionale è molto alto e quindi tende a dare in uscita,a fronte per esempio di piccoli errori in ingresso, grandi variazioni di duty-cycle, mentre l’integrale è tale per cui iltermine KI = KI

Ts

2 è piccolissimo; talmente piccolo che in alcune versioni del programma era stato addiritturaeliminato trasformando di fatto il regolatore in un semplice proporzionale9: introdurre tale termine, anche sepiccolissimo, comportava normalmente l’instabilità del sistema sia in simulazione sia sul campo. Adottare invecela soluzione PID permette di avere termini nel complesso più gestibili. In realtà anche il PID presenta questiproblemi se non venisse implementato senza polo in alta frequenza. A tal proposito si tenga sempre presente chese il fattore N aumentasse, il coefficiente derivativo digitale aumenterebbe anch’esso in modo proporzionale.

8Si osservi che se fosse φm = 94, determinando KI e KP in forma chiusa si otterrebbe un KI negativo e quindi il sistema sarebbeinstabile. Porre φm = 90 migliora comunque la risposta almeno in termini di fase.

9Tra le varie versioni fatte ve n’era una in cui il regolatore era un semplice P in cascata ad un filtro passa-basso (ovviamente digitale) chetagliava frequenze molto alte. Questo risolse molti problemi, ma presentava comunque oscillazioni di ampiezza rilevante sulla corrente diuscita.

Page 81: Dispensa PID

5.3. REGOLATORE PID DI CORRENTE 81

blu - PI ottenuto dai coefficienti PID, verde - PI con la stessa ωt di PID, rosso - PID

Figura 5.3: Diagramma di Bode delle funzioni d’anello ottenute con regolatori PI e PID.

Figura 5.4: Risposta in frequenza della funzione di trasferimento tra uscita I(s) e disturbo e(s).

5.3.2 Simulazione del regolatore digitale

La simulazione deve ovviamente rispettare il più possibile la configurazione del caso reale. Si noti a tal propositoche il sistema di controllo PID è stato sviluppato per essere particolarmente reattivo: mentre tutto il sistema ècontrollato con PWM a 20kHz, il PWM del regolatore di polarizzazione viene gestito a 40kHz. Il periodo diPWM è anche il tempo di integrazione che in questo caso sarà quindi pari a Ts=25µs.

La simulazione verrà condotta come al solito confrontando la soluzione tempo-continua (s), tempo-discreta(z) e digitale (C SIMULINK) usando il modello in figura 5.5. Il disturbo verrà posto all’interno del regolatore come

Page 82: Dispensa PID

82 CAPITOLO 5. REGOLATORE PID

indicato. Il metodo di implementazione segue il primo metodo di discretizzazione (sezione 5.2) del regolatore,ossia i termini P, I e D sono valutati separatamente.

Figura 5.5: Modello per la simulazione PID.

Implementazione classica del regolatore

L’implementazione classica prevede di scrivere il regolatore basandosi sulla funzione z. Si osservi fin d’ora chetutti e tre i regolatori non presentano soglie sull’uscita. Ciò è legato fondamentalmente al fatto che porre un antiwind-up poteva complicare almeno inizialmente le cose, senza una reale utilità in quanto le saturazioni sarà sìbene tenerle in considerazione, ma in fase di implementazione su micro-processore. Scopo di queste simulazioniè riuscire a sintetizzare il regolatore in modo corretto e vedere quali sono le problematiche (soprattutto di calcolo).Il codice è il seguente:

/* DEFINIZIONI */#define I_REALE u0[1]#define I_RIF u0[0]#define OUP 7373 /*=90V*/#define ODW -OUP#define IUP 1887400 /* =OUP*2^8 */#define IDW -IUP#define DUP OUP /* Soglia del derivativo */#define DDW -DUP/*MACRO*/#define KP(e)((e*10))#define KI(e)((e*3)+(e>>3)+(e>>4))#define KIS 8#define KD(e)((e*799))#define B_A(ba)((ba)-(ba>>7)+(ba>>8)+(ba>>10)+(ba>>11))#define KDS 3short int error, error_1=0, proporzionale;long int integrale=0, derivata=0;

Page 83: Dispensa PID

5.3. REGOLATORE PID DI CORRENTE 83

/* --- FUNZIONE DI REGOLAZIONE --- */short int error_i, error_d, dc;double out; /* è a 32bit perché 4096*10+7373+7373 > 2^15 */error = ((I_RIF-I_REALE)*8);error_i = error+error_1;error_d = error-error_1;error_1 = error;/* PROPORZIONALE */proporzionale = KP(error);/* INTEGRALE */if(error_i>=0) integrale+=KI(error_i);

else integrale-=KI((-error_i));/* DERIVATIVO */if (derivata>=0) derivata=B_A(derivata); /*Per prima cosa ’peso’ subito la derivata... */

else derivata=-(B_A((-derivata)));derivata += KD(error_d); /*...poi aggiungo il nuovo termine *//* OUT */out=(derivata>>KDS)+proporzionale+(integrale>>KIS); /* sarebbe meglio fare il cast a long */y0[0]=out;y0[1]=(y0[0]*50)/4096;y0[2]=error;y0[3]=proporzionale;y0[4]=integrale>>KIS;y0[5]=derivata>>KDS;

Leggendo il codice si possono trovare alcune definizioni riguardo le soglie che però non vengono utilizzate.Come noto la macro KP non altera il coefficiente a differenza di KI e KD. Essendo KI=KI

Ts

2 =0,0125 si è preferitomoltiplicarlo per 256 (28) portandolo KI=3,2 per aumentarne la precisione; è esattamente quanto fatto per ilregolatore di corrente PI (paragrafo 3.3.1) anche se in quel caso il termine KI è stato maggiorato di 212. Perquanto riguarda il termine KD esso è pari a KD=KD

2Tsa

'99,875; potrebbe sembrare insensato maggiorare questovalore, ma così è stato fatto. Precisamente è stato maggiorato di 23. Questo perché il termine derivativo èaccompagnato dal termine B_A il quale è negativo e in valore assoluto è pari a 0,9975. Da questo termine èrichiesta la massima precisione possibile! più si riesce a renderlo in maniera precisa, più fedele sarà la risposta.Si osserva che questo valore va a riscalare (pesare) il valore al passo precedente della derivata, quindi il risultatodi tale operazione è un numero nella stessa base della derivata e per questo non può essere riscalato. Detto ciò èchiaro che conviene riscalare il termine derivativo che in questo caso è pari a KD=KD

24

Tsa'99,875·23=799; ora la

derivata è un valore in base 11 bit. Tornando un momento sul termine B_A si è detto che il suo valore è negativo.Leggendo il codice, però si nota come questo termine venga gestito come termine positivo. Questo perché se sivaluta l’espressione 5.7 si osserva che il termine viene sottratto per ottenere il risultato voluto e quindi è comegestire un fattore positivo.

I riscalamenti introdotti su proporzionale e integrale fanno sì che le variabili derivata e integrale deb-bano essere a 32 bit. É chiaro che quando l’uscita verrà calcolata (out), le grandezze dovranno essere riportatein base 12 bit mediante appositi shift.

Per quanto riguarda le varie grandezze portate in uscita (y0[0], y0[1], ecc) servono solo per attività didebug.

In figura 5.6 sono riportati gli andamenti di corrente circolante nel sistema e tensione in uscita dal regolatorea fronte di un ingresso a gradino con disturbo di tensione pari ad una sinusoide di ampiezza 30V e frequenza1000rad/s. Mentre in uscita gli effetti del disturbo sono trascurabili, sulla tensione si vede che vi è una armonicache mira ad eliminare gli effetti del disturbo e. Si nota inoltre che all’inizio vi è un impulso di tensione cheraggiunge circa i 2700V. É chiaro che nel caso reale occorrerà prevedere una saturazione.

Come si vedrà in seguito un valore elevato di N unito al fatto che vengano fatte determinate scelte su comecalcolare la derivata, potrebbe provocare alcuni problemi a livello computazionale risolvibili per esempio dimi-

Page 84: Dispensa PID

84 CAPITOLO 5. REGOLATORE PID

Figura 5.6: Riferimento a gradino con disturbo sinusoidale a 1000rad/s di ampiezza 30 V.

nuendo N . Se si volesse ridurre il coefficiente N per esempio a 5 ne conseguirebbe la seguente variazione nelcodice:

#define KD(e)(((e*799)+(e>>1)))#define B_A(ba)((ba)-(ba>>7)+(ba>>8)+(ba>>9)+(ba>>11))#define KDS 4

Queste macro sono legate al fatto che KD=49,9688 e viene maggiorato di 24, mentre ba=-0,9988. Dal punto di

vista delle simulazioni non vi sono cambiamenti sensibili.

Implementazione del regolatore con derivata a 20Ts

In altri casi affrontati sul levitatore si è visto che spesso il sensore introduce degli errori spesso causati da in-terferenze ed accoppiamenti. Ciò non causa tendenzialmente problemi in un controllo PI, ma può causarne perla parte derivativa. Supponendo ora che il derivativo sia molto elevato è facile prevedere che si possano averegrandi escursioni del duty-cycle a fronte di errori molto piccoli. Di contro esiste anche il problema opposto. Seil derivativo è molto piccolo e il sistema presenta inerzie molto alte è probabile che tra un quanto di tempo (Ts) el’altro vi siano variazioni talmente piccole che non possano essere valutate. In entrambi i casi, quindi, si rischie-rebbe esclusivamente di derivare il rumore il quale tipicamente è ad alta frequenza e quindi può dare contributisignificativi.

Tra le varie soluzioni provate per ovviare al problema, quella che ha dato i migliori risultati è di considerarela derivata in una scala temporale diversa, ossia all’errore attuale deve essere sottratto non al valore precedente,ma al valore di n volte precedenti, per esempio 20; con un intervallo di 20 campioni la finestra temporale su cuiviene effettuata la derivata è pari a Tsn=20·25µs=500µs. Quindi ricalcolando l’equazione 5.6 con Tsn al postodi Ts si ottengono i seguenti coefficienti:

KD=49,3827 ba=-0,9753 a=81 b=-79

Attenzione però che questi valori sono stati ottenuti con N=5. Si è notato che aumentando N si hanno problemidi integrazione che provocano oscillazioni non accettabili. Ciò è dovuto al termine B_A: annullandolo, infatti, ilsistema torna ad avere una risposta corretta nel senso che arriva a regime e l’errore statico è nullo, mal’andamento della risposta è ben diverso da quello del regolatore z. Probabilmente questo è dovuto al fatto chetutti i termini che costituiscono le grandezze derivative (ossia KD e B_A) richiedono di rappresentare i coefficienticalcolati nel modo più preciso possibile; anche piccole variazioni possono dare risultati completamente errati.

Page 85: Dispensa PID

5.3. REGOLATORE PID DI CORRENTE 85

Il codice proposto di seguito realizza quanto detto:

/* DEFINIZIONI */#define I_REALE u0[1]#define I_RIF u0[0]#define OUP 7373 /*=90V*/#define ODW -OUP#define IUP 1887400 /* =OUP*2^8 */#define IDW -IUP #define EDTHUP 147 /* 7373/KD = Soglia errore derivativo */#define EDTHDW -EDTHUP#define DUP OUP /* Soglia del derivativo */#define DDW -DUP/*MACRO*/#define KP(e)((e*10))#define KI(e)((e*3)+(e>>3)+(e>>4))#define KIS 8#define KD(e)(((e*790)+(e>>3)))#define B_A(ba)((ba)-(ba>>5)+(ba>>8)+(ba>>9)+(ba>>11))#define KDS 4#define ND 20 /*Campioni x la derivazione */short int error[ND], error_1=0, proporzionale;long int integrale=0, derivata=0;

/* --- FUNZIONE DI REGOLAZIONE ---*/

short int error_i, error_d, dc, i;double out; /* è a 32bit perché 4096*10+7373+7373 > 2^15 */for(i=ND-1; i>0; i--)

error[i]=error[i-1]; /* sposto tutti i termini precedenti */error[0] = ((I_RIF-I_REALE)*8);error_i=error[0]+error[1]; /* errore integrale */error_d=error[0]-error[ND-1]; /* errore derivativo *//* PROPORZIONALE */proporzionale = KP(error[0]);/* INTEGRALE */if(error_i>=0) integrale+=KI(error_i);

else integrale-=KI((-error_i));/* DERIVATIVO */if (derivata>=0) derivata=B_A(derivata); /*Per prima cosa ’peso’ subito la derivata... */

else derivata=-(B_A((-derivata)));derivata += KD(error_d); /*...poi aggiungo il nuovo termine */

/* OUT */

out=(derivata>>KDS)+proporzionale+(integrale>>KIS);y0[0]=out;y0[1]=(y0[0]*50)/4096;y0[2]=error[0];y0[3]=proporzionale;y0[4]=integrale>>KIS;y0[5]=derivata>>KDS;

Il codice è sostanzialmente uguale al precedente tranne per il fatto che error_d viene calcolato con il valoreattuale e il valore di 20 passi prima. É chiaro che per fare ciò occorre memorizzare tutti i termini fino al ventesimoe tramite il ciclo for i termini vengono spostati indietro di una posizione aggiornando così ad ogni ciclo (ossiaogni Ts) la finestra temporale per eseguire la derivata.

Per quanto riguarda i risultati essi sono soddisfacenti, ma è possibile comunque identificare dei problemi all’i-nizio del gradino e sul fatto che la risposta non è fedele a quella della soluzione con il regolatore in z-trasformata,in quanto quest’ultimo è sviluppato considerando un intervallo di tempo pari a Ts, mentre il regolatore digita-le effettua la derivata a 20Ts. In figura 5.7-a è riportato il comportamento del sistema con ingresso a gradino,ma senza disturbo, mentre in 5.7-b è stato aggiunto un disturbo sinusoidale di 30V a 100rad/s. Chiaramentel’andamento tra regolatore z (rimasto invariato) e regolatore C sono diversi.

Page 86: Dispensa PID

86 CAPITOLO 5. REGOLATORE PID

(a) Nessun disturbo (b) Disturbo sinusoidale: 30V - 100rad/s

Figura 5.7: Risposta con regolatore ottenuto con N=5 e derivata su 20 campioni.

5.3.3 Implementazione su micro-processore dsPIC30F

Anche questa volta il codice implementato è scritto in C orientato al compilatore C30 di MICROCHIP. I files diprogetto sono i seguenti:

global.h definisce le principali variabili e definizioni di costanti comuni a tutti i files.

init.h file di intestazione delle funzioni di inizializzazione. Contiene le dichiarazioni delle funzioni diInitPORT(), InitPWM(), InitADC() ed eventuali macro.

init.c file C di implementazione delle funzioni di inizializzazione.

pid.h file di intestazione contenente le dichiarazioni e macro necessarie per effettuare la routine di regola-zione.

main_Polarizzazione.c file C principale. Contiene la funzione main e le funzioni di interrupt.

Per quanto riguarda la configurazione delle periferiche e la determinazione delle scadenze temporali, si osserviche non è cambiato nulla dal sistema descritto al capitolo 4. Anche la formula per il calcolo del periodo di PWM(4.1) non è cambiata anche se in questo caso il PLL rispetto al caso precedente (figura 4.6) adesso il PLL è pari ax16. Però si è detto che la frequenza di commutazione è stata portata a 40 kHz quindi l’equazione 4.1 risulta:

PTPER =7372800

2 · 4· 1640000

+ 1 = 368

Codice C

Si consiglia di leggere il codice seguente tenendo sempre a portata di mano [4], quanto meno per capire quali sonole procedure necessarie per la configurazione e la gestione delle periferiche. Si noti che il codice seguente nascedalla raffinazione di altre versioni del codice, quindi potrebbero esserci definizioni e variabili che non vengonousate nel codice vero e proprio. Infine si osservi che il codice è relativo alla derivata calcolata con polo in altafrequenza con N=5 e una maggiorazione del coefficiente derivativo di 24 per contenere le variazioni sul piccoloerrore, come detto in precedenza.

Page 87: Dispensa PID

5.3. REGOLATORE PID DI CORRENTE 87

=======================

global.h

#ifndef __GLOBAL_H__#define __GLOBAL_H__#include <p30f4012.h>#define ON 1#define OFF 0/* Logica di controllo dei LED inversa */#define LED_VERDE_ON _RE5=0b0#define LED_VERDE_OFF _RE5=0b1#define LED_ROSSO_ON _RE4=0b0#define LED_ROSSO_OFF _RE4=0b1#define CLOCK 7372800 //Clock esterno, come sulle schede di valutazione#define NBIT 12#define NBIT2 13#define NBASE 4095#define NBASE2 8191 #defineNBASE3 16383 #defineNBASE24 16777000 //in realtà 2^24=16777261#define FREQ 40000 //40KHz#define PER 0.000025 //Periodo#define DUTYCYM (int)736 //DC massimo in unipolare singola gamba#define DUTYCY PERIODO //DC massimo in unipolare doppia gamba#define DUTYCYUP 332 //Saturazione UP di duty-cycle#define DUTYCYDW -332 //Saturazione DW di duty-cycle#define OFFSET_I 518 //Offset delle correnti per riportarle allo 0#define CORRENTEP ADCBUF0 //an0!#endif //end of __GLOBAL_H__

=======================

init.h

#ifndef __INIT_H__#define __INIT_H__#define TRIGGER_AD_PWM 0b011#define TRIGGER_AD_TMR3 0b010#define TRIGGER_AD_AD 0b000#define CHANNEL4 0b11#define CHANNEL2 0b01#define CHANNEL1 0b00extern void InitTIMER(unsigned int nStep); //Non serve in questo programmaextern void InitPORT();extern void InitPWM(int nleg, unsigned char interrupt_enable);extern void InitAD(unsigned char, unsigned char, unsigned char, unsigned char);#endif //__INIT_H__

=======================

init.c

#include <p30f4012.h>#include "Init.h"#include "Global.h"/** Inizializzazione delle PORTE (I/O, digitali/analogiche **/void InitPORT()

TRISD=0x0000;PORTD=0xFFFF;TRISB=0xFFFF;TRISE=0x0080;PORTB=0xFFFF;PORTE=0xFFFF; //Sulle mie schede i led e i pulsanti sono in logica inversaADPCFG=0x0000;

Page 88: Dispensa PID

88 CAPITOLO 5. REGOLATORE PID

/** Inizializza il PWM *******************************************************************Il parametro in ingresso nleg determina quante gambe voglio abilitare in modo indipendente

******************************************************************************************/void InitPWM(int nleg, unsigned char interrupt_enable)

PTPER=PERIODO; //Attenzione a _PTMOD!!! che influenza PTPER se >= 0b10PTCONbits.PTMOD=0b10; //Free Running Mode=0b00, Continuous Up/Dw=0b10PTCONbits.PTOPS=0b0000; //PostscalerPTCONbits.PTCKPS=0b00; //PrescalerPTCONbits.PTSIDL=0b0;PTCONbits.PTEN=0b1;PWMCON1=0x0000;if(nleg>0)

PDC1=0; //duty cycle per PWM1 16bit, quindi duty=50%->PDCx=PTPERPWMCON1bits.PMOD1=0b1; //Indipendent mode 0=off, 1=onPWMCON1bits.PEN1H=0b1; //Abilito la gamba altaPWMCON1bits.PEN1L=0b1; //Abilito la gamba bassa

if(nleg>=2)

PDC1=DUTYCY; //se ’2’ è perché controllo il ponte ad HPDC2=DUTYCY; //duty cycle per PWM1 16bit, quindi duty=50%->PDCx=PTPERPWMCON1bits.PMOD2=0b1; //Indipendent mode 0=off, 1=onPWMCON1bits.PEN2H=0b1; //Abilito la gamba altaPWMCON1bits.PEN2L=0b1; //Abilito la gamba bassa

if(nleg>=3)

PDC3=0; //duty cycle per PWM1 16bit, quindi duty=50%->PDCx=PTPERPWMCON1bits.PMOD3=0b1; //Indipendent mode 0=off, 1=onPWMCON1bits.PEN3H=0b1; //Abilito la gamba altaPWMCON1bits.PEN3L=0b1; //Abilito la gamba bassa

FLTACON=0x0000;_PWMIF=0;_PWMIE=(interrupt_enable&0x1);

void InitAD( unsigned char trigger_AD, unsigned char ADCS_delay,

unsigned char ingresso, unsigned char channel )

/* Le tabelle di configurazione sono da pagina 420 in poi del Manual Family [4]. */

ADCHS=0;

ADCHSbits.CH0SA=ingresso&0x0F; //ingressi AN0->CH1=>ADCBUF1, AN1->CH0=>ADCBUF0

_SIMSAM=0b1; //se 1 -> simultaneous sampling

_SMPI=0b000; //Interrupt dopo ogni campionamento se 0switch(trigger_AD) case TRIGGER_AD_PWM:

_SSRC=TRIGGER_AD_PWM; //011=PWM trigger eventbreak;

case TRIGGER_AD_TMR3:_SSRC=TRIGGER_AD_TMR3; //Timer3 trigger eventbreak;

default:_SSRC=TRIGGER_AD_AD; //ogni fine conversione l’AD si autoriattiva

_ASAM=0b1; //Automatic sample_CSCNA=0b0; //Disabilito lo scanning dei sample/hold se 0_ALTS=0; //Alternate MUX Sampling disabilitatoADCON2bits.CHPS = channel&0x03; //00=S/H su CH0, 01=S/H su CH0 e CH1, 1x tutti

//---Questi sono flag per PWM---//SEVTCMPbits.SEVTCMP=0;SEVTCMPbits.SEVTDIR=0b0;_SEVOPS=0b0000; //se 1,ogni 2 PWM scatta l’int AD

//------------------------------//ADCON3bits.SAMC = 1; //tempo minimo di sampleADCON3bits.ADCS = ADCS_delay&0x3F; //Setta il minimo tempo per la conversione A/D.ADPCFGbits.PCFG0 = 0;ADPCFGbits.PCFG1 = 0;ADPCFGbits.PCFG2 = 0;_ADIE=1; _ADIF=0;

Page 89: Dispensa PID

5.3. REGOLATORE PID DI CORRENTE 89

_ADON=0b1; //Attivo l’ADON

=======================

pid.h

#define CURRENT_BASE 50 //lem da 25A con una 2 spire ->50A teorici, 40 saturati#define OFFSET_CURRENT 512#define INITIAL_CURRENT 0 //eventuale valore iniziale della corrente#define CURRENT_RIF 2047 //2047=25A/***** PID di corrente *********/#define PROPORZIONALEI(e)((e*10))#define INTEGRALEI(e)((e*3)+(e>>3)+(e>>4))#define KIS 8 //shift per l’integrale#define KD(e)(((e*800)-(e>>1))) //con 400 o 500 forse è meglio#define B_A(ba)((ba)-(ba>>7)+(ba>>8)+(ba>>9)+(ba>>11))#define KDS 4 //shift per la derivata//---------SOGLIE------------//#define OUP 7373 /*=90V -> 90/50*4096*/#define ODW -OUP#define IUP 1887400 /* =OUP*2^8 */#define IDW -IUP#define DUP OUP /* Soglia del derivativo */#define DDW -DUP/********** CHECK DUTY-CYCLE *************/#define DCUP 699 //perdo il 5% della tensione x sicurezza #define DCDW 37/********** MACRO DI RIPORTO DEL DC **************/#define V_OFFSET 4097

#define GET_DC(v_digit)((v_digit>>4)+(v_digit>>6)+(v_digit>>7)+(v_digit>>8))

Rispetto alle simulazioni sono state aggiunte le soglie per variabili di uscita, integrale e derivata, oltre alla acroGET_DC per il calcolo del valore digitale del duty-cycle.

=======================

main_Polarizzazione.c

#include <p30f4012.h>#include "Global.h"#include "Init.h"#include "pid.h"/***** Global *****************/int errorI, errorI_1=0, proporzionale, correnteIp, riferimentoIp=CURRENT_RIF, vd_out;long int integrale=INITIAL_CURRENT, derivata=0;/******************************//********* MAIN *******************/int main()

InitPORT();InitPWM(2,OFF);LED_VERDE_ON;while(_RE8); //fino a che resta tutto in stop o nn premo RE8 nn fare nullaNop();while(!_RE8);LED_VERDE_OFF;InitAD(TRIGGER_AD_PWM,10,0,CHANNEL1);LED_ROSSO_ON;while(1);

/**********************************//****************************

Interrupt SubRoutine

****************************/void _ISR _ADCInterrupt()

Page 90: Dispensa PID

90 CAPITOLO 5. REGOLATORE PID

int dc, dcaux, errorIi, errorId;_RD0=1; //Flag per la misura dei tempi di esecuzione

/***************************************************REGOLATORE DI CORRENTE: metodo dei trapezi

***************************************************/correnteIp=((CORRENTEP-OFFSET_I))<<3; //riporto la corrente a 12biterrorI=(riferimentoIp-correnteIp); //calcolo l’errore

//INTEGRALEerrorIi=errorI_1+errorI;errorId=errorI-errorI_1;if(errorIi>=0)

integrale+=INTEGRALEI(errorIi);else

integrale-=INTEGRALEI((-errorIi));//PROPORZIONALE

proporzionale=PROPORZIONALEI(((long int)errorI));//DERIVATA

if(derivata>=0) derivata=B_A(derivata);else derivata=-(B_A((-derivata)));

derivata+=KD(errorId);//CALCOLO DELL’USCITA

vd_out=(derivata>>KDS)+proporzionale+(integrale>>KIS);if(vd_out>OUP) vd_out=OUP;

else if(vd_out<ODW) vd_out=ODW;/***************************************************

USCITA riportata sul DC

***************************************************/vd_out+=V_OFFSET; //porto il valore da 0 a 8191 (->13bit)dc=GET_DC(vd_out);if(dc>DCUP) dc=DCUP;

else if(dc<DCDW) dc=DCDW;PDC2=dc;PDC1=DUTYCYM-dc;

/************************************TRATTAMENTO FINALE DELLE VARIABILI

************************************/if(integrale>IUP) integrale=IUP;

else if(integrale<IDW) integrale=IDW;errorI_1=errorI;if(derivata>DUP) derivata=DUP;

elae if(derivata<DDW) derivata=DDW;errorI_1=errorI;_ADIF=0;_RD0=0;

Il codice del regolatore non è molto diverso da quello delle simulazioni. In più a prima si osserva che tramite lamacro GET_DC viene calcolato il termine del duty-cycle (dc) riscalando la grandezza vd_out opportunamentesaturata tra 0 e 736. Una volta ottenuto il duty-cycle questo viene precauzionalmente limitato tra DCDW e DCUPin modo da avere un duty-cycle compreso tra 5% e 95% del dutty-cycle per ogni singola gamba10. Successiva-mente il valore dc viene assegnato ad una gamba (PDC2=dc) mentre il suo complemento vine assegnato all’altra(PDC1=DUTYCYM-dc). Infine, oltre alla saturazione dell’uscita, si procede anche alla saturazione dell’integrale ederivata. Infatti la derivata presenta un termine (B_A) “integrativo” ossia si può dire che anche la derivata è unavariabile “con memoria” in quanto dipende dagli stati precedenti.

=======================

Per quanto riguarda lo sviluppo del codice con derivata ogni 20Ts verranno riportate le modifiche rispetto alcodice precedente:

=======================10Ciò aiuta a evitare che le valvole e/o i driver si danneggino.

Page 91: Dispensa PID

5.3. REGOLATORE PID DI CORRENTE 91

pid.h

.../***** PID di corrente *********/#define PROPORZIONALEI(e)((e*10))#define INTEGRALEI(e)((e*3)+(e>>3)+(e>>4))#define KIS 8#define KD(e)(((e*790)+(e>>3))) //con 500 forse è meglio#define B_A(ba)((ba)-(ba>>5)+(ba>>8)+(ba>>9)+(ba>>11))#define KDS 4#define STEPN 20 //STEP per il calcolo della derivata...

=======================

main_Polarizzazione.c

/***** Global *****************/int errorI[STEPN], proporzionale, correnteIp, riferimentoIp=CURRENT_RIF, vd_out;long int integrale=INITIAL_CURRENT, derivata=0;/***********************************************************/.../****************************

Interrupt SubRoutine

****************************/void _ISR _ADCInterrupt()

int dc, dcaux, errorIi, errorId, i;_RD0=1; //Flag per la misura dei tempi di esecuzione

/***************************************************REGOLATORE DI CORRENTE: metodo dei trapezi

***************************************************/correnteIp=((CORRENTEP-OFFSET_I))<<3; //riporto la corrente a 12bitfor(i=STEPN-1; i>0; i--) errorI[i]=errorI[i-1];errorI[0]=(riferimentoIp-correnteIp); //calcolo l’erroreerrorIi=errorI[0]+errorI[1];errorId=errorI[0]-errorI[STEPN];

//INTEGRALEif(errorIi>=0) integrale+=INTEGRALEI(errorIi);

else integrale-=INTEGRALEI((-errorIi));//PROPORZIONALE

proporzionale=PROPORZIONALEI((errorI[0]));//DERIVATA

if(derivata>=0) derivata=B_A(derivata);else derivata=-(B_A((-derivata)));

derivata+=KD(errorId);// CALCOLO DELL’USCITA

vd_out=(derivata>>KDS)+proporzionale+(integrale>>KIS);if(vd_out>OUP) vd_out=OUP;

else if(vd_out<ODW) vd_out=ODW;...

=======================

Page 92: Dispensa PID

92 CAPITOLO 5. REGOLATORE PID

Page 93: Dispensa PID

Appendice A

Breviario sulla sintassi C

In questa appendice vengono riportate le nozioni base necessarie per la scrittura di un programma in C. Perinformazioni più complete e dettagliate si rimanda comunque alla lettura di un buon libro sui fondamenti del C oalle numerosissime guide su internet come per esempio [L6].

A.1 Tipi di dati

Le informazioni che verranno date di seguito si possono trovare anche nel manuale del compilatore. Nel casodi dsPIC si fa riferimento al manuale del compilatore C30 [3]. Le informazioni sotto riportate sono di caratteregenerale, quindi si consiglia sempre di verificarle con quanto scritto nel manuale del compilatore che si ha indotazione.

Scalari

char 8bit con segno. Usato per i caratteri.

unsigned char 8bit senza segno.

short int 8bit interi con segno. Usato per i numeri. Se il processore è a 32bit, tipicamente short int è a16bit.

unsigned short int 8bit senza segno. Valgono le considerazioni fatte per short int.

int 16bit con segno. Tipicamente è la parola del processore se il processore computa a 16 bit o più. Inaltre parole se il processore è a 8bit, int vale sempre 16, mentre se il processore è a 32 bit, int è a32bit. Se non precisato, in questa sede si assume int pari a 16bit.

unsigned int 16bit con segno. Valgono le considerazioni fatte per int.

long int 32bit con segno. Tipicamente se il processore è a 32bit e int è a 32bit, long int resta comunquea 32 bit.

unsigned long int 32bit senza segno. Valgono le considerazioni fatte per int.

long long int 64bit con segno; con unsigned diventa senza segno.

93

Page 94: Dispensa PID

94 APPENDICE A. BREVIARIO SULLA SINTASSI C

float 32bit in virgola mobile, tipicamente a 64 per sistemi a 32bit. Nel caso del C30 il valore va da 2−126

a 2128.

double 32bit a virgola mobile tipicamente a 64 per sistemi a 32bit. valgono le stesse considerazioni difloat.

long double 64bit in virgola mobile, tipicamente 128 per sistemi a 32bit. il valore va da 2−1022 a 2−1024.Spesso double e long double hanno la stessa lunghezza. Ciò dipende tipicamente dal compilatoreo dai parametri si compilazione.

Per assegnare (o definire) un numero si può ricorrere alle forme seguenti:

c=’A’ assegna un carattere

x=123 assegna un numero espresso in decimale

y=0x3F0 assegna un numero espresso in esadecimale. In questo caso il valore è a 16bit.

z=0b101 assegna un numero espresso in binario.

o=011 assegna un numero ottale.

l=123L assegna un numero di tipo long. Chiaramente se l non è long il compilatore provvederà allacastizzazione.

f=2.344 assegna un numero in virgola mobile (float o double). Si può anche porre una f alla fine perforzare il tipo float, ma il numero deve avere anche il “.” (per esempio 0.1f)

Array

Gli array sono strutture di dati omogenei contigui. Sono definiti come segue:

char string[100]; //definizione stringa di lunghezza 100 byteint vector[10]; //definizione vettore di 10 numeri interi a 16 bit.

string[10]=’X’; //assegnazione del carattere X all’undicesimo carattere

l’incremento dell’indice in string permette di accedere ai vari byte della stringa (ossia ci si sposta di 8bit pervolta), mentre in vector permette di accedere ai vari numeri del vettore (ossia ci si sposta di 16bit per volta).Per accedere ai vari valori è sufficiente scrivere il nome della variabile seguito da un numero che, per esempionel caso della variabile string, va da 0 a 99. I valori negativi non sono accettati, mentre quelli superiori a 99causano i così detti buffer overflow; ciò in un microprocessore si traduce nella sovrascrittura di altre variabili e/oindirizzi di ritorno delle funzioni1

Un array può anche essere definito come un puntatore (pag. 96), ma il metodo per accedervi è il medesimo.É anche possibile definire array di strutture.

1Normalmente in processori come i pic ciò si traduce in un reset. Si osservi che in alcuni micro della serie 18 è possibile, configurandoopportunamente i configuration bits, impedire il reset a fronte di un buffer/stack-overflow.

Page 95: Dispensa PID

A.1. TIPI DI DATI 95

Strutture e unioni

Le strutture sono aree dati formattate (strutturate) in un particolare modo. Tipicamente racchiudono più datispesso di tipo diverso. Si indicano come segue

struct NOME_STRUTTURA tipo NOME_VARIABILE1, NOME_VARIABILE2;tipo NOME_VARIABILE3;

;

dove il NOME_STRUTTURA può anche essere posto alla fine, ossia dopo la parentesi graffa chiusa. Normalmente ladefinizione della struttura è preceduta dalla keyword typdef che permette di definire un nuovo tipo di variabile:

typedef struct tipo NOME_VARIABILE1, NOME_VARIABILE2;tipo NOME_VARIABILE3;

NOME_STRUTTURA ;

Per richiamare la struttura e per accedere ai vari campi si scrive semplicemente:

typedef struct //definizione della strutturaint x; char c; //campi

t_struct; //t_ indica che è un tipo; è una pura convenzione.struct t_struct x,y; //definizione delle variabilix.x=10; //assegno il numero 10;x.c=’x’; //assegno il carattere x

y=x; //copio x in y. Non tutti i compilatori lo accettano.

Spesso però è necessario poter accedere singolarmente ai singoli bit che compongono una struttura. Una strutturacome la seguente permette di fare ciò:

typedef struct unsigned LSB :1; //bit meno significativounsigned BIT2 :1; //2 bitunsigned :2; //2 bit “non indirizzabili”unsigned NIBBLE :4; //4 bit = 1 Nibbleshort int BYTE :8; //byte con segno; :8 in questo caso non è obbligatorio,

//come non è obbligatorio cambiare variabile in short int

t_ComplexStruct;

Così facendo è possibile definire una variabile (in questo caso di 16bit) divisi in vari campi che minimo devonoessere di 1 bit. Ciò risulta molto comodo nei micro controllori.

Dal punto di vista della memoria, una struttura occupa tanti byte quanti quelli delle singole variabili definiteall’interno; per esempio t_struct definita in precedenza occupa 3 byte. Spesso però è utile avere una certa areadi memoria alla quale si vuole accedere contemporaneamente con due o più formattazioni diverse. Per fare ciò siricorre alle union come segue:

typedef union long int l; //32 bitunsigned int i; //supposto int 16 bitchar c[2];

t_union;

La union appena definita permette di accedere alla stessa area di memoria agendo sullo scalare i o sull’array c.Per esempio:

Page 96: Dispensa PID

96 APPENDICE A. BREVIARIO SULLA SINTASSI C

t_union x;

x.l=0x10009; //x.i=0x0009, c[0]=0x09, c[1]=0x00x.i=0xF50; //setto la variabile i: c[0] vale 0x50, c[1]=0x0F, l=0x10F50x.c[1]++; //ora si ha i=0x1050 e l=0x11050

questo implica che sizeof(t_union)6=sizeof(long int)+sizeof(int)+2*sizeof(char). In altre pa-role tutte le variabili contenute in una union partono dal medesimo indirizzo di memoria. Per capire megliol’organizzazione della memoria si osservi la tabella seguente che mostra come è allocato il valore 0x11050:

La variabile di dimensioni maggiori setta la dimensione della union e viene posizionata, in questo esempio, allaposizione di memoria 0x2000; a questa posizione corrisponde anche il primo byte (ossia quello menosignificativo) della union. Tutte le altre variabili vengono collocate a questo indirizzo di memoria: condividendolo stesso indirizzo di memoria tutti sottocampi della variabile x condividono i singoli byte. Attenzione però chel’esempio proposto è solo qualitativo per capire come funziona una union. Infatti l’organizzazione dei datidipende dal processore. L’esempio quindi calza per i processori dsPIC30F i quali rappresentano i dati nelformato “little endian” (vedi [3] §5.3) ossia il byte più significativo risiede all’indirizzo di memoria più alto,viceversa il formato “big endian” usato per esempio nei processori POWERPC di FREESCALE (IBM).

Se ora si volesse fare in modo che la variabile c[2] punti al secondo e terzo byte della union, è possibile unirequanto fin’ora detto e ottenere una struttura di questo tipo:

typedef union long int l; //32 bitunsigned int i; //supposto int 16 bitstruct

unsigned :8;char c[2];

; t_union;

Puntatori

Si indicano con * prima del nome della variabile:

void* puntatore generico.

char* puntatore a carattere o ad array di caratteri (ossia stringhe).

int* puntatore a numero intero o ad array di numeri interi.

I puntatori sono tutti di dimensione pari alla “parola” del processore. Ciò significa che in termini di memoria nonvi è differenza tra char*, int*, ecc.

Lo stralcio di codice seguente mostra come si indica alla variabile di puntare ad una determinata cella dimemoria:

Page 97: Dispensa PID

A.1. TIPI DI DATI 97

int x,*y; //x è un numero, y è un puntatore

...y=&x;

il carattere & seguito dal nome di una variabile, ne restituisce il puntatore. Per modificare il valore contenutoall’indirizzo di memoria contenuto in y (ossia per modificare il valore di x) si procede come segue:

*y=3; //equivale a scrivere x=3

ossia il carattere * seguito dalla variabile permette di accedere alla locazione di memoria puntata dal puntatore.In altre parole il valore (3 in questo caso) viene scritto nella variabile x.

Nota: si osservi che la definizione multipla di puntatori NON si scrive come segue:int* x,y,z;

ciò infatti definisce che solo x è in puntatore a variabili di tipo int, mentre y e z sono interi normali. Lascrittura corratta può essere fatta in almeno due modi; il primo, più semplice, è il seguente:int *x, *y, *z;

il secondo invece prevede la definizione di un tipo di dato int*:typedef intp int*;

intp x,y,z;

Come accennato a pag. 94, un puntatore può definire un array; per esempio:

int i,x[3],*y;for(i=0; i<3; i++) x[i]=i; //riempio l’array.y=x; //indico che y deve puntare all’array x. Si noti che x senza quadre è un puntatore.y[2]=100; //accedo a x tramite y, ma con la stessa sintassi. ora anche x[2] è 100.

quindi ora y[i] è pari a x[i]. Si noti però che se le variabili fossero definite come int, ma il puntatore comechar, è possibile accedere a qualsiasi byte dell’array x:

int i,x[3];char *y;x[0]=0x0001; x[1]=0x0203; x[2]=0x0405; //riempio l’array.y=(char*)x; //indico che y deve puntare all’array x, ma va castizzato!!

In questo caso y[3] sarà uguale a 0x02, y[4] sarà uguale a 0x03, ecc. Discorso analogo per le strutture.Riprendendo per esempio la struttura t_struct si osserva che se viene definito il puntatore, l’accesso ai campidella struttura non avviene più con il punto, ma con la freccia -> come segue:

t_struct *y;...y->x=10;

Keyword const e volatile

Le keyword const e volatile servono per qualificare il tipo di dichiarazione di variabile. Vengono poste inuna dichiarazione prima del tipo come segue:

const int x;volatile char y;const volatile struct s;

Page 98: Dispensa PID

98 APPENDICE A. BREVIARIO SULLA SINTASSI C

Queste keyword possono essere poste davanti a qualsiasi tipo di variabile (scalari, array, union, struct, enum, ecc).

const specifica che la variabile creata possiede un valore che non è più modificabile all’interno del program-ma. In realtà ciò dipende dal compilatore. Si consideri infatti il seguente programma di esempio:

#include <stdio.h>int main()

const int x=123; //definizione e inizializzazione della costanteconst int *px; //puntatore costanteint *p=&x; //puntatore normalepx=(int*)&x; //questo è permesso ma da un warningx=0; //errore di compilazione in gcc!

*px=10; //errore di compilazione in gcc!

*p=20; //permessoprintf("%i\n",x);

Questo programma non è orientato al micro controllore ed è da intendersi puramente come un esempio; Per esserecompilato richiede un compilatore apposito2. Compilando ed eseguendo il programma, il compilatore restituiscechiaramente due errori relativi al fatto che si sta cercando di assegnare grandezze costanti; viene anche gene-rato un warning a causa del fatto che *px non viene inizializzato in fase di dichiarazione, ma successivamente.L’output del compilatore gcc è il seguente:

cc file.c -o filefile.c: In function ‘main’:file.c:6: warning: initialization discards qualifiers from pointer target typefile.c:9: error: assignment of read-only variable ‘x’file.c:10: error: assignment of read-only location

make: *** [c] Error 1

Ora se si suppone di commentare le righe che danno il warning e gli errori, il programma viene compilato.Non solo: il programma funziona anche andando addiritura a modificare il valore della variabile const tramite ilpuntatore *p. Questo comportamento è legato sia al compilatore sia al fatto che si sta compilando il programmaper un sistema operativo. Si osservi che una assegnazione di questo tipo (ossia forzare la scrittura di una const)in un microprocessore come il dsPIC30F causa il reset del processore: infatti l’assegnazione di variabili const(per esempio x=0) in C30 non dà errori di compilazione ma le istruzioni generate sono “illegali”.

Nota: si osservi che definire const int *px vuol dire definire un puntatore normale che però punta ad unvalore immodificabile ed è questa la ragione per cui nell’esempio viene restituito un warning e non un er-rore. Se si volesse definire un puntatore costante, ossia che contenga un indirizzo di memoria ben preciso,occorre definire il puntatore in questo modo:int *const px = &variabile_int;

l’inizializzazione deve essere fatta subito con il puntatore a una qualsiasi variabile di tipo analogo (int inquesto caso). Si osservi cha px punterà sempre e solo all’indirizzo di memoria della variabile variabile_int.

volatile invece è tipicamente usate nei sistemi real-time e/o embedded. Si supponga di definire una variabileche non è altro che un alias per identificare la mappatura di un registro del processore per il controllo di unparticolare dispositivo. Un modo per farlo è il seguente:

static volatile unsigned char TMR0 @ 0x01;

2In questo caso il gcc di Linux, ma va bene qualsiasi altro compilatore.

Page 99: Dispensa PID

A.2. DICHIARAZIONI 99

in particolare queta riga indica dove si trova il registro di accumulazione del registro Timer03 del processorePIC16F684. Tale registro contiene il valore del timer. Si supponga ora come esempio di fare un loop al fine dibloccare il programma (ossia la funzione main) fino a che il valore del timer non sia tornato a 0 in questo modo:

int main() ...while(TMR0!=0); //blocco qui l’esecuzione se TMR0 è diverso da 0...

Questo (pseudo) codice è corretto proprio perché TMR0 è stato definito come volatile. Se non fosse stato definitoin questo modo, il compilatore in fase di ottimizzazione potrebbe vedere TMR0 come una variabile qualunquee quindi la tendenza sarebbe quella di trattare la variabile andandola a caricare in un registro controllando poinel ciclo while il valore di tale registro. Ciò è corretto dal punto di vista del compilatore perché velocizza leoperazioni, ma non è ciò che si voleva realizzare!

Nota: Quanto detto, però, non vale solo per le variabili che hanno indirizzi di memoria assoluti e ben precisi(come TMR0 appunto), anche per variabili gestite in interrupt e controllate in polling4, come nell’esempioseguente:volatile char contatore; //variabile glogale

int main() //main function

...

while(contatore<N);

...

void isr interrupt() //interrupt function

...

contatore++;

...

A.2 Dichiarazioni

Dichiarazione di funzione

Le dichiarazioni di funzione possono essere fatte fondamentalmente in due modi. Il primo prevede di creare unfile .h dove vengono definiti tutti i prototipi i quali vengono implementati in un file .c (normalmente chiamato conla stessa base del file .h) il quale include il file .h con le definizioni dei tipi. Il vantaggio principale di ciò è cheogni funzione implementata ha uno scope globale. In altre parole se si definiscono delle funzioni come segue:

extern void function1(void);extern void function2(void);extern void function3(void);

quando le si andrà ad implementare, la prima funzione potrà chiamare al suo interno tutte le altre definite suc-cessivamente. Non solo: la visibilità di queste funzioni sarà globale per tutti i file che includeranno il file .h chele definisce (ossia da dopo la macro #include). É chiaro che se all’interno del file .c che implementa le trefunzioni viene definita una quarta funzione, questa avrà visibilità solo all’interno del file .c, come nell’esempioche segue:

3Codice prelevato dal file pic16f684.h reperibile dal compilatore C PicLite di HT su [L4].4Ciò è vero in particolar modo nei sistemi a micro controllore.

Page 100: Dispensa PID

100 APPENDICE A. BREVIARIO SULLA SINTASSI C

//Inclusione di funzioni.h dove sono definite le tre funzioni function1, 2 e 3

#include ”funzioni.h” //” perché il file è nella directory corrente

//dichiarazione della quarta funzione visibile sono all’interno del file .c!

void function4(void);

//Implementazione delle prime 3 funzioni

void function1()

//TODO

void function2()

//TODO

void function3()

//TODO

void function4()

//TODO

La funzione function4 definita all’inizio viene vista da tutte le altre tre funzioni e a sua volta può chiamaretutte le funzioni definite in funzioni.h in quanto definita dopo l’inclusione di tale file. Si noti che se fossestata definita per esempio dopo l’implementazione della funzione 1, quest’ultima non avrebbe potuto chiamare lafunzione 4.

Il secondo modo per definire e implementare le funzioni è direttamente all’interno del file sorgente .c. Lanorma è quella di definire prima tutte le funzioni e di implementarle poi in fondo al file, tipicamente dopola funzione main. Ciò perché valgono ancora tutte le considerazioni relative alla visibilità fatte per il casoprecedente.

Un’ultima nota riguardo la definizione delle funzioni è che non è necessario definire subito i nomi dellegrandezze necessarie, ma si può procedere definendo la funzione come segue:

void functionX(int, unsigned, char);

Implementazione delle funzioni

L’implementazione delle funzioni può essere fatta subito dopo la definizione della funzione, oppure in un altropunto del programma (come precedentemente accennato) la quale è anche la scelta consigliata. Come detto iparametri della funzione possono anche non essere indicati preventivamente, ma quando la funzione viene imple-mentata allora verranno definiti i nomi delle grandezze (int, unsigned e char rifacendosi al caso precedente).Se invece le funzioni viene definita subito con i relativi nomi dei parametri, nel momento in cui si effettueràl’implementazione dovranno essere reindicati con lo stesso nome:

void functionX(int a, unsigned b, char c) //TODO

Si nota che la keyword extern non viene ridefinita.

Un altro modo per definire e implementare le funzioni è il seguente:

int functionC(x)int x;

//TODO

Page 101: Dispensa PID

A.2. DICHIARAZIONI 101

Questo tipo di definizione normalmente prevede una implementazione in inline ossia viene definito subito ilcodice che realizza la funzione senza definire precedentemente la funzione; questo perché se venisse definitaprecedentemente il compilatore potrebbe restituire un warning dicendo che la funzione ha un parametro senzatipo. Si noti comunque che questo tipo di sintassi è valido solo in C e non in C++. É comunque una definizioneobsoleta.

Nota: Le funzioni possono essere definite e/o implementate con la keyword static. Per la programmazione sumicro controllore questo può non essere rilevante, ma per sistemi più complessi o di alto livello (comesistemi operativi real-time) può prevenire la ridefinizione di funzioni che possono creare ambiguità o chenon devono essere ridefinite in nessun file (per esempio nel kernel Linux le primitive di I/O che devonoessere esportate).

Variabili, costanti e parametri

I parametri in una funzione possono essere:

Nulli indicati con void, ma i più di compilatori accettano anche le parentesi vuote. Per esempio:int func1(void);

int func2();

Valori indicati con il tipo di variabile definibile dall’utente come int, char, ecc. Per esempio:int func3(int x, char c);

I valori passati possono essere ridefiniti internamente, ma ciò non causerà nulla alle variabili passatedall’esterno alla funzione una volta che questa viene chiusa perché è il valore di queste grandezzeche viene copiato nello stack e non il loro putatore.

Puntatori Per esempio con:int func4(int *x, struct ST *c);

in questo caso se all’interno della funzione (ossia in fase di implementazione) x viene assegnata comex=(int*)c ora punterà a un diverso indirizzo di memoria, ma la variabile passata dall’esterno nonsubirà modifiche; se però si assegna *x=10 allora la variabile esterna passata alla funzione assumeràil valore 10.

Costanti Indicano che il valore non può essere modificato. Servono tipicamente per passare stringhe definitedall’utente. Per esempio:void func5(const char *str); tipicamente verrà chiamata come func5(”Stringa generica”);

esempi tipici sono le funzioni standard del C relativa all’utilizzo delle stringhe definite in string.h,come strcmp, strncmp, ecc.

Le variabili definite all’interno delle funzioni hanno visibilità locale alla funzione e vengono allocate nello stack,quindi se non vengono inizializzate internamente alla funzione, tali variabili assumono un valore che dipendedalla storia dello stack; eccezione fatta nel caso in cui le variabili siano definite come static, nel qual caso nonsolo verranno inizializzate una sola volta, ma all’uscita della funzione il loro valore non verrà perso. Si noti chese una variabile locale ha lo stesso nome di una globale, la variabile utilizzata nella funzione sarà quella locale.Chiaramente il valore delle variabili globali (o comunque con visibilità “superiore”) non viene alterato.

Page 102: Dispensa PID

102 APPENDICE A. BREVIARIO SULLA SINTASSI C

Dichiarazioni di MACRO

Alcuni esempi di come si definisce una macro sono i seguenti:

#define MACRO1 ((int)’c’+1)#define MACRO2(x,y)((x+1)%y)#define MACRO3(var,field)((var)->(field))#define MACRO4(i)(MACRO##i)

La prima è la definizione di una costante, la seconda è una macro a tutti gli effetti in quanto esegue alcuni contidati due parametri in ingresso. La terza prevede che il parametro var sia un puntatore a una struttura e field diauno dei suoi campi. Infine la quarta macro in funzione del numero i chiama una delle altre macro. Per esempiose si volesse chiamare la prima macro è sufficiente scrivere MACRO4(1). Si noti che se i è contenuto all’internodi una parola, la macro 4 va definita come MACRO4(i)(STRH##i##STRL) dove STRH e STRL sono le stringhealta e bassa che compongono la macro.

Una macro può anche essere definita su più righe (come qualsiasi altro comando) ricorrendo al carattere “\”come nell’esempio seguente:

#define DEFINE_PRINT_ERROR \printf(”Error %i at %X\n”, \

num_error, index_error)#define MACRO_PRINT_ERROR(n,i)( \printf(”Error %i at %X\n”, \

n, i) )

Page 103: Dispensa PID

Appendice B

Validità del regolatore PI

Un regolatore PI come quello studiato nei capitoli 3 e 4, non è sempre la soluzione migliore. L’esempio che verràora proposto mostra che il regolatore non può essere progettato, in linea teorica, con qualsiasi banda passante; lasoluzione sarà quella di cambiare tipo di regolatore.

Si consideri quindi il circuito in figura B.1 e la relativa funzione di trasferimento tra Vin e Vout:

VoutVin

=1LC

s2 + s 1CR + 1

LC

Figura B.1: Circuito R-L-C.

Supponendo i valori R=100Ω, L=10mH , C=470µF ne consegue che i poli del sistema siano complessiconiugati e pari a -10,64±461,14i. Le risposte in frequenza relative sono rappresentate in figura B.2.

Supponendo ora di effettuare il calcolo relativo a un PI per il controllo del sistema secondo quanto detto nelcapitolo 4 (equazioni 2.3) impostando per esempio 1000 rad/s come banda passante e 90 come margine di fase,i coefficienti del regolatore saranno Kp=0,1 e Ki=-3700. Questo risultato è notevole ed è dovuto al fatto che lafrequenza di taglio impostata per il calcolo dei regolatori è superiore alla pulsazione di risonanza, come si notaanche dai grafici in figura B.3. Inoltre dal diagramma di Bode si nota che la funzione L(s) = R(s) ·G(s) taglial’asse a 0dB con pendenza -60dB/decade.

Si potrebbe quindi pensare di ridurre la banda passante ad un valore inferiore alla pulsazione di risonanza, peresempio wt = 100. Le cose però non migliorano perché il sistema presenta un margine di fase negativo (figuraB.4). Ciò nonostante, però, le cose non migliorano perché, anche se ora Kp=0,01 e Ki=95,3, il margine di fase ènegativo.

Si noti che in alcuni casi il sistema si stabilizza se la banda passante viene drasticamente ridotta rispetto allapulsazione di risonanza. Nonostante ciò si vede come si perdano tutti i vantaggi derivati dal calcolo in forma

103

Page 104: Dispensa PID

104 APPENDICE B. VALIDITÀ DEL REGOLATORE PI

(a) Diagramma di Bode (b) Diagramma di Nyquist

Figura B.2: Risposta in frequenza del circuito RLC.

(a) Diagramma di bode L(s) (b) Diagramma di Nyquist L(s)

Figura B.3: Risposta in frequenza della funzione d’anello L(s) calcolata con pulsazione di taglio a 1000 rad/s.

chiusa dei parametri. Il sistema infatti anche se venisse stabilizzato avrebbe risposte lentissime. Il regolatorePI in questo caso non è l’ideale. In questi casi è preferibile definire un regolatore generico che vada (al limite)a cancellare i poli complessi coniugati e introduca un polo a più alta frequenza in modo da avere una rispostacomplessiva migliore. La soluzione da adottare è una funzione generica del tipo seguente:

R(s) = k

∏Nn=1 (s + an)

n∏Mm=1 (s + bm)m

(B.1)

In particolare è noto dalla teoria che un sistema di regolazione deve avere un integrale per annullare l’errore aregime; quindi si può esprimere R(s) = R1(s)R2(s) dove R2 = 1

s ossia un integratore. Detto ciò è chiaro cheR1(s) verrà modellizzato basandosi sulla funzione risultante RG(s) = R2(s) ·G(s) la quale risulta ovviamentecon una pendenza maggiore di 20dB/dec; ciò implica che occorrerà porre almeno due zeri. Perché la funzionesia fisicamente realizzabile1 occorre però prevedere anche due poli: avendo R2(s) un polo nell’origine, occorre

1Anche se non è necessario che la funzione sia fisicamente realizzabile per implementarla su un micro, se la funzione è di questo tipo itermini del regolatore sono tipicamente più facilmente gestibili da un micro-processore.

Page 105: Dispensa PID

105

(a) Diagramma di bode di L(s) (b) Diagramma di Nyquist di L(s)

Figura B.4: Risposta in frequenza della funzione d’anello L(s) calcolata con pulsazione di taglio a 100 rad/s.

aggiungere almeno un polo in alta frequenza. La funzione avrà una forma simile alla seguente:

R(s) = R1(s) ·R2(s) = k(s + a1)(s + a2)

(s + b)· 1s

(B.2)

dove a1 e a2 sono tali per cui si cercherà di ridurre (al limite annullare) l’effetto della risonanza. Lo studio disistemi come questo può essere fatto per via grafica ponendo il denominatore della funzione pari a quello dellafunzione G(s) in modo da cancellare i poli complessi coniugati, ossia la risonanza. Infine si inserisce un polo inalta frequenza per quanto detto poco prima e un coefficiente k che “aggiusti” la risposta in termini di guadagno ebanda passante. La funzione proposta è la seguente:

R(s) = ks2 + c1s + c2

ds2 + s= 0.005

s2 + 21.766s + 2.1277 · 105

s(2.5 · 10−4s + 1)(B.3)

I diagrammi relativi alla funzione L(s) = R(s) ·G(s) sono riportati in figura B.5. É chiaro che un andamento

(a) Diagramma di Bode (b) Diagramma di Nyquist

Figura B.5: Diagrammi di Bode e Nyquist relativi alla funzione d’anello L(s) con eliminazione della risonanza.

Page 106: Dispensa PID

106 APPENDICE B. VALIDITÀ DEL REGOLATORE PI

come quello ottenuto è legato al fatto che la risonanza è stata cancellata in modo perfetto. Ciò è dipendentedal fatto che si assume il sistema modellizzato in modo perfetto. Nella pratica, però, è difficile che il modellorispecchi in modo perfetto la realtà; ciò implica che il modello del regolatore può introdurre un altro punto dirisonanza il quale tende ad incrementare una certa gamma di frequenze. Si supponga per esempio che i poliper compensare la risonanza siano pari a -10,64±400,14i, ossia l’armonica alla quale avviene la risonanza è piùbassa. Si ottengono i grafici in figura B.6.

(a) Diagramma di Bode (b) Diagramma di Nyquist

Figura B.6: Diagrammi di Bode e Nyquist relativi alla funzione d’anello L(s) con zeri risonanti a sinistra.

Si noti che il fatto di aver posto gli zeri a sinistra della risonanza è necessario, come mostrato in figura B.7.Infatti ponendo gli zeri in modo tale che la risonanza si sposti a destra della risonanza introdotta dalla funzioneG(s), il sistema è instabile. A sostenere ciò, in figura B.8 sono riportate le due risposte al gradino nei due casiappena studiati.

(a) Diagramma di Bode (b) Diagramma di Nyquist

Figura B.7: Diagrammi di Bode e Nyquist relativi alla funzione d’anello L(s) con zeri risonanti a sinistra.

Page 107: Dispensa PID

B.1. DISCRETIZZAZIONE DEL REGOLATORE 107

(a) Step con zeri risunanti a sinistra (b) Step con zeri risonanti a destra

Figura B.8: Risposta al gradino unitario relativa ai casi in figura B.6 e B.7.

B.1 Discretizzazione del regolatore

Il regolatore in z trasformata è sufficiente applicare alla funzione B.3 la trasformazione ti Tustin (equazione 2.15)da cui si ottiene:

R(z) = k

(4 + 2c1Tsc2T

2s

)z2 +

(2c2T

2s − 8

)z +

(4 + 2c2Ts − 2c1T

2s

)(4d + 2Ts) z2 − 8dz + (4d− 2Ts)

(B.4)

da cui ne deriva l’espressione dell’uscita del regolatore nelle sequenze:

y∗(n) = k

(e∗(n)

4 + 2c1Ts + c2Ts4d + 2Ts

+ e∗(n− 1)2c2Ts − 84d + 2Ts

+ e∗(n− 2)4− c1Ts − 2c1T

2s

4d + 2Ts

)+

+y∗(n− 1)8d

4d + 2Ts+ y∗(n− 2)

2Ts − 4d

2Ts + 4d(B.5)

Per la scrittura del codice ci si appoggia alla scrittura all’equazione B.5 espressa come segue:

y∗(n) = e∗(n)E0 + e∗(n− 1)E1 + e∗(n− 2)E2 + y∗(n− 1)Y 1 + y∗(n− 2)Y 2 (B.6)

le cui costanti, per analogia con B.5, sono facilmente individuabili; ogni costante verrà espressa con la rispettivamacro.

Sostituendo ora i valori dei parametri del sistema possiamo tracciare il diagramma di Bode di R(s) e R(z). Iltempo di campionamento scelto è Ts = 50 · 10−6µs da cui si ottiene la seguente funzione di trasferimento in z:

R(z) =0.02001z2 − 0.03999z − 0.01999

0.0011z2 − 0.002z + 0.0009

I diagrammi di Bode sono riportati in figura B.9. Come si nota, il sistema presenta una distorsione in bassafrequenza. Anche se sembra che la fase sia migliore perché resta a 90 per una gamma di frequenze più ampia,in realtà ponendo R(z) in cascata a G(s) il sistema complessivo risulta instabile. Ciò risulta dalle simulazioni,ma è facilmente intuibile dal semplice diagramma di Bode. Come detto, infatti, se i due poli complessi coniugatidovuti agli zeri hanno una pulsazione maggiore della pulsazione di risonanza individuata in G(s), il sistemasi instabilizza. Ricordando che R(s) è stata progettata per eliminare perfettamente i poli di G(s), è chiaro

Page 108: Dispensa PID

108 APPENDICE B. VALIDITÀ DEL REGOLATORE PI

Figura B.9: Diagramma di Bode della funzione R(s) e R(z).

che il picco risonante (di R(z)) è spostato verso destra, il sistema è instabile. La funzione in z deve quindiessere ricalcolata tramite l’introduzione della distorsione del tempo di campionamento; ciò è spiegato in modoesaustivo in [3] e consiste semplicemente nel calcolare un nuovo valore di Ts con il quale calcolare i coefficientiin z. Esaminando il grafico in figura B.9 si intuisce che per fare in modo che le due “guglie” si sovrapponganooccorrerebbe ridurre Ts in modo che il grafico venga “compresso”. Attenzione però al fatto che la funzione R(z)dovrà essere plottata con Ts pari a 50·10−6µs ossia il “vecchio” intervallo di campionamento. Per chiarire questoaspetto di seguito viene riportato del codice MATLAB per valutare la distorsione:

Tsd=fattore_distorsione*Ts;%c1,c2 : coefficienti del denominatore G(s); d=1/4000 : polo in alta frequenza in R(s)

%coefficienti del numeratoreZn2=k*(4+2*c1*Tsd+c2*Tsd^2); Zn1=k*2*(c2*Tsd^2-4); Zn0=k*(4-2*c1*Tsd+c2*Tsd^2);

%coefficienti del denominatoreZd2=4*d+2*Tsd; Zd1=-8*d; Zd0=4*d-2*Tsd;z=tf(’z’,Ts); % z rimande calcolata con passo Ts!Rz=(Zn2*z^2+Zn1*z+Zn0)/(Zd2*z^2+Zd1*z+Zd0);%se presente R definita nel dominio ’s’ plottare con:bode(R, Rz);

Il valore della variabile fattore_distorsione è stato individuato per tentativi e posto pari a 0,86. Con questovalore si ottiene il diagramma di Bode e la risposta al gradino relativi rispettivamente al sistema tempo-continuoe discreto (figura B.10-a e B.10-b). I coefficienti della funzione diventano:

R(z) =0.02001z2 − 0.04z − 0.01999

0.001074z2 − 0.002z + 0.000926

Page 109: Dispensa PID

B.2. MODELLISTICA 109

(a) Bode (b) Step

Figura B.10: Diagrammi con R(z) calcolata in distorsione.

B.2 Modellistica

I risultati riportati in figura B.12 sono riportati i risultati del modello SIMULINK sviluppato in figura B.11.

Figura B.11: Modello in s e z del sistema in esame.

La modellistica dei sistemi studiati è abbastanza semplice e non è altro che l’implementazione delle funzioniindicate precedentemente in s e z. Più complesso è invece il regolatore C il quale verrà implementato basandosisull’equazione B.6. Le costanti dell’equazione B.6 sono:

E0=18.6313 E1=-37.2426 E2=18.6167Y1=1.8623 Y2=-0.8623

Sviluppare il codice C con variabili double è quindi abbastanza semplice: Uno stralcio di tale codice, i cui risultatisono mostrati in figura B.13, è il seguente:

/* 0: errore attuale; 1: errore precedente; 2: errore di 2 passi precedenti */

double error[3];

/* 0: uscita attuale; 1: uscita precedente; 2: uscita di 2 passi precedenti */

double out[3];

out[0]=error[0]*18.4264-error[1]*36.8288+error[2]*18.4096+out[1]*1.8416-out[2]*0.8416;

Page 110: Dispensa PID

110 APPENDICE B. VALIDITÀ DEL REGOLATORE PI

(a) Dettaglio della risposta a gradino (b) Tensione dovuta all’ingresso a gradino

Si noti che il regolatore C non è implementato in questi grafici. Per i colori riferirsi alla figura B.11.

Figura B.12: Confronto dell risposta dei regolatori tempo-continuo e tempo-discreto.

(a) Risposta al gradino (b) Tensione in uscita dal regolatore

Figura B.13: Risposta del regolatore C realizzato con variabili double.

Come si vede l’andamento della risposta del regolatore z si sovrappone perfettamente a quella del regolatore C.Ora però occorre adattare il codice a un micro controllore, quindi è necessario passare in digitale anche per quantoriguarda le grandezze. Si assume a titolo di esempio un trasduttore con portata ±10V che riporti il risultato a10 bit ossia compreso nell’intervallo 0÷1023 acquisito dal micro processore. L’equazione per la trasduzione siassume pari a:

Vdigit =Vreale10V

· 512 + 512

Il riferimento applicato avrà un valore di picco pari a 1V. Di seguito viene riportato il codice C SIMULINK

necessario per eseguire la regolazione con variabili intere:

#define RIFERIMENTO u0[0]#define VALOREREALE u0[1]#define E0(e)((e*75475)+(e>>1)+(e>>3)+(e>>4)+(e>>6)+(e>>9)+(e>>10))#define E1(e)((e*150850)+(e>>1)+(e>>3)+(e>>4)+(e>>5)+(e>>8)+(e>>10))#define E2(e)((e*75405)+(e>>1)+(e>>3)+(e>>4)+(e>>8)+(e>>10)#define Y(y)((y>>1)+(y>>2)+(y>>4)+(y>>6)+(y>>7)+(y>>8)+(y>>10))int out[3]; /* 32bit. Array per tenere conto di allo stato attuale, precedente e di 2 volte prima */short int error[3]; /* 16bit. array analogo a out, ma per gestire l’errore */

Page 111: Dispensa PID

B.2. MODELLISTICA 111

/-----------------------------/int intE0, intE1, intE2; /*Variabili a 32bit*/int intY, outD; /*Variabili e 32bit */

/* Riposizionamento elementi array */error[2]=error[1];error[1]=error[0];error[0]=(RIFERIMENTO-VALOREREALE)<<3;

/* Analogamente per l’uscita */out[2]=out[1];out[1]=out[0];

/* Calcolo dei vari componenti dell’uscita */if(error[0]>=0) intE0=E0(error[0]);

else intE0=-(E0((-error[0])));if(error[1]>=0) intE1=E1(error[1]);

else intE1=-(E1((-error[1])));if(error[2]>=0) intE2=E2(error[2]);

else intE2=-(E2((-error[2])));outD=out[1]-out[2];if((outD)>=0) intY=(Y(outD));

else intY=-(Y((-outD)));/* Calcolo l’uscita */

out[0]=intE0-intE1+intE2+out[1]+intY;/* Gestione dell’uscita del blocco S-Function Builder */

y0[0]=out[0]>>12; /* visualizzo y0[0] in base 2^12 */y0[1]=((double)out[0]*10)/(4096*4096); /* converto tutto in grandezze fisiche “reali” */

Il codice appena riportato è il risultato di alcuni passaggi che mirano a portare il codice formalizzato in grandezzedouble a grandezze di tipo intero (int). Per prima cosa il sistema in base 4096 (12 bit) è troppo impreciso esi è passati subito a lavorare in base 16777216 (24 bit). Il cambiamento di base, però, non riguarda il calcolodell’errore (il quale è riportato in base 4096), ma il calcolo dei coefficienti E0, E1 ed E2 i quali rispetto al valorevero vengono moltiplicati per 4096 aumentando notevolmente la precisione.

Esaminando quindi il codice si individuano le prime definizioni delle macro relative ai parametri appenadescritti i quali vanno a moltiplicare gli errori e, subito dopo, si nota la macro Y. Questa macro sostituisce lemacro che realizzano i valori Y1 e Y2 in quanto si è notato che Y1-1-Y2'1.1102·10−6, quindi trascurabile. Ciòpermette di porre Y1=Y2+1 da cui:

out[1]*Y1-out[2]*Y2=out[1]+(out[1]-out[2])Y

dove Y=Y2. Questo costrutto permette di ridurre il carico computazionale, come si vedrà nel corso del program-ma, in quanto si eseguono sia una comparazione (if) che una macro in meno. A questo punto occorre notare unacosa molto importante: a differenza di quanto detto per i coefficienti E, i coefficienti Y1, Y2 e di conseguenza Ynon sono maggiorati di 4096, ma restano al valore calcolato inizialmente; ciò è dovuto al fatto che questi coef-ficienti “pesano” i valori precedenti della variabile out[0] la quale deriva dall’elaborazione dell’errore per uncoefficiente E in base 4096 che porta inevitabilmente la variabile out[0] in base 16777216. Quindi out[i]*Yè anch’esso un numero in base 1677216.

Proseguendo nell’analisi si trovano le dichiarazioni dei due array (out e error) di 3 elementi che tengonoconto del valore corrente (0), del valore precedente (1) e del valore di due passi precedenti (2).

Passando all’interno del programma vero e proprio si vede che l’array dell’errore viene aggiornato spostandoindietro di una posizione i vecchi valori e, infine, viene calcolato il nuovo valore dell’errore (error[0]) portato,mediante uno shift di tre bit, in base 4096. Analogamente viene fatto per i vari elementi dell’array out. Succes-sivamente vengono calcolati i vari componenti dell’uscita. Tenendo presente che le varie macro hanno shift versodestra, occorre fare un controllo sul segno della grandezza come già visto nei capitoli precedenti. Successivamen-te si effettua il calcolo dell’uscita out[0]. Le uscite y0 invece sono relative al blocco S-Function di SIMULINK.Si noti che l’uscita y0[1] è il valore reale della tensione applicata.

Page 112: Dispensa PID

112 APPENDICE B. VALIDITÀ DEL REGOLATORE PI

I risultati relativi al riferimento a gradino sono riportati in figura B.14. Come si nota la dinamica e la velocitàdi risposta sono pressoché identiche a quelle della funzione con regolatore z. Anche dal punto di vista dinamicol’inseguimento del riferimento avviene perfettamente; l’andamento mostrato in figura B.15 mostra come reagisceil sistema a fronte di un riferimento sinusoidale da con pulsazione di 1000rad/s. Si noti che il riferimento è seguitomolto meglio se variabile rispetto al gradino. Infatti se si ingrandisse la figura B.14 nel tratto finale, si vedrebbeun leggero scostamento (ingegneristicamente accettabile) tra l’uscita dovuta al regolatore C e quella dovuta alregolatore z con riferimento a gradino rispetto al riferimento sinusoidale. Nonostante ciò, questo è il migliorerisultato ottenuto.

(a) Step (b) Tensione applicata

Figura B.14: Riferimento a gradino del regolatore C.

(a) Sinusoide 1000 rad/s (b) Tensione applicata

Figura B.15: Riferimento sinusoidale del regolatore C.

Come detto poco prima, la tensione in uscita dal blocco S-Function Builder è un valore reale. Ciò è vero anchenella realtà, ma occorre tenere presente che la variabile che tiene conto del duty-cycle nel micro controllore (peresempio PDCx nei processori dsPIC30F) è una variabile discreta, quindi la tensione applicata al carico sarà unafrazione ben precisa della massima tensione applicabile (ossia della tensione di DC bus). A titolo di esempio sisupponga di avere un ponte H con una tensione di DC bus pari a 50V e che il valore massimo del duty-cycle siaper esempio 736; essendo un ponte ad H se la variabile duty-cycle è pari a 368 la tensione sul carico è nulla.

Page 113: Dispensa PID

B.2. MODELLISTICA 113

Questo vuol dire che la risoluzione della tensione sul carico è pari a 2·50V/736, ossia 0,1359V. Una possibilesoluzione per tenere conto di ciò prevede una modifica al codice precedentemente riportato come segue:

/*dc=368+y0[1]*368/50; ’dc’ è una variabile unsigned int a 16bit sul microva realizzato con una macro (GET_DC())per evitare la divisione */

#define GET_DC(o)((o>>18)+(o>>21)+(o>>24))short int dc;

.../* Gestisco l’uscita del blocco S-Function Builder */if(out[0]>=0) dc=GET_DC(out[0]);

else dc=-(GET_DC((-out[0])));if(dc>368) dc=368;else if(dc<-368) dc=-368;y0[0]=dc+368; /* Reale valore del duty-cycle PDC1 */y0[1]=((double)dc*50)/736; /*valore reale della tensione*/

Chiaramente l’introduzione del duty-cycle degrada la risposta come mostrato in figura B.16. Come prevedi-bile, la risposta al gradino peggiora leggermente come anche quella sinusoidale, anche se quest’ultima menovistosamente. I risultati ottenuti sono quindi più che soddisfacenti.

(a) Riferimento a gradino (b) Riferimento sinusoidale

Figura B.16: Risposta con introduzione del duty-cycle.

Page 114: Dispensa PID

114 APPENDICE B. VALIDITÀ DEL REGOLATORE PI

Page 115: Dispensa PID

Riferimenti

Bibliografia

[1] DALLA TEORIA AL CODICE MACCHINA: SCRITTURA DEL CODICE PER UN PI DIGITALE- M. Matuonto, F. L. Mapelli

[2] Elementi di CONTROLLO DIGITALE - Guido Guardabassi

[3] Manuale del compilatore C30 (su [L3] application note 51284D)

[4] Manual Family dsPIC30F (su [L3] application note 70046D)

[5] ANALISI TEORICA E SPERIMENTALE DEGLI APPARATI DI ECCITAZIONE E LEVITAZIO-NE NEI SISTEMI MAGLEV EMS - Tesi di dottorato di Giovanni Maria Foglia - dip. Ing. Elettrica- Politecnico di Milano - anno 2001

[6] PROGETTO E REALIZZAZIONE SPERIMENTALE DEL SISTEMA DI REGOLAZIONE DI UNLEVITATORE EMS TRADIZIONALE E A MAGNETI PERMANENTI - Tesi di laurea di CalzoniPietro - anno 2006

[7] Datasheet della demo board PicKit2 (su [L3] datasheet DS-51556A)

[8] Datasheet del processore PIC16F684 (su [L3] datasheet 41202D)

[9] Paolo Bolzen, Riccardo Scattolini, Nicola Schiavoni, “Fondamenti di controlli automatici”, McGrawHill 1998

[10] Fondamenti di automatica I - Paolo Rocco, Politecnico di Milano

[11] Comandi MATLAB di uso comune - Giudicatti Italo

Link

[L1] http://www.iac.cnr.it/~amadori/M4

[L2] http://www.ettorepanella.com/public/corsi/Trasformata%20Z.pdf#search=%22Z%20trasformata%22

[L3] http://www.microchip.com

[L4] http://www.ht-soft.com

[L5] http://www.freescale.com

[L6] http://publications.gbdirect.co.uk/c_book/

www.lyx.org LYX programma con cui è stata scritta questa dispensa (front-end per LATEX)

115