Hallo Leute,
also ich habe schon vor paar Tagen ein paar Fragen zum Thema PI-Regler
in C programmieren gehabt, siehe:
[[Beitrag "PI-Regler für GS-Motor"]]
Einiges ist mir noch überhaupt nicht klar.
Ich möchte einen Gleichstrommotor regeln.
Angetrieben wird dieser Motor mit PWM, ich hab es so realisiert, dass
ich einen Timer mitlaufen lasse mit Reloadregister= FCE0. Bei bestimmten
Ereignissen hab ich dann nen Signalwechsel an den Pins, die dann zum
Motortreiben führen. Also am Anfang sag ich: P6 = 0, P7 = 1; wenn der
Timerwert mit einem Registerwert CC30 übereinstimmt (compare mode), dann
P6=1, P7 =0; wenn der Timer abgelaufen ist, dann wieder P6 =0, P7 =1
usw.
Das heißt mein Signal hat eine Periode von FFFF-FCE0 und die Breite der
pos. Periode ist Wert von CC30-FCE0.
Wenn die Breite des pos. Impulses = Breite des neg. Impulses
(FFFF-FCE0)/2 = 400dez , dann dreht sich der Motor nicht, denn der
Effektivwert der Spannung = 0V. (falls das einer kritisch hinterfragen
mag, das ist wirklich so, ich hab es schon ausprobiert).
Mit der Stellgröße des Reglers möchte ich Einfluß auf PWM nehmen, d.h.
die Breite des pos. Impulses beeinflussen und zwar nur des pos. Imp.
weil mein Motor sich nur in eine Richtung drehen muss.
Eingentlich müsste ich die Stellgröße auf 2^16 begrenzen, weil sich sich
ja aus der Differenz zweier Registerinhalte berechnet, allerdings und
jetzt kommt endlich die Frage: meine Stellgröße bewegt sich nur im
Bereich zw. 400dez und 800dez, denn sonst würd sich der Motor ja in
andere Richtung drehen. Also müsste ich die doch nur auf 1024 begrenzen,
oder????
Später verwende ich sie in einer unsigned long int variable, also
vielleicht doch auf 2^16 begrenzen???
Alle. Die Rechnung hat einen Raum von 2^16, genannt Integer. Macht Sinn.
Das Stellglied ist schon bei 400+400 am Anschlag. Du willst nur positiv
aussteuern. Dann ist der Steuerbereich noch 400. Dann wuerde ich den
Rechenbereich auch auf 128 * 400 begrenzen.
Man bildet den 2^16er Raum auf 400 ab und zaehlt noch 400 dazu. Nein ?
If (Rechnung > 128*400) then Rechnung:=128*400;
Stellglied:= 400+ Rechnung div 128;
Das div 128 ist dasselbe wie Rechtsschieben 7
Wir erniedrigen den Wertebereich von kleiner 65535 auf 400, am
Guenstigsten ist mit 128 dividieren. Eine Division mit 128 ist sieben
Stellen nach rechts schieben. Damit wir nicht zuviel bekommen bBegrenzen
wir zuerst auf 128*400. Alles was groesser ist wird auf 128*400 gesetzt.
Nach der Division erhalten wir somit als maximum 400.
Nein ?
Also 400dez ist ja (FFFF-FCE0)/2. Bei FCE0 fängt mein Timer an zu
zählen.
Wenn der WErt des Timers den im CC1_C30 entspricht, gibt es nen
Interrupt und nen Flankenwechsel.
Ich hab mir überlegt die Pulsbreite des PWM-Singales mit HIlfe von
CC1_C30 zu steuern. Das heißt der Wert in diesem Register wird in
Abhängigkeit der Stellgröße gesetzt. So wie ich es verstanden hab, ist
die Stellgröße die Pulsbreite. Der Wert des CC1_c30 darf sich nur im
Bereich zwischen FE6F und FFFF bewegen. Die Differenz beträgt dann genau
400dez.
Also hab ich die Stellgröße so begrenzt:
// Begrenzung des Stellenwertes auf die maximale Größe
1
if(pi_r.Stellwert<65135)// Begrenzung nach unten, also auf FE60
2
{pi_r.Stellwert=65135;}
3
4
if(pi_r.Stellwert>65535)// Begrenzung nach oben, also auf FFFF
<Dh den Regelbereich von irgendwas kleiner 65k (400*128) erniedrigt man
auf 400 und addiert diese zu 0xFE60 fuer das Stellglied.>
Worauf bezieht sich diese Aussage? Was sie an mich gerichtet?
Einige Unguenstigkeiten.
-Die Begrenzung wird nie aufgehoben.
-die div 100 ist nicht gut, mach 128.
Nee das wird nichts. Bei welchem Fehler beginnt sich die Stellgroesse zu
bewegen ?
Mach :
pi_r.Stellwert= 0xFE60 + Kp*pi_r.Regelabweichung;
..
Begrenzung =0;
if(pi_r.Stellwert<0xFE60) // Begrenzung nach unten, also auf FE60
{
pi_r.Stellwert = 0xFE60;
Begrenzung = 1; // Rergler läuft in der Begrenzung
}
if(pi_r.Stellwert>0xFFFF) // Begrenzung nach oben, also auf FFFF
{
pi_r.Stellwert =0xFFFF;
Begrenzung = 1; // Regler läuft in der Begrenzung
}
also die Begrenzung hab ich aufgehoben, da hattest du völlig Recht.
Die Division durch 100 hat eigenlich andere Bewandnis und zwar ist das
meine Ta von 0.01. Ich dividiere duch 100, weil ich beim Multiplizieren
der int mit Zahlen < 0 schlechte Karten hab.
<Mach :
pi_r.Stellwert= 0xFE60 + Kp*pi_r.Regelabweichung;
..>
Wo kommt deiner Meinung nach dieser Therm hin? Und wieso soll ich nach
unten bis FE60 begrenzen? Ich meine, es ist bis FE6F!!
Dein Antiwindup ist Mist. Man läßt den Integralanteil nicht schlagartig
komplett weg, wenn man in der Begrenzung ist (woraufhin dann keine
Begrenzung mehr da ist, also wieder rein, wieder raus, wieder rein...),
sondern begrenzt ihn.
Meine Punkte.
-Kostanten so schreiben wie sie sind. HexKonstanten in Hex.
-Die Regel Berechnung und das Stellglied trennen. Lieber der
Uebersichtlichkeit halber nochmals eine zusaetzliche Zeile. In dem Falle
die Regelung zwischen 0 und irgendwas rechnen, dann auf
Herunterskalieren auf die 0 bis 400 und dann zum Wert FE6F hinzuzaehlen.
Ich denke dieser Wert ist sowieso dynamisch, dh Temperatur- und
allenfalls Betriebsdspannungsabhaengig.
Kartoffel wrote:
> ok, und was macht das Ding dann, wenn ich mich in der> Begrenzung befinde? Wie errechnet sich dann der I-Anteil??
bin zwar kein mechatroniker aber hab trotzdem einen PID Regler
gecoded...
Also, wenn du in der Begrenzung bist tut der gar nichts mehr (der I
Anteil).
Allerdings könnte ich dir ein wenig support geben wenn du meinen Code
aus der Codesammlung verwenden würdest... ^^
lg
@ JÜrgen G. und alle anderen:
Also laut deiner Aussage stimmt ja dann die Aussage des "mechatronikers"
nicht und mann kann den I-Anteil in der Begrenzung schon weg lassen
oder?
Wenn nicht, also dann weiß ich überhaupt nicht, wie ich den Windup
verhindern kann....
// Begrenzung des Stellenwertes auf die maximale Größe
51
52
if(pi_r.Stellwert<65135)// Begrenzung nach unten, also auf FE60
53
{
54
pi_r.Stellwert=65135;
55
Begrenzung=1;// Rergler läuft in der Begrenzung
56
57
}
58
59
elseif(pi_r.Stellwert>65535)// Begrenzung nach oben, also auf FFFF
60
{
61
pi_r.Stellwert=65535;
62
Begrenzung=1;// Regler läuft in der Begrenzung
63
}
64
65
else
66
{
67
Begrenzung=0;
68
}
69
70
returnpi_r.Stellwert;// Übergabe Stellgröße
71
}
Ich meine, jetzt passt es einigermaßen...das mit dem Skallieren kommt
no.
Allerdings hab ich jetzt ne Warnung beim Aufrufen der Fkt. PI_Init.
Ich ruf sie in main vor der Endlosschleife auf. Hab es auch schon
probiert, die Fkt. als extern zu deklarieren, dat geht au net...:-(
Weiter im Text.
Ach übrigens, das mit der Fkt. PI_Init hab ich behoben.
Also : Der Stellwert.
Was sagt er mir denn genau bei einem PWM-Singal. Zur Erinnerung: ich
bewege mich in einem Bereich zwischen 400 und 800 (Pulsbreite). Bei 400
steht der Motor, bei 800 dreht er voll auf.
Also ich berechne mich meiner Reglergleichung den Stellwert. Also ich
hab da noch Probleme zu verstehen was der genau darstellt. Ist das eine
Zahl im Bereich zwischen 400 und 800? Die Pulsbreite steuer ich ja mit
einem Register. Muss dann der neu errechnete Reglerstellwert in dieses
Register reingeschrieben werden?????