Forum: Mikrocontroller und Digitale Elektronik DC Motor: Stromregelung mit PWM


von Mathias Q. (paolo_pinkel)


Lesenswert?

Hallo zusammen,

fuer mein Projekt - der Geschwindigkeitsregelung eines DC 
Reihenschlussmotors bin ich gerade dabei eine gescheite regelung zu 
entwerfen.

Geplant ist eine Kaskadenregelung mit Stromregler als Begrenzer im 
inneren Regelkreis.

Dieser soll als PI Regler ausgelegt sein, mit der Stellgroesse des 
Geschwindigkeitsreglers minus Strom als Regelgroesse und dem PWM 
Verhaeltniss als Stellgroesse.
Die Pulsweite PW1 geht von 40000...0 (aus...ein).

Zunaechst moechte ich mal den P Anteil festlegen.
(Nach Ziegler/Nichols ist p = 0.45 * Pkrit, wo es grade zu schwingen 
anfaengt)

Fuer den Fall das der Strom groesser wird als der Sollwert, wird der 
Regelanteil (Abweichung = Soll - Ist) negativ. Da ich aber keine 
negative Stellgroesse erzeugen kann, dachte ich mir ich begrenze diesen 
auf 0, sprich PW1 = 40000.

Jedoch merke ich in der Praxis, dass bei solchen Stroemen der PW Wert 
andauernd von aus auf x "springt" und nicht auf aus bleibt.

Koennte mir das nur dadurch erklaeren, dass die Stellgroesse immer nur 
ganz kurz in die Begrenzung geht, der Strom sollte aber auf Grund der 
Induktivitaet des Motors nicht so schnell folgen. Ich kappiers einfach 
nicht.

Der Code des Reglers ist angehaengt, lauft auf nem C167.

Waere toll wenn, mir jemand helfen koennte.
1
/* ----- A/D Conversion ready interrupt program ----------------------------- */
2
void ad_int (void) interrupt 0x3F
3
{
4
5
  
6
  
7
  ADST = 1;           /* Conversion start */
8
9
  while(ADBSY) {};         /* wait of end of conversion */
10
   
11
  current = ADDAT & 0x03FF;       /*read result of conversion  */
12
  
13
14
15
/* ----- PI current control ---------------------------------------- */
16
17
   current_error = (long) current_desired - (long) current;
18
19
/*** set Deadband ***/  
20
  current_error_temp = current_error;
21
   if (current_error_temp < 0)
22
      current_error_temp *= (-1);
23
   if (current_error_temp < 10)   /* current error < 100mA       */
24
      current_error = 0;    /* set current error zero      */
25
     
26
27
/*** Calculate Proportional Term ***/
28
 current_proportional_term=(current_error*(long)current_proportional_gain);
29
  
30
31
/*** Find Accumulated Error ***/
32
   if((current_controll_output>=0) && (current_controll_output<=40000))
33
     current_acc_error = ((long)current_acc_error) + (long)current_error;
34
35
36
/*** Calculate Integral Term ***/
37
   current_integral_term = (current_acc_error*(long)current_integral_gain) ;
38
39
/*** Check For Integral Term Out Of Range & Apply Saturation ***/
40
   current_integral_term_temp = ((long)current_acc_error * (long)current_integral_gain) ;
41
   
42
   if(current_integral_term_temp >= 40000) {  
43
      current_integral_term = 40000 ;  
44
      }
45
   else {
46
      if(current_integral_term_temp <= 0) {
47
         current_integral_term = 0 ;
48
         }
49
        }
50
51
52
53
54
/*** Sum Up Control Terms ***/
55
   current_controll_output = (long) current_integral_term ;
56
   current_controll_output += current_proportional_term ;
57
   
58
59
/*** Limit Value Of Control Term ***/
60
   if(current_controll_output >= 40000) {
61
      current_controll_output = 40000 ;
62
    }
63
   else {
64
     if(current_controll_output <= 0) {
65
        current_controll_output = 0 ;
66
      }
67
   }
68
   
69
  PW1 = 40000 - (short)current_controll_output;
70
71
  PWMIR  = 0;            
72
73
}

so far...

von Martin Cibulski (Gast)


Lesenswert?

Hallo Mathias,

wenn ich den Code richtig verstehe, begrenzt Du zuerst
die Zwischenergebnisse und am Ende den Ausgang noch einmal.
Dann dauert es beim Zurückschwingen erst eine gewisse Zeit, bis
am Ausgang die 100% verlassen werden.
Wenn also die P und I-Werte Vollausschlag (100%) und der Ausgang die
Summe auf 100% begrenzt, sind im Regler immernoch 200% vorhanden, die
beim Gegenregeln erst einmal abgebaut werden müssen.

Ich verwende einen Algorithmus nur mit Differenzen
zum vorigen Zyklus auskommt, dann tritt das Problem nicht auf.
Außerdem normiere ich erst alle Ein- und Ausgänge, das geht auch mit 
Integer-Zahlen.

Läuft der Motor nur vorwärts ?
Wenn nicht, brauchst Du auch negative Stellgrößen.
Zumindest beim Abbremsen braucht man doch negativen Strom, oder ?

Gruß,
Martin



VORGABEN:

istwert_min
istwert_max
sollwert_min = istwert_min
sollwert_max = istwert_max
stellgroesse_min
stellgroesse_max
V : Verstärkung
TN : Nachstellzeit in Rechenzyklen

NORMIEREN:

sollwert_norm = (sollwert - istwert_min) / (istwert_max - istwert_min)
istwert_norm = (istwert - istwert_min) / (istwert_max - istwert_min)
Stellgroesse_norm  = (stellgroesse - stellgroesse_min) / 
(stellgroesse_max - stellgroesse_min);

DIFFERENZEN ZUM LETZTEN ZYKLUS:

diff_sollwert = sollwert_norm - alt_sollwert_norm
diff_istwert = istwert_norm - alt_istwert_norm

NEUE STELLGROESSE (NORMIERT):

Stellgroesse_norm  = Stellgroesse_norm
                  + V * ((diff_sollwert - diff_istwert) + (sollwert_norm 
- istwert_norm) / TN);

STELLGROESSE DENORMIEREN:

Stellgroesse = stellgroesse_min
             + Stellgroesse_norm * (stellgroesse_max - 
stellgroesse_min);

STELLGROESSE BEGRENZEN:

if Stellgroesse > Stellgroesse_max then
    Stellgroesse = Stellgroesse_max;
end;
if Stellgroesse < Stellgroesse_min then
    Stellgroesse = Stellgroesse_min;
end;

von Mathias Q. (paolo_pinkel)


Lesenswert?

Hi Martin (und andere)

> Wenn also die P und I-Werte Vollausschlag (100%) und der Ausgang die
> Summe auf 100% begrenzt, sind im Regler immernoch 200% vorhanden, die
> beim Gegenregeln erst einmal abgebaut werden müssen.

Theoretisch stimmt das schon, aber bei den Tests, die ich fahre ist der 
I-Anteil sowieso erstmal auf null gesetzt. Es handelt sich um einen 
reinen P-Regler.


> Ich verwende einen Algorithmus nur mit Differenzen
> zum vorigen Zyklus auskommt, dann tritt das Problem nicht auf.
> Außerdem normiere ich erst alle Ein- und Ausgänge, das geht auch mit
> Integer-Zahlen.

Was einem D-Regler entspricht, den ich gar nicht einsetze. Spaeter werde 
ich den I-Anteil zuschalten.

> Läuft der Motor nur vorwärts ?

ja


Nochmal zu meinem eigentlichen Problem:

Wenn der Strom hoeher wird als der Sollwert, springt die Stellgroesse 
mit einigen Mhz zwischen 0 und ca. 70/80%. Eigentlich sollte Sie null 
bleiben bis der Strom unter den Sollwert sinkt.

Wenn ich das Ding simuliere tritt der Effekt nicht auf.

Koennte es sich um einen Aliasing - Effekt handeln? Der Regler wird 
einmal pro Puls, nach jeder A/D Wandlung aufgerufen

von Mathias Q. (paolo_pinkel)


Lesenswert?

Nachtrag:

Ich vermute, der Fehler liegt incht beim Regler, sondern vielleicht Beim 
Sensor oder A/D Wander, oder sonstwo.

Ich habe spasseshalber mal einen simplen Zweipunktregler genommen:
1
if(current > current_desired ) 
2
P7 = 0x0000;                     //Ausgang null
3
4
if(current < current_desired ) 
5
 P7 = 0x0002;                    //Ausgang eins

Gleiches Resultat: wenn der Strom ueber den Sollwert steigt (auch bei 
grosser Differenz) schaltet der Regler schnell zwischen null und eins, 
statt auf null zu bleiben.

*gruebel, gruebel*

von Mathias Q. (paolo_pinkel)


Lesenswert?

Nachtrag 2:

Der Stromwert bricht ab und zu (auch im hoeren Bereich) ein, fragt nicht 
warum, vermute das haengt mit dem Stromfreilauf zusammen. Sollte auf 
Grund der Induktivitaet aber gar incht gehen, na weiss der Kuckuck.

Ich habe das Problem jetzt geloest, indem ich den Stromwert 
approximiere:
1
current = (49*current + current_temp)/50;

Geht ganz gut...

LG

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.