Forum: Mikrocontroller und Digitale Elektronik Immer noch Fragen zu PI-Regler


von Kartoffel (Gast)


Lesenswert?

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???

von sechsminuszwei (Gast)


Lesenswert?

Ja, moeglichweise muss  mal zwischendurch skalieren. Das ist ganz 
normal.

von Kartoffel (Gast)


Lesenswert?

also auf wieviel Bit wird sie begrenzt? Welche meiner Überlegungen ist 
denn richtig?

von sechsminuszwei (Gast)


Lesenswert?

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

von Kartoffel (Gast)


Lesenswert?

was ich noch nicht ganz verstehe: wieso auf 128*400??????

von sechs ueber drei (Gast)


Lesenswert?

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 ?

von Kartoffel (Gast)


Lesenswert?

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
5
{pi_r.Stellwert =65535;}

Oder hab ich da nen Denkfehler??

von sechs ueber drei (Gast)


Lesenswert?

Das kann man so machen. Ja.

von Michael Wilhelm (Gast)


Lesenswert?

Wie ist pi_r.Stellwert denn implementiert? Wenn das ein unsigned int 
ist, geht die Abfrage (Begrenzung nach oben) in die Hose.

MW

von sechs ueber drei (Gast)


Lesenswert?

Dh den Regelbereich von irgendwas kleiner 65k (400*128) erniedrigt man 
auf 400 und addiert diese zu 0xFE60 fuer das Stellglied.

von Kartoffel (Gast)


Lesenswert?

Stellwert ist ein unsigned long int. Wieso geht die Abfrage denn in die 
Hose??

von Kartoffel (Gast)


Lesenswert?

<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?

von Michael Wilhelm (Gast)


Lesenswert?

Bei unsigned long ist alles in Ordnung. Habe ich nur zur Sicherheit 
geschrieben wg. unsigned int.

MW

von sechs ueber drei (Gast)


Lesenswert?

>Worauf bezieht sich diese Aussage? Was sie an mich gerichtet?

Nee. War n'Furz in den Wind.

von Kartoffel (Gast)


Lesenswert?

Also meine Regler-Funktion schaut jetzt so aus:
1
unsigned long int Regeln (unsigned long int Istdrehzahl)
2
{
3
4
pi_r.Istwert=Istdrehzahl;
5
pi_r.Regelabweichung = pi_r.Sollwert-pi_r.Istwert;             // e=w-x
6
pi_r.I_Anteil = pi_r.I_Anteil+pi_r.Regelabweichung;            // esum=esum+e
7
8
9
//         Reglergleichung  mit Antiwindup
10
11
if (Begrenzung==1)
12
{
13
pi_r.Stellwert = Kp*pi_r.Regelabweichung;  // ohne Integralanteil
14
}
15
else
16
{
17
pi_r.Stellwert = Kp*pi_r.Regelabweichung + (Ki*pi_r.I_Anteil)/100;  //y=....
18
}
19
20
21
//       Begrenzung des Stellenwertes auf die maximale Größe
22
23
if(pi_r.Stellwert<65135)    // Begrenzung nach unten, also auf FE60
24
{
25
  pi_r.Stellwert = 65135;
26
  Begrenzung = 1;       // Rergler läuft in der Begrenzung
27
 
28
} 
29
30
if(pi_r.Stellwert>65535)    // Begrenzung nach oben, also auf FFFF
31
{
32
  pi_r.Stellwert =65535;
33
  Begrenzung = 1;        // Regler läuft in der Begrenzung
34
}
35
36
37
38
  
39
  return pi_r.Stellwert;                    // Übergabe Stellgröße
40
}

wär nett, wenn ihr noch mal drüber schauen könntet.

von sechs ueber drei (Gast)


Lesenswert?

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
}

von Kartoffel (Gast)


Lesenswert?

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!!

von der mechatroniker (Gast)


Lesenswert?

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.
1
if (!Begrenzung)
2
    pi_r.I_Anteil = pi_r.I_Anteil+pi_r.Regelabweichung;  // esum=esum+e

Die andere if-Abfrage und die Formel ohne I-Anteil muß raus.

von Kartoffel (Gast)


Lesenswert?

@ mechatroniker : ok, und was macht das Ding dann, wenn ich mich in der 
Begrenzung befinde? Wie errechnet sich dann der I-Anteil??

von sechs ueber drei (Gast)


Lesenswert?

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.

von JÜrgen G. (Firma: 4CKnowLedge) (psicom) Benutzerseite


Lesenswert?

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

von Kartoffel (Gast)


Lesenswert?

@ 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....

von der mechatroniker (Gast)


Lesenswert?

> ok, und was macht das Ding dann, wenn ich mich in der
> Begrenzung befinde? Wie errechnet sich dann der I-Anteil??

Der bleibt gleich!

von Kartoffel (Gast)


Lesenswert?

sodala, ich hab ein paar Änderungen vorgenommen und poste den Code jetzt 
noch mal, das mit dem Windup ist auch berücksichtigt.
1
//*************************************************************************************
2
//                    Variablen
3
//*************************************************************************************
4
5
//double Ta=0.01
6
//unsigned long int Stellwert_old = 0;
7
bit Begrenzung;
8
9
10
11
12
//*************************************************************************************
13
//                    Prototypen
14
//*************************************************************************************
15
unsigned long int Regeln (unsigned long int Istdrehzahl); // Funktion zum Aufrufen des Reglers
16
void PI_Init(void); // Reglerinitialisierung
17
18
19
20
//*************************************************************************************
21
//                     Funktionen
22
//*************************************************************************************
23
void PI_Init(void)
24
{         
25
pi_r.Kp = 18;
26
pi_r.Ki = 60;
27
Begrenzung=0;
28
pi_r.I_Anteil=0;
29
pi_r.Regelabweichung = 0;
30
31
}
32
33
34
35
unsigned long int Regeln (unsigned long int Istdrehzahl)
36
{
37
  pi_r.Istwert=Istdrehzahl;  
38
  pi_r.Regelabweichung = pi_r.Sollwert-pi_r.Istwert;             // e=w-x
39
40
  //         Antiwindup
41
42
  if (Begrenzung!=1)
43
  {
44
    pi_r.I_Anteil = pi_r.I_Anteil+pi_r.Regelabweichung;            // esum=esum+e
45
46
  }
47
48
  pi_r.Stellwert = pi_r.Kp*pi_r.Regelabweichung + (pi_r.Ki*pi_r.I_Anteil)/100;  //y=....
49
50
  //       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
  else if(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
  return pi_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...:-(

von Kartoffel (Gast)


Lesenswert?

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?????

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
Noch kein Account? Hier anmelden.