Hallo noch mal,
Leute Hilfe, ich programmier einen PI-Regler für einen GS-Motor.(mit
Keil und XC167 von Infineon).
Die Reglerparameter habe ich theoretisch bestimmt, also müssten die
passen.
Hier der Code:
Stellwert=(pi_r.Kp*(pi_r.Regelabweichung))/16+((pi_r.Ki*pi_r.I_Anteil)*pi_r.Ta)/10000;//Ta= 210ms, nicht durch 1000, weil Ki=12/10
76
77
printf("Stellwert: %d",Stellwert);
78
printf("\n");
79
80
81
if(Stellwert<20)// Begrenzung nach unten, also auf FE6F
82
{
83
Stellwert=20;
84
Begrenzung=1;// Rergler läuft in der Begrenzung
85
86
}
87
88
elseif(Stellwert>400)// Begrenzung nach oben, also auf FFFF
89
{
90
Stellwert=400;
91
Begrenzung=1;// Regler läuft in der Begrenzung
92
}
93
else
94
{
95
Begrenzung=0;
96
}
97
98
printf("Stellwert nach Begrenzung: %d",Stellwert);
99
printf("\n");
100
101
pi_r.Stellwert=MIN+Stellwert;
102
103
104
printf("pi_r.Stellwert: %X",pi_r.Stellwert);
105
printf("\n");
106
returnpi_r.Stellwert;// Übergabe Stellgröße
107
}
Der pi_r.Stellwert lad ich in ein Register, mit dem ich die Breite von
PWM einstelle, so:
CC2_CC30 = Regeln (Drehzahl_mot);
Hab mir ein paar Werte ausgeben lassen. Die Datei hab ich angehängt.
Die Solldrehzahl beträgt 500U/min.
Mein Regler pendelt sich bei ca. 150 U/min ein und sense.....
Könnt ihr BITTE drüber schauen, ich find den Fehler nicht:-((((
Dein Log mal etwas besser formatiert, sodass man auch die
zeitliche Entwicklung der Werte erkennen kann
Istdrehzahl Abw Stellwert Begr
462 38 11 30 FE8D
248 252 24 30 FE8D
165 335 29 30 FE8D
157 343 30 30 FE8D
162 338 115 115 FEE2
861 -361 -19 30 FE8D
428 72 7 30 FE8D
173 327 23 30 FE8D
163 337 24 30 FE8D
156 344 24 30 FE8D
160 340 24 30 FE8D
155 345 24 30 FE8D
156 344 24 30 FE8D
154 346 24 30 FE8D
153 347 24 30 FE8D
153 347 24 30 FE8D
154 346 24 30 FE8D
154 346 24 30 FE8D
155 345 24 30 FE8D
162 338 24 30 FE8D
156 344 24 30 FE8D
161 339 24 30 FE8D
(Du solltest wirklich dein Programm so modifizerien, dass es
diese Tabelle ganz von alleine erzeugt. Es ist nämlich
ziemlich fad, jedes mal diese Formatierung händisch zu machen)
Was auffällt. Deine Regelabweichung wird nicht kleiner. Das
ist für mich der Hinweis, dass dein I Anteil nicht stimmt.
Das könnte jetzt wiederrum von deiner seltsamen Anti-Windup
Begrenzung kommen oder aber Ki hat ganz einfach das falsche
Vorzeichen.
Anti Windup:
Beim Anti Windup begrenzt du die Summe auf einen bestimmten
Maximalen oder Minimalen Wert, damit die nicht unendlich hoch
wird. Das hat nichts mit dem Stellwert der hinten raus kommt
zu tun.
pi_r.I_Anteil = pi_r.I_Anteil + pi_r.Regelabweichung;
if( pi_r.I_Anteil > SomeMaximum )
pi_r.I_Anteil = SomeMaximum;
if( pi_r.I_Anteil < SomeMinimum )
pi_r.I_Anteil = SomeMinimum;
Was noch auffällt.
Du hast hier
248 252 24 30 FE8D
165 335 29 30 FE8D
157 343 30 30 FE8D
162 338 115 115 FEE2
861 -361 -19 30 FE8D
einen enormen Sprung. Sobald der Regler aus deiner 'Begrenzung'
raus kommt, fährt er die Stellgröße extrem in die Höhe. Wieder
ein Hinweis darauf, dass mit der Begrenzung was nicht stimmen
kann.
Warum debuggst du dein Programm nicht Schritt für Schritt.
Dafür ist der Debugger nämlich da.
Haste kein Main (void)-Funktion geschrieben?
Und wie wird die Solldrehzahl eingegeben?
@AC/DC:
hier ist das Debuggen nicht möglich, da das ganze ja ein physikalischer
Prozess ist. Im Einzelschrittmodus hat man keinen zusammenhängenden
Prozess mehr.
Ein Main hab ich schon geschrieben, ist hier nicht von Bedeutung, da da
nur Sachen initialisiert werden etc.
Kartoffel wrote:
> @AC/DC:>> hier ist das Debuggen nicht möglich, da das ganze ja ein physikalischer> Prozess ist. Im Einzelschrittmodus hat man keinen zusammenhängenden> Prozess mehr.
Um so wichtiger, dass du Log Files hast, mit denen man auch etwas
anfangen kann.
Nimm die neuberechnung für deinen I-Anteil aus der If bedingung raus.
Dann den I - Anteil begrenzen auf z.B. +- 10 oder +- 15
Dann den P- Anteil begrenzen auf z.B. +- 15 oder +- 20
Dann summieren
Dann alles begrenzen auf 20 bis 400
Ich denke, dass bei deinem log die untere Begrenzung bei 30 lag. Wenn
deine Stellgroße nun kleine als 30 ist (z.B. P =15, I= 5), wird dein I
Anteil niemals größer. also reiner p_ Regler mit offset, da I=konstant.
@AC/DC:
>hier ist das Debuggen nicht möglich, da das ganze ja ein physikalischer>Prozess ist. Im Einzelschrittmodus hat man keinen zusammenhängenden>Prozess mehr.
Meine Frage nach der Sollwertangabe hast du leider nicht beantwortet.
Also nach einer Dokumentation über das Debuggen macht es keinen Sinn
wenn Echtzeit oder die Aktion/Reaktion der Hardware getestet werden
soll.
(Ich vermute da du das mit physikalischer Prozess meinst)
Wenn du mit printf Werte ausgibst ist das für mich sehr wohl debuggbar.
Aber mach man es so wie du das für richtig hälst. Vielleicht bin ich mit
meinem Vorschlag ja auf dem Holzweg. Habs ja nur gut gemeint.
Wie bereits schon festgestellt:
Liegt dein Stellwert unter der Mindestgrenze, hat dein I-Anteil keinen
Einfluss mehr -> P-Regler -> bleibende Regelabweichung
@ gast und gast 99:
also normalerweise würde ich die untere Grenze der Stellgröße auf 0
begrenzen. Das Problem dabei ist, dass bei Stellgröße=0 die
Motordrehzahl auch = 0 U/min wird. Heißt: Motor dreht sich nicht.
Meine Drehzahlbestimmung erfolgt mittels Interrupt, der bei jedem pos.
Impuls des Encoders ausgelöst wird. Das bedeutet, wenn sich der Motor
nicht dreht, dann kann auch keine Drehzahlbestimmung mehr erfolgen und
es kann nicht festgestellt werden, dass die aktuelle Motordrehzahl = 0
ist. Es wird mit dann mit alten Werten geregelt und nicht mit den
aktuellen.
Du überprfts bei einer bestimmten anzahl von interrupten, wieviel zeit
vergangen ist?
Überprüfe doch in regelmäßigen zeitabständen, die anzahl der interrupte
und mache dann einen reset.
Wenn du in der unteren begrenzung bist, kann dein I anteil die bleibende
regelabweichung nicht mehr ausregeln.
Was macht deine regelung denn bei einer sollgröße (z.B. 1500 U/min), bei
der deine stellgröße nicht in der begrenzung arbeitet?
Was ist denn nun?
Wie sieht dein Programm aus und klappt das jetzt mit der
Begrenzung des I-Anteils?
Es kann doch nicht so schwer sein, die 4 Zeilen Code mal
abzuändern.
So ungefähr müsste das aussehen. Ob die +- 1000 bei der Begrenzung
der I-Anteils sinnvoll sind oder nicht, kann ich so nicht sagen.
Das muss man ausprobieren.
@ Karl heinz Buchegger:
hab ich doch schon lang getan, hab noch nicht gepostet gehabt, weil es
noch nicht optimal läuft.
Den I_Anteil hab ich zufälligerweise auch auf +/-1000 begrenzt. Hab es
aber auch mit anderen Werten ausprobiert, der Regler verhält sich bei
verschiedenen Drehzahlen anders, heißt bei 500 u/min ist die Begrenzung
von 1000 gut, bei 1000u/min eine andere....
Kartoffel wrote:
> verschiedenen Drehzahlen anders, heißt bei 500 u/min ist die Begrenzung> von 1000 gut, bei 1000u/min eine andere....
Lass mich raten, du hast Schwingungen?
Ich würde mich auch an deiner Stelle nicht zusehr an die K-Parameter
klammern. Auch wenn du die theoretisch bestimmt hast (oder gerade
deswegen)
@ Karl heinz Buchegger:
ja, der Motor bewegt sich total ruckartig und manchmal regelt er sich
nicht auf die Solldrehzahl ein. Z.B. bei einer niedrigen Solldrehzahl
von unter 300, schwingt er sich auf ne Drehzahl von ca. 70 ein.
Vielleicht sollte ich wirklich an dem Kp noch drehen.....??
Wegen dem Timer:
Du nimmst die kleine auftretenden Drehzal und bestimmst die Zeit die
dann ein Interupt dauert.
Sagen wir mal auf niedrigster Drehzahl kommt alle 100ms ein Interupt.
Dann startest du einen Timer der bei etwa 150ms überlauft/einen Compare
auslöst.
Im Interupt für die Drehzalmessung sezt du den Timer auf 0.
Timer interupt tritt nie auf --> Der Motor dreht
Timer interupt tritt auf --> Der Motor steht
Ein Motor hat eine statische (konstant) und eine dynamische (in
Abhängigkeit von der Drehzahl) Reibung. Beides muss man (zumindest)
näherungsweise bestimmen und dann kompensieren.
Mit einfach an einem Parameter drehen wird es echt schwer. Gib doch
einmal genauere daten zum Motor (Datenblatt?).
sodala, jetzt hab ich ein bisschen was geändert, denn die
Stellwertbegrenzung:
1
if(Stellwert<=0)// Begrenzung nach unten, also auf FE6F
2
{
3
Stellwert=30;
4
5
}
stimmt ja nicht. Das hab ich nur vorläufig so gemacht, weil bei
Stellwert = 0(das wär die richtige Begrenzung), die Drehzahl auch auf 0
gesetzt wird.
Die Drehzahlermittlung geschieht aber nur bei nem Interrupt durch pos.
Impuls vom Encoder. Das würde heißen: es kann nicht festgestellt werden,
dass die Drehzahl = 0 ist.
Jetzt hab ich es so geändert:
1
Drehzahl_mot=(unsignedint)(Drehz_sum/Durchlauf);
2
if(Stellwert_alt==0)
3
{
4
Drehzahl_mot=0;
5
Drehz_sum=0;
6
Durchlauf=0;
7
8
}
in Drehz_sum ist die Summe der Drehzahlen über eine Umdrehung (500
Impulse).
Die Ausgabe der Werte, hab ich angehängt. Etwas haut da nicht hin....
Wieso zeigt er mir die pi_r. Stellwert so komisch an?
Ausgabe:
Kartoffel wrote:
> signed long int I_Anteil; // kann auch negativ werden
Na wer sagts denn. Das ist ein long. Damit muss die
Formatieranweisung dafür %ld lauten.
Hab die Ausgabe jetzt berichtigt. Hab aus dem I-Anteil auch nen unsigned
int gemacht.
Gestern ist mir noch ein Fehler aufgefallen und zwar: die Aufrufperiode
des Reglers war größer als die Streckenzeitkonstante des Reglers (=Ta
beim PT1=12,77ms).
Hab die Aufrufperiode jetzt auf ca. 1ms reduziert.
Außerdem wurde mir empfohlen, die Periode von PWM auch auf ca. 1ms
einzustellen, ich hatte sie viel schneller eingestellt gehabt.
Weiß jemand warum?
Ich hab es schon gemacht, bin jetzt auch im hörbaren Bereich und es
piepst schrecklich...
Stellwert=(pi_r.Kp*(pi_r.Regelabweichung))/5+((pi_r.Ki*pi_r.I_Anteil)*pi_r.Ta)/10000;//Ta= 210ms, nicht durch 1000, weil Ki=12/10
46
47
48
if(Stellwert<=0)// Begrenzung nach unten, also auf FE6F
49
{
50
Stellwert=0;
51
52
}
53
54
if(Stellwert>400)// Begrenzung nach oben, also auf FFFF
55
{
56
Stellwert=400;
57
}
58
59
Stellwert_alt=Stellwert;
60
pi_r.Stellwert=MIN+Stellwert;
61
62
printf("%d\t%d\t%d\t%d\t%u\t\n",Istdrehzahl,
63
pi_r.Regelabweichung,
64
pi_r.I_Anteil,
65
Stellwert,
66
pi_r.Stellwert);
67
68
69
returnpi_r.Stellwert;// Übergabe Stellgröße
70
}
Hab die Werte, die ich beobachte angehängt. Irgendwie ist es jetzt so,
dass dass egal wie ich mein Ki verändern tue, sich nichts ändert. Ich
hatte Ki zwischen 1 und 10000 und meine geregelte Istdrehzahl hat sich
nicht geändert.
Schau dir doch mal dein LOG File an.
Dein I-Anteil ist ständig in der Begrenzung von +100.
Wie soll denn da der Regler die Stellgröße noch erhöhen
können, wenn die Begrenzung das verhindert.
Was wird das eigentlich? Soll jetzt das Forum deinen Regler
per Ferndiagnose komplett debuggen? Ein bischen mehr
Eigeninitiative!
@ Karl heinz Buchegger:
also an der Begrenzung des I-Anteils ist es nicht gelegen. Egal ob ich
auf 100, 1000 oder 10000 begrenzt habe, hatte ich das gleiche Verhalten.
Habe das Problem jetzt orten können(aus Eigeninitiative :-)).
Wenn ich Ki=100 genommen habe und die Reglergleichung so:
dann hat es nicht funktioniert und er hat nie auf den Sollwert geregelt.
Wenn ich allerdings Ki=1 hatte und die 100 mit den 10000 verrechnet hab
(mathematisch eigentlich das Gleiche).
Die Gleichung schaut so aus:
Dann hats funktioniert. Erklären hab ichs mir noch nicht können, bin
eingentlich durch Ausprobieren drauf gekommen. Werd mir jetzt noch
Gedanken machen, wieso es so funktioniert und anders nicht.
Ach ja, die /10000 kommen von der Abtastzeit von 1,6ms.
Die hatte ich am Anfang 0,2 s gewählt und die war eindeutig zu groß
gewählt (auch Eigeninitiative!!!).
> Erklären hab ichs mir noch nicht können
Schau dir die Datentypen der beteiligten Variablen in deiner
Formel an un d überlege ob es da zu Überläufen kommen kann.