Hallo Leute, ich bin dabei mich in den PI- Regler einzuarbeiten. Ich habe eine blöde Frage zu der Stellgröße (y) ich möchte dass der Regler ein Wert zwischen 0 und 255 ausgibt. Für y habe ich den Datentyp int genommen, wenn jetzt der Regler aber runter regelt läuft der Wert in den negativen Bereich und um das zu vermeiden habe ich den begrenzt. if(y1<0) {y=0; } else {y=y1;} if(y1>255) {y=255;} else {y=y1;} Das funktioniert aber nicht, sobald die Variable y1 im negativem Bereich ist, springt der y auf 255 anstatt auf 0. Wo ran liegt das was mache ich falsch?
was hast du denn für ein Datentyp für y1 genommen? char ? dann kann y1 nicht <0 oder >255 werden! Ohne Quelltest kann man nicht viel zum fehler sagen
uint16_t ReadChannel(uint8_t mux); uint16_t w; uint16_t x; uint16_t e; uint16_t esum; uint16_t Kp=1; uint16_t Ki=1; uint16_t Kd; uint16_t y; uint16_t yi; uint16_t y1; ISR (TIMER1_COMPA_vect) { esum = esum + e; yi = Ki * esum; } int main (void) { //Initialisierung des LCD Displays 4 Bit Mode LCD_Init(); //Löschen des Displays LCD_Clear(); //Initialisierung von TIMER1 TCCR1B |= (1 << CS12 | 1 << WGM12 | 1 << CS10); TCCR1A = 0b00000000; TIMSK |= (1 << OCIE1A); OCR1A = 15624; //Initialisierung von TIMER2 (PWM OC2) DDRD |= (1<<7)|(1<<4); TCCR2 |= (1<<WGM20|1<<COM21|1<<COM20|1<<CS20|1<<CS21|1<<CS20); DDRD |= (1<<7); //Globale Interrupts freischalten sei(); __________________________________________________________________ do { w = ReadChannel(1); x = ReadChannel(7); e = w - x; y1 = Kp * e + yi; //yi im Interrupt if(y1<0) {y=0; } else {y=y1;} if(y1>255) {y=255;} else {y=y1;} OCR2 = y ; //Ausgabe eines Textes auf dem LCD Display LCD_Print(0,0,"Soll = %i ",w); LCD_Print(1,0,"Ist = %i ",x); LCD_Print(2,0,"Diff = %i ",e); LCD_Print(3,0,"Stell = %i %i ",y,y1); } while(1); } ende + noch die ADC Funktion aber die Funktioniert ja. So das ist mein Quelltext. @hugo y1 ist auch uint_16t
dein yl ist ein uint16_t (unsigned int), der kann doch gar nicht negativ werden (wie schon gesagt), probier mal int16_t
ich würde aus persönlicher erfahrung behaupten, dass du das mit der auflösung nur schwer stabil hinkommst. angenommen dein soll ist 128, deine maximal mögliche regelabweichung 50 und schon kann dein P nur noch 2 sein ohne über deinen maximalwert 255 rauszuschießen. so ungefähr: 128 + (2*50) = 228 wenn du extrem grob auflöst und richtig gut aufpasst beim skalieren deiner werte geht es vielleicht irgendwie. die andere frage ist wofür du den I-Anteil brauchst, bzw. ob du den wirklich brauchst und nicht vielleicht mir einer minimalen regelabweichung leben kannst. würde es dir zumindest wesentlich einfacher machen und dein system wäre stabiler. schönen abend noch!
du solltest die variablen in der interrupt funktion auch zu volatile definieren. Bis dann ...
Der Regler ist eine reine Übungsaufgabe, der leider noch nicht funktioniert.
@Tupf wie meinst du das? kannst du es näher erklären? Ich bin noch ein ziemlicher Anfänger.
gehe bitte in das GCC Forum. Das Forum kannst du links in der Spalte anklicken. Dann suche im Betreff nach volatile. Da gibt es hunderte von Erklaerungen. Viel Spass ...
Hallo, ich würde erstmal grundsätzlich den PI-Regler formulieren: y(t) = k*( e(t)+1/Ti*int(e(t)) ) oder y(t) = k*e(t) + int(k/Ti*e(t)) Als Abtastregler und in erster Näherung: y = k*e + e_int mit e_int = e_int + T * k/Ti*e Damit das ganze nicht überläuft, muss man jede Einzelrechnung auf Überlauf prüfen: e_int < min: e_int = min e_int > max: e_int = max y = k*e + e_int y < min: y = min y > max: y = max So läuft der Regler nicht über und kommt auch sofort aus der Begrenzung heraus, wenn e(t) das Vorzeichen wechselt. e(t) muss vorzeichenbehaftet laufen, wie alle Werte, die im Regler verarbeitet werden. Ich würde anfangen und alles mit int16 rechnen. Dann kann man den Ausgang auf 0 bis 255 begrenzen und als unit8 ausgeben. Gruss
Ich danke euch allen, ich habe mein Regler jetzt am laufen. Als Datentyp habe ich jetzt wirklich den int genommen und damit funktioniert es. Und das e und esum habe ich begrenzt. Außerdem habe ich in die Formel das Ta rein genommen, was vorher eigentlich auch nicht kritisch war, weil die Abtastzeit 1 sek betrug. Jetzt frage ich mich, was ist wenn die Abtastzeit kürzer werden soll? Den Interrupt kann ich ja verkürzen wie ich möchte, die Zeit muss ich aber auch in meine Rechnung einbeziehen, versteht der Kontroller auch Kommazahlen? z.B. 0.2 sek welchen Datentyp muss ich dafür nehmen float?
Hallo, es ändert sich die Berechnung des Integrals: e_sum = e_sum + Ta * k/Ti*e wenn also die Abtastzeit kleiner wird, muss das Integral pro Abtastpunkt weniger stark anwachsen. Der Faktor für das Integral wird also kleiner: e_sum = e_sum + kI* e mit kI = Ta * k/Ti und der Reglerausgang (Stellgrösse) y = k*e + e_sum Gruss Waldo
Hallo, ein PI-Regler wird in der Regel folgendermaßen formuliert: y(t) = k*( e(t)+1/Ti*int(e(t)) ) Es gibt die Reglerverstärkung k und die Integrationszeitkonstante Ti oft auch als Nachstellzeit bezeichnet. Die Reglerverstärkung bewertet die Summe aus P-Anteil und I-Anteil, ist also die Gesamtverstärkung. Das Integral sollte also wie folgt berechnet werden: yI = yI + Ta * k/Ti * e mit Ta ... Abtastzeit Ti ... Integrationszeit bzw. Nachstellzeit k ... Reglerverstärkung Der Reglerausgang: y = k * e + yI Also muss in der Interruptroutine nicht einfach die Regelabweichung aufsummiert werden. Das hat den Nachteil, dass die Begrenzung schwer zu machen ist. Es ist besser yI in der Interruptroutine zu rechnen und die Begrenzung zu machen: yI = yI + Ta *k/Ti * e yI > max: yI = max yI < min: yI = min Die Konstante Ta * k/Ti kann im Voraus berechnet werden, um Zeit zu sparen. Gruss
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.