Libs for using Nucleo STM32F411 periphery

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PIDControl.cpp Source File

PIDControl.cpp

00001 #include "mbed.h"
00002 #include "PIDControl.h"
00003 
00004 //====================================================================================================================================
00005 //                                                  Konstruktor und Regelprozess
00006 //====================================================================================================================================
00007 
00008 PIDControl::PIDControl (bool P_usr, float KP_usr, bool I_usr, float KI_usr, bool D_usr, float KD_usr){
00009     
00010       awu_gain = 0;                                                 // Anti-Windup deaktivieren
00011       u_max = 32760;                                                // Maximale Stellgröße limitiert auf max. Integer Wert
00012       u_min = -32760;                                               // Minimale Stellgröße limitiert auf min. Integer Wert
00013       lockctrl = false;                                             // Regler frei parametrierbar
00014       
00015       e_last = 0;                                                   // Letzter Regelfehler ist 0
00016       e_sum = 0;                                                    // Integralteil ist 0
00017       u = 0;                                                        // Führungsgröße ist 0
00018       awu_value = 0;                                                // Atin-Windup größe ist 0
00019       status  = 0;                                                   // Statusregister bisher nicht gefüllt
00020       extfct = false;                                               // Keine Externe Funktion festgelegt
00021       
00022       P = P_usr;                                                    // P-Anteil on/off
00023       KP = KP_usr;                                                  // P-Anteil Verstärkung
00024       I = I_usr;                                                    // I-Anteil on/off
00025       KI = KI_usr;                                                  // I-Anteil Verstärkung
00026       D = D_usr;                                                    // D-Anteil on/off
00027       KD = KD_usr;                                                  // D-Anteil Verstärkung
00028      
00029     }
00030 
00031 
00032 int16_t PIDControl::ctrltask  (int16_t wsoll, int16_t yist, uint16_t time){
00033     
00034         setStatus(0);                                               // Regeltask aktiv - Flag aktivieren
00035     
00036         int16_t e = wsoll - yist;                                   // Regelfehler bestimmen             
00037         e_sum = e_sum + e;                                          // Integralanteil bestimmen
00038         
00039         if(e > 0){                                                  // Regelfehler positiv
00040             setStatus(4);                                           // Regelfehler positiv - Flag aktivieren
00041             resetStatus(3);                                         // Regelfehler negativ - Flag deaktivieren
00042             resetStatus(2);                                         // Regelfehler null - Flag deaktivieren            
00043         }
00044         
00045         if(e < 0){                                                  // Regelfehler negativ
00046             resetStatus(4);                                         // Regelfehler positiv - Flag deaktivieren
00047             setStatus(3);                                           // Regelfehler negativ - Flag aktivieren
00048             resetStatus(2);                                         // Regelfehler null - Flag deaktivieren            
00049         }
00050                        
00051         if(e == 0){                                                 // Regelfehler null
00052             resetStatus(4);                                         // Regelfehler positiv - Flag deaktivieren
00053             resetStatus(3);                                         // Regelfehler negativ - Flag deaktivieren
00054             setStatus(2);                                           // Regelfehler null - Flag aktivieren
00055         }
00056         
00057         int16_t divisor = log2(time);                               // Bestimmung der Zeller um die das geschoben werden soll
00058        
00059         if(P){                                                      // P-Anteil bestimmen
00060             P_var = (KP * e);                                       // u = Kp * e   
00061         }
00062         else{
00063             P_var = 0;                                            // kein P-Anteil vorhanden
00064         }
00065             
00066         if(D){                                                      // D-Anteil bestimmen
00067             D_var = KD * time * (e - e_last);                       // u = Kd * Ta * (e - e_last) + P-Anteil 
00068             D_var = D_var << 10;                                    // Zeitanpassung, da eingabe in µs  
00069         }
00070         else{
00071             D_var = 0;                                              // kein D-Anteil vorhanden
00072         }
00073             
00074         if(I){                                                      // I-Anteil bestimmen
00075             I_var = (KI * (e_sum - awu_value));                     // u = Ki / Ta * (e_sum - awu_value) + P-Anteil + D-Anteil  
00076             I_var = I_var  << divisor;                              // Division durch die Zeit
00077         }
00078         else{
00079             I_var = 0;                                              // kein I-Anteil vorhanden
00080         }               
00081 
00082         resetStatus(1);                                             // I-Anteil an Grenze geraten
00083 
00084         if(integrallimiter){                                        // Limiteriung des I-Anteils erforderlich?
00085             if(e_sum >= i_max){                                     // Limitierung der Integralsumme zur oberen Schwelle
00086                 setStatus(1);                                       // Fehler I-Anteil über Grenzwerte
00087                 e_sum = i_max;                                      // Limitierung der Summe
00088                 awu_value = (e_sum - i_max) * awu_gain;             // Anti-Windup Berechnung
00089             }
00090 
00091             if(e_sum <= i_min){                                     // Limitierung  der Integralsumme zur unteren Schwelle
00092                 setStatus(1);                                       // Fehler I-Anteil über Grenzwerte
00093                 e_sum = i_min;                                      // Limitierung der Summe
00094                 awu_value = (e_sum - i_min) * awu_gain;             // Anti-Windup Berechnung
00095             }
00096         }  
00097    
00098         u = P_var + D_var + I_var;                                  // Reglerausgang definieren
00099         
00100         resetStatus(6);                                             // Regelgrenze max überschritten zurücksetzen
00101         resetStatus(7);                                             // Regelgrenze min überschritten zurücksetzen  
00102     
00103         if(u >= u_max){                                             // Limitierung des Regelausgangs zur oberen Schwelle
00104             setStatus(7);                                           // Fehler Regelgrenze max überschritten
00105             u = u_max;                                              // Ausgabe des Stellgrößen Limits 
00106         }
00107 
00108         if(u <= u_min){                                             // Limitierung des Regelausgangs zur unteren Schwelle
00109             setStatus(6);                                           // Fehler Regelgrenze min überschritten
00110             u = u_min;                                              // Ausgabe des Stellgrößen Limits 
00111         }      
00112             
00113         e = e_last;                                                 // Regelfehler als letzten Regelfehler übernehmen
00114         resetStatus(0);                                             // Regeltask aktiv - Flag deaktivieren
00115         
00116     return u;                                                       // Ausgabe der Stellgröße  
00117    
00118     }
00119 
00120 //====================================================================================================================================
00121 //                                                   Setter und Getter Funktionen
00122 //====================================================================================================================================
00123    
00124 bool PIDControl::setKP (bool P_usr, float KP_usr){                   // Setzen des P-Anteils
00125     
00126     if(!lockctrl){
00127         P = P_usr;                                                  // P-Anteil on/off
00128         KP = KP_usr;                                                // P-Anteil Verstärkung
00129         
00130         return true;                                                // Setzen der Werte erfolgreich     
00131         }
00132     else{ 
00133         return false;                                               // Setzen der Werte nicht erfolgreich
00134         }   
00135     } 
00136 
00137     
00138 bool PIDControl::setKI (bool I_usr, float KI_usr){                   // Setzen des I-Anteils
00139     
00140     if(!lockctrl){
00141         I = I_usr;                                                  // I-Anteil on/off
00142         KI = KI_usr;                                                // I-Anteil Verstärkung
00143         
00144         return true;                                                // Setzen der Werte erfolgreich     
00145         }
00146     else{ 
00147         return false;                                               // Setzen der Werte nicht erfolgreich
00148         }   
00149     } 
00150 
00151 
00152 bool PIDControl::setKD (bool D_usr, float KD_usr){                   // Setzen des D-Anteils
00153     
00154     if(!lockctrl){
00155         D = D_usr;                                                  // D-Anteil on/off
00156         KD = KD_usr;                                                // D-Anteil Verstärkung
00157         
00158         return true;                                                // Setzen der Werte erfolgreich     
00159         }
00160     else{ 
00161         return false;                                               // Setzen der Werte nicht erfolgreich
00162         }   
00163     } 
00164 
00165 
00166 bool PIDControl::setAWU (float awu_gain_usr){                        // Setzen des Anti-Windups
00167     
00168     if(!lockctrl){
00169         awu_gain = awu_gain_usr;                                    // Anti-Windup Verstärkung
00170         
00171         return true;                                                // Setzen des Wertes erfolgreich     
00172         }
00173     else{ 
00174         return false;                                               // Setzen des Wertes nicht erfolgreich
00175         }   
00176     }  
00177 
00178 void PIDControl::setIlimits (bool integrallimiter_usr, int16_t i_max_usr, int16_t i_min_usr){ // Setzen des Integrallimits
00179 
00180     if(!lockctrl){
00181         integrallimiter = integrallimiter_usr;                      // Integrallimits aktivieren
00182         i_max = i_max_usr;                                          // maximaler I-Anteil 
00183         i_min = i_min_usr;                                          // minimaler I-Anteil   
00184     }
00185 }
00186 
00187 void PIDControl::setUlimits (int16_t u_max_usr, int16_t u_min_usr){  // Setzen des Ausgangsgrößenlimits
00188 
00189     if(!lockctrl){
00190         u_max = u_max_usr;                                          // maximale Stellgröße
00191         u_min = u_min_usr;                                          // minimale Stellgröße  
00192     }
00193 }
00194         
00195  
00196     
00197 void PIDControl::lock (){
00198          lockctrl = true;                                           //  Einstellung der Regelparamieter sperren             
00199     }
00200 
00201 
00202 void PIDControl::unlock (){
00203           lockctrl = false;                                         // Einstellung der Regelparamter freigeben 
00204     } 
00205  
00206     
00207 uint8_t PIDControl::getStatus (){ 
00208     return status ;                                                  // Rückgabe des aktuellen Statusvektors
00209 }
00210 
00211 
00212 void PIDControl::setERFFCT (void (*EXTERN_CTRL_HANDLER)(void)){         // Adresse zur externen Funktion übergeben und Freigabe setzen
00213           extfct = true;                                               // Externe Funktion vorhanden. Freigabe setzen.
00214           CTRL_HANDLER = EXTERN_CTRL_HANDLER;                          // Funktionspointer der Funktion übernehmen     
00215     } 
00216 
00217 //====================================================================================================================================
00218 //                                                   Interne Funktionen
00219 //====================================================================================================================================
00220 
00221 
00222 int16_t PIDControl::log2(int16_t a){                                // Bestimmt die nächstkleinere Zweierpotenz der Zahl a
00223   
00224         if(a == time_last){
00225             return time_last_result;                                // Aktueller Wert entspricht letztem Wert
00226             }               
00227         
00228          a = time_last;                                             // Speichert aktuellen Wert
00229   
00230          static const int DeBruijnFolge[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31};
00231 
00232             a |= a >> 1;                                            // Runden auf die kleinste Stelle
00233             a |= a >> 2;
00234             a |= a >> 4;
00235             a |= a >> 8;
00236             a |= a >> 16;
00237            
00238            time_last_result = DeBruijnFolge[(uint32_t)(a * 0x07C4ACDDU) >> 27];     // Ausgabe der passenden Zweierpotenz
00239            
00240     return time_last_result; 
00241   }
00242 
00243 
00244 void PIDControl::setStatus(int bit){ 
00245     
00246     status  |= (1 << bit);                                           // Setzt das vorher ausgewählte Bit    
00247     
00248     if((extfct) && (bit >= 5 )){                                    // Wenn externe Funktionen aktiviert sind und ein schwerwiegender Fehler abgelegt wird
00249         (*CTRL_HANDLER)();                                          // Aufruf der Externen Funktion   
00250     }  
00251 }
00252 
00253 
00254 void PIDControl::resetStatus(int bit){ 
00255 
00256     int temp = 0xFF;                                                // Maske erstellen
00257     temp ^= (1 << bit);                                             // Maske anpassen 
00258     status  &= temp;                                                 // Resetzen des entsprechenden Bits
00259                                      
00260 }