Hallo Zusammen, habe gerade ein Problem mit meiner PID-Regelung (Im Anhang befindet sich mein Codeausschnitt). Entwicklungsumgebung TWINCAT BECKHOFF. ich habe einen PID-Regler "realisiert" der eine bestimmte vorgegebene Solltemperatur erreichen muss. Die PI Anteile (kp ki) und die Solltemperatur habe ich als Globale Variablen definiert. (D-Anteil wird zunächst nicht implementiert) Output der PID-Regelung steuert mittels PWM (8bit PWM / 255) ein Solid-State-Relai und somit die Heizung. Nun zu meinem Problem: habe im Netz viel über "Anti-Windup" gelesen, doch komme irgendwie nicht darauf, wie ich dies in meinem Programm umsetzen muss. Der I-Anteil steigt auf den maximalen Wert. Ich erreiche den max. Outputwert (255) und erst sobald die Solltemperatur erreicht wird geht dieser Wert runter auf 0, doch das soll ja nach meiner Ansicht schon eher funktionieren sobald man sich an die Solltemperatur nähert, damit die Temperatur geregelt wird und "keine" Überschwingung vorkommt. Was genau muss ich also im Code ändern (wenn mein Code soweit stimmt), damit ich die Temperatur regeln kann (wenn möglich ohne Überschwingung)? Vielen Dank schon mal im Voraus Grüße
Hallo, zunächst mal haben wir deinen Code ja nicht und können dir nicht genau sagen, was du daran ändern musst. Zum anderen: wo hakt es denn mit dem Verständnis? Alles, was ein simples, aber gut funktionierendes Antiwindup macht, ist die Integration im I-Term zu stoppen, wenn die Ausgangsgröße (bei dir also Summe aus P+I) am Anschlag ist. Zum anderen ist es normalerweise nicht so, dass der I-Term bei Solltemperatur auf 0 geht, sondern der P-Term, weil der I-Term gegen die konstanten Wärmeverluste regelt.
Ich seh jetzt erst, dass su den Code ja angehängt hattest. Für mich sieht es so aus, als wäre ein AWU implementiert. Der I-Anteil wird nicht vergrößert/verkleinert, wenn man am oberen/unteren Anschlag steht.
Ich stehe unheimlich auf unvollständigen Code! Oder habe ich da ein Augenproblem? Was sind Out_max und sein Kumpel Out_min? Kannst Du aber auch für Dich behalten;)
Danke erstmal für die schnellen Antworten. Also mein Problem ist, ich habe kein Kühlprozess und muss die aktuelle Temperatur auf eine bestimmte vorgegebene Temperatur bringen. Kann evtl. sein, dass ich Antiwindup falsch verstanden habe. Was in meinem Programm passiert: Der PID Regler ist soweit parametrisiert, dass er zwischen 0 und 100 % Taktung ein Relais ansteuert (über einen Funktionsblock in der die PWM realisiert wurde). Ich begrenze ja den Reglerausgang auf 0-255, heißt bei 255 soll vollgeheizt werden und zwischen 0-255 die PWM durchgeführt und in Takten geheizt werden. Was ich aber nicht verstehe ist, dieser Wert "255" am Reglerausgang fällt erst dann, wenn die Solltemperatur erreicht wird, d. H. es wird erst geregelt, wenn die Solltemperatur erreicht wurde, weil der Wert sich dann zwischen 0-255 bewegt. Somit wird auch weiter in Takten geheizt obwohl die Solltemperatur erreicht wurde. Hoffe jetzt ist es einigermaßen verständlich.. Mirko W. schrieb: > Der I-Anteil > wird nicht vergrößert/verkleinert, wenn man am oberen/unteren Anschlag > steht. Das habe ich auch befürchtet. Mache sowas zum ersten mal, kann sein, dass da vieles evtl nicht stimmt :D Wie kann ich den I-Anteil besser implementieren im Code? Sebastian S. schrieb: > Was sind Out_max und sein Kumpel Out_min? Merke gerade, dass ich die Variablendeklaration vergessen habe mit zu kopieren :D Out_min = 0, Out_max = 255 für die Begrenzung.
:
Bearbeitet durch User
Immer noch unvollständig! In Deinem Falle hat es mit dem Anti-Windup folgendes auf sich: Dein Mikrocontroller hat wahrscheinlich einen Arbeitsbereich, für die PWM, vom 0 bis 255. Ergibt die Berechnung des Korrekturwertes mehr als 255 oder weniger als 0, so wird dieser Wert einfach Begrenzt. <<<<<<<<<<<<<< IF output_value > Out_max THEN output_value := Out_max; limit_on_high := TRUE; ELSIF output_value < Out_min THEN output_value := Out_min; limit_on_low := TRUE; END_IF; <<<<<<<<<<<<<< Auf der Ebene von Bits bzw. Bytes passiert hier nämlich folgendes: Max 255 + 1 = 256 = nicht darstellbar = 0 uups. Min 0 - 1 = -1 = nicht darstellbar = 255 uups. Vorsicht manche µP können, aus Sicht der PWM, auch mehr als 255. Bei z.B. 12 Bit heißt das 4095 (MAX). Oder 0 bis 4095. Muttu µP fragen.
:
Bearbeitet durch User
Muzaffer S. schrieb: > Danke erstmal für die schnellen Antworten. > > Also mein Problem ist, ich habe kein Kühlprozess und muss die aktuelle > Temperatur auf eine bestimmte vorgegebene Temperatur bringen. > > Ich begrenze ja den Reglerausgang auf 0-255, heißt bei 255 soll > vollgeheizt werden und zwischen 0-255 die PWM durchgeführt und in Takten > geheizt werden. > > Was ich aber nicht verstehe ist, dieser Wert "255" am Reglerausgang > fällt erst dann, wenn die Solltemperatur erreicht wird, d. H. es wird > erst geregelt, wenn die Solltemperatur erreicht wurde, weil der Wert > sich dann zwischen 0-255 bewegt. Somit wird auch weiter in Takten > geheizt obwohl die Solltemperatur erreicht wurde. > > Hoffe jetzt ist es einigermaßen verständlich.. Bei deinem I Part ist das P auch mit drinnen. Damit ist der I von Anfangsn schon zu hoch. Wenn also P von anfangen 255 hat ist I auch 255. Da kann beim anähern der P kleiner werden wie er will weil I auf Anschlag ist. Wenn nur 255 und 0 kommt sind die Werte zu stark. I hängt ja von P ab und wenn Kp zu groß ist wirkt I kaum und P baut zu spät ab. Gruß JackFrost
:
Bearbeitet durch User
Nur fürs Verständnis: 1. Weshalb willst du ein Antiwindup? 2. Was glaubst du, ist das Problem an Mirko W. schrieb: > Der I-Anteil > wird nicht vergrößert/verkleinert, wenn man am oberen/unteren Anschlag > steht. ? 3. Was hast du bisher konkret versucht und wo hast du den Code denn her? Allein hier im Forum gibt es mehrere Threads mit zum Teil gutem Code. 4. Was für Erfahrungen hast du bisher mit Regelungstechnik? Ausbildung? Studium? damit der I-Anteil im Code wirklich nur den I-Anteil macht, müsste hier
1 | I_Part_Zw_Summe := ((((error * GVL_VAR.kP) + (delta_error_last_cycle * GVL_VAR.kP)) / 2.0) * (cycle_time / GVL_VAR.kI)); |
in
1 | I_Part_Zw_Summe := (delta_error_last_cycle * (cycle_time / GVL_VAR.kI)); |
ersetzt werden.
Der wesentliche Ansatz an Temperaturreglern ist, den PI Regler als Korrektur zu einer Vorwaertssteuerung zu verwenden. Bedeutet der Wert fuer das Stellglied wird erst mal per Tabelle bereitgestellt. Die Tabelle bildet die Temperaturdifferenz zwischen Solltemperatur und Umgebungstemperatur auf das Stellglied ab. Das misst man einfach mal durch. Stellwert 128 ergibt welche Temperatur ? Stellwert N ergibt welche Temperatur..., fuer alle N. Und dieser Stellwert wird durch den PI nur noch korrigiert.
Du weisst doch sicher ungefähr, bei welchem Stellwert sich der Regler auf Dauer für deinen Sollwert einpegelt und du kannst das Zeitliche Verhalten abschätzen. Mach es wie folgt: Sobald deine Temperatur erstmalig über einen Wert knapp unterhalb vom Sollwert kommt, belegst du den I - Anteil vom Regler so, dass sich die für den Sollwert zu erwartende Stellgröße einstellt. (Nur, wenn du das noch nicht getan hast - sonst kann bei Messschwankungen der Regler "hängen" bleiben) Gleichzeitig merkst du dir in einem Bit, dass die dieses Überschreiben durchgeführt hast. Sobald die Temperatur wieder auf einen Wert weiter unterhalb des Sollwerts gefallen ist, setzt du das Merkerbit zurück und gibst das Überschreiben für den nächsten Aufheizvorgang wieder frei.
Mirko W. schrieb: > Weshalb willst du ein Antiwindup? Das habe ich im Netz gelesen, dass das die Lösung für mein Problem ist Mirko W. schrieb: > Was hast du bisher konkret versucht und wo hast du den Code denn her? Zum Teil selber probiert und viel im Netz gefunden. Hab mein Program durch mein embedded Pc gejagt und ausprobiert. Die Werte und der Reglerausgang wird so berechnet wie beschrieben. Die skallierung und Begrenzung des Outputs funktioniert auch. Der Reglerausgang ist an eine PWM-Funktion verknüpft, der einen Puls in 10s Abständen generiert und die Heizung über dine SSR taktet. Mirko W. schrieb: > Was für Erfahrungen hast du bisher mit Regelungstechnik? Ausbildung? > Studium? Ich studiere derzeit Angewandte Informatik, habe aber bisher nur auf C, C++, Python programmiert. Sowas ist mir recht neu :) Patrick schrieb: > Mach es wie folgt: Danke für den Ansatz, das werde ich mal ausprobieren..
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.