Forum: Mikrocontroller und Digitale Elektronik PID Regler nach Ziegler/Nichols


von Ma B. (drumstick)


Lesenswert?

Hallo Zusamen!

Ich arbeite mit dem stm32f103vdt6 und dem uvision von Keil.

Ich möchte die Drehzahl eines EC Motors reglen, Hallsensoren.

Ich setze ein PID Regler ein:
1
float speed_curr;                                         
2
float ctrl_out;  
3
float i_term      = 0.0;
4
float e;
5
float ealt;
6
float speed_last  = 0.0;
7
const  float KS     = 0.218;//10.00;
8
const  float Tg     = 0.027;
9
const  float Tu     = 0.006;
10
float Tv            = 0.5 * Tu;
11
float Tn            = Tg;
12
float       Ta      = 0.005; //(1000 / ITVms_MOTSPD_CTRL) / 1000;
13
float       KP      = (0.6 / KS)*(Tg / Tu);
1
void tsk_Motor_speed_ctrl(float speed_cmd)  
2
{
3
  const int   ctrl_out_max  = 4095;
4
  const int   ctrl_out_min  = 0;
5
  static int  errcnt        = 0;          
6
  float       KI            = KP / Tn;
7
  float       KD            = KP / Tv;
8
  
9
  speed_curr = get_Motor_speed(); 
10
  if(get_MotRun())                
11
  {
12
    e = speed_cmd - speed_curr;   
13
    i_term += e;                  
14
    if(i_term > Setup.PIDpar.iMax)
15
      i_term = Setup.PIDpar.iMax; 
16
    if(i_term < Setup.PIDpar.iMin)
17
      i_term = Setup.PIDpar.iMin; 
18
  
19
20
    ctrl_out  = (KP * e) + (KI * Ta * i_term) + (KD / Ta * (e - ealt));
21
22
    if(ctrl_out < ctrl_out_min)     
23
    {
24
      set_MotorEnPinAlwaysOff(true);
25
      ctrl_out = ctrl_out_min;      
26
    }
27
    else
28
    {
29
      set_MotorEnPinAlwaysOff(false);
30
    }
31
    if(ctrl_out > ctrl_out_max)     
32
    {  
33
      ctrl_out = ctrl_out_max;      
34
    }
35
36
    if(speed_curr < 1)              
37
    {
38
      errcnt ++;
39
      if(errcnt >= (1000 / ITVms_MOTSPD_CTRL))
40
      {
41
        Motor_STOP();                         
42
        iStopp = true;                        
43
      }
44
    }
45
46
    speed_last = speed_curr;
47
    ealt = e;
48
49
  }
50
  else
51
  {
52
    ctrl_out = 0;         // reset the DAC value                   
53
    i_term = 0.0;         // reset the deviation of the speed value
54
    errcnt = 0;           // reset the error counterregister       
55
  }
56
57
  DAC_MotI = ctrl_out;  // transfers the motor current value to the DAC   
58
                                                      
59
}

Das KS ergibt sich aus 152/700.
152 ist der Maximale Istwert der Sprungantwort.
700 ist der Maximale Stromwert (digits), den der Regler zulassen kann.

Der Antrieb fährt nicht immer an, sieht jemand noch etwas oder hat 
verbesserungsvorschläge?!

Danke und Gruss!

von Ma B. (drumstick)


Lesenswert?

Der Istwert fährt sofort auf 140mm/s und bleibt da mehr oder weniger. 
Der Sollwert ist maximal 75mm/s. und fährt mit einer Rampe an und bremst 
auch verzögert.

von Thorsten O. (Firma: mechapro GmbH) (ostermann) Benutzerseite


Lesenswert?

Lass dir doch mal die einzelnen Anteile (P, I, D) einzeln ausgeben. Dann 
siehst du wahrscheinlich, welcher Teil dir Probleme macht.

Mit freundlichen Grüßen
Thorsten Ostermann

von Ma B. (drumstick)


Lesenswert?

KD = KP * Tv! habs gefunden!

Danke!

von sebastian (Gast)


Lesenswert?

Hi,

gut wenn du deinen code am laufen hast?
Beim ansehen hätte ich auf den D-Anteil getippt.

>ctrl_out  = (KP * e) + (KI  Ta  i_term) + (KD / Ta * (e - ealt));

Wie ist die bindung der Operatoren * und /? Die haben in C doch die 
selbe Prio? Werden die von Links nach rechts ausgeführt oder ist das 
compiler abhänig?

ctrl_out  = (KP * e) + (KI  Ta  i_term) + ( KD * (e – ealt)/Ta));

Sorry wenn ich Mist schreibe? Ich habe noch nich so die Ahnung

gruß sebastian

von Oliver J. (skriptkiddy)


Lesenswert?

sebastian schrieb:
> Wie ist die bindung der Operatoren * und /? Die haben in C doch die
> selbe Prio? Werden die von Links nach rechts ausgeführt oder ist das
> compiler abhänig?
Von links nach rechts und das ist im C-Standard so festgelegt.

Meinst du, dass die Operantenreihenfolge hier wirklich eine Rolle 
spielt, wenn er doch float verwendet?

Gruß Oliver

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.