Forum: Mikrocontroller und Digitale Elektronik PID Regler timing


von Lyroy (Gast)


Lesenswert?

Hallo allerseits,
wie ist das mit dem PID Regler gemeint wenn man zwei Zeiten hat.

Zeit A / Frequenz mit der ich die Drehzahl lese und meine globale 
Variable update

Zeit B / Frequenz mit der ich den PID Regler antriggere und dies meine 
"iterations_time" darstellt
1
current_error = ref_speed - rpm;
2
          integration_sum = integration_sum + (current_error * iteration_time);
3
          duty = ( KP * current_error + 
4
                 KI * integration_sum + 
5
                 KD *((current_error -previous_error)/iteration_time));

Welche der beiden Frequenzen muss höher sein? Habe gerade hier einen 
blackout.
Ich versuche hier die Drehzahl eines Bürstenmotors zu regeln.

Zweite Frage (STM32 spezifisch):
Wenn ich beides in einer Callbackroutine anhandele, also die Timer für 
ZeitA und Zeit B, könnte ich mir da Probleme wegen Überholern/Blockeden 
einhandeln?
Nehmen wir an Timer1 alls 1ms und Timer2 alle 10.
Würde die Callback routine aufgerufen werden für Timer1 wenn Timer2 code 
noch läuft?

Vielen Dank für die Hilfe..brauche gerade ein paar kleine denkanstöße
1
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim)
2
{    
3
  if(tim->Instance == TIM4) 
4
  {
5
    
6
//    enc_cnt = htim1.Instance->CNT - enc_cnt_old;
7
//    enc_cnt_old = htim1.Instance->CNT;
8
//    
9
//    rpm=0+((enc_cnt*20*60)/400);
10
      
11
//    rpm_tmp=rpm_tmp+((enc_cnt*100*60)/400);
12
//    counter_avg++;
13
//    
14
//    if(counter_avg==2)
15
//    {
16
//      rpm=rpm_tmp/2;
17
//      counter_avg=1;
18
//      rpm_tmp=0;
19
//    }
20
    res=1;
21
    
22
  }
23
  else if(tim->Instance == TIM5) 
24
  {
25
26
        
27
          current_error = ref_speed - rpm;
28
          integration_sum = integration_sum + (current_error * iteration_time);
29
          duty = ( KP * current_error + 
30
                 KI * integration_sum + 
31
                 KD *((current_error -previous_error)/iteration_time));
32
          
33
34
          if(duty<0)
35
          duty =duty*-1;  
36
          
37
          
38
          if((duty*12)>10000)
39
            duty=10000;
40
          else  
41
            duty=duty*12;
42
          htim3.Instance->CCR1 = duty;
43
44
          previous_error = current_error;
45
          res=0;
46
          
47
  }
48
  
49
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Lyroy schrieb:
> Welche der beiden Frequenzen muss höher sein?

Da der PID Regler nur einmal alle 10ms gezündet wird, ist es auch nur 
alle 10ms nötig, ihm eine Ist-Drehzahl zu liefern. Du kannst zwar öfter 
Drehzahl messen, ist aber sinnlos.
Um Konflikte zu vermeiden, kannst du beide Tasks in einem Schwupps 
erledigen.

von Lyroy (Gast)


Lesenswert?

Matthias S. schrieb:
> Da der PID Regler nur einmal alle 10ms gezündet wird, ist es auch nur
> alle 10ms nötig, ihm eine Ist-Drehzahl zu liefern. Du kannst zwar öfter
> Drehzahl messen, ist aber sinnlos.
> Um Konflikte zu vermeiden, kannst du beide Tasks in einem Schwupps
> erledigen.

Herzlichen Dank hierfür!

Habe es jetzt so kombiniert. Der PID wird alle 10ms gestartet. Demnach 
habe ich Iterationstime auf 0.01 gestellt. Nur so läuft der Duty auf 
Anschlag. Stelle ich aber die iterationtime auf 1, dann läuft der PID 
recht cool.
Woran liegt das? ich dahcte die Zeitkonstante wäre wichtig im algo
1
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim)
2
{    
3
  if(tim->Instance == TIM4) 
4
  {
5
    
6
//    enc_cnt = htim1.Instance->CNT - enc_cnt_old;
7
//    enc_cnt_old = htim1.Instance->CNT;
8
//    
9
//    rpm=0+((enc_cnt*20*60)/400);
10
      
11
//    rpm_tmp=rpm_tmp+((enc_cnt*100*60)/400);
12
//    counter_avg++;
13
//    
14
//    if(counter_avg==2)
15
//    {
16
//      rpm=rpm_tmp/2;
17
//      counter_avg=1;
18
//      rpm_tmp=0;
19
//    }
20
    res=1;
21
    
22
  }
23
  else if(tim->Instance == TIM5) 
24
  {
25
    
26
          //enc_cnt = htim1.Instance->CNT - enc_cnt_old;
27
          enc_cnt = htim1.Instance->CNT;
28
          //enc_cnt_old = htim1.Instance->CNT;
29
          rpm=0+((enc_cnt*100*60)/400);
30
          htim1.Instance->CNT=0;
31
32
        
33
          current_error = ref_speed - rpm;
34
          integration_sum = integration_sum + (current_error * iteration_time);
35
          duty = ( KP * current_error + 
36
                 KI * integration_sum + 
37
                 KD *((current_error -previous_error)/iteration_time));
38
          
39
40
          if(duty<0)
41
          duty =duty*-1;  
42
          
43
          
44
          if((duty*12)>10000)
45
            duty=10000;
46
          else  
47
            duty=duty*12;
48
          htim3.Instance->CCR1 = duty;
49
50
          previous_error = current_error;
51
          res=0;
52
          
53
  }
54
  
55
}

Beitrag #6425078 wurde von einem Moderator gelöscht.
Beitrag #6425082 wurde von einem Moderator gelöscht.
von Lyroy (Gast)


Lesenswert?

IchRegelDasSchon schrieb im Beitrag #6425078:
> Da fehlt der Anti-Wind Up Code für die Stellgrößenbeschränkung.
> Und sonst ist die Frage, wie du den PID-Regler überhaupt ausgelegt hast?
> Hast du in Simulink simuliert? Welche Zeitkonstante hat deine
> Regelstrecke?

Hab einen  DC Motor mit Encoder dran. der DC Motor wird mit PWM 
angesteuert. Den Encoder werte ich aus und rechne es in rpm um. 
Eingestellt habe ich durch ausprobieren im debugger mode.

Meinst Du mit Zeitkonstante wie oft der PIG angefeuert wird? Das sind 
alle 10ms
Was meinst Du mit Anti-Wind Up Code?
1
float ref_speed = 80;float duty =0;
2
float iteration_time =1;
3
4
float previous_error = 0;float current_error = 0;
5
float KP = 0.0001;float KI = 0.1002;float KD = 0.4;
6
float input = 0;float integration_sum = 0;

von Lyroy (Gast)


Lesenswert?

IchRegelDasSchon schrieb im Beitrag #6425082:
> Lyroy schrieb:
>>           if(duty<0)
>>           duty =duty*-1;
>>
>>
>>           if((duty*12)>10000)
>>             duty=10000;
>>           else
>>             duty=duty*12;
>
> Das sieht auch sehr komisch aus. Das PWM Signal sollte gerade eine
> effektive Spannung ergeben, die der Regler rausgibt.
> Und was soll das sein? if(duty<0) duty =duty*-1;
> Bugfixing der übelsten Sorte?

ok, verstehe..Dem PID interessiert die Physik die dahinter ist nicht, 
stimmts?

So läuft es auch ziemlicg gut... Das mit der iteration_time=1 habe ich 
nicht verstanden. Wieso muss es 1 sein und nicht 0.01?
1
// refernce and pid related constants
2
float ref_speed = 80;float duty =0;
3
float iteration_time =1;
4
5
float previous_error = 0;float current_error = 0;
6
//float KP = 0.0001;float KI = 0.1002;float KD = 0.4;
7
float KP = 20;float KI = 2;float KD = 3;
8
float input = 0;float integration_sum = 0;

....
1
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim)
2
{    
3
  if(tim->Instance == TIM4) 
4
  {
5
    res=1;
6
    
7
  }
8
  else if(tim->Instance == TIM5) 
9
  {
10
    
11
          //enc_cnt = htim1.Instance->CNT - enc_cnt_old;
12
          enc_cnt = htim1.Instance->CNT;
13
          //enc_cnt_old = htim1.Instance->CNT;
14
          rpm=0+((enc_cnt*100*60)/400);
15
          htim1.Instance->CNT=0;
16
17
        
18
          current_error = ref_speed - rpm;
19
          integration_sum = integration_sum + (current_error * iteration_time);
20
          duty = ( KP * current_error + 
21
                 KI * integration_sum + 
22
                 KD *((current_error -previous_error)/iteration_time));
23
          
24
25
//          if(duty<0)
26
//          duty =duty*-1;  
27
          
28
          
29
          if((duty)>10000)
30
            duty=10000;
31
          else  
32
            duty=duty;
33
          htim3.Instance->CCR1 = duty;
34
35
          previous_error = current_error;
36
          res=0;
37
          
38
  }
39
  
40
}

von M. K. (sylaina)


Lesenswert?

Lyroy schrieb:
> Das mit der iteration_time=1 habe ich
> nicht verstanden. Wieso muss es 1 sein und nicht 0.01?

Also ich habs nur überflogen aber die Itteration-Time stellt wohl die 
Abtastzeit dar. Wenn du an TA schraubst hat das signifikanten Einfluss 
auf das Regler-Verhalten, das ist jetzt nicht grad ungewöhnlich. So 
gefühlt würde ich sagen wenn sich die Abtastzeit um den Faktor 100 
beschleunigt muss KI um den Faktor 100 runter und KD um den Faktor 100 
rauf. Am Besten aber simuliert man das mal durch, z.B. mit Matlab 
Simulink oder, wenn man Matlab nicht hat, mit SciLab (sehr guter 
Matlab/Simulink-Clon)

von Lyroy (Gast)


Lesenswert?

M. K. schrieb:
> Lyroy schrieb:
>> Das mit der iteration_time=1 habe ich
>> nicht verstanden. Wieso muss es 1 sein und nicht 0.01?
>
> Also ich habs nur überflogen aber die Itteration-Time stellt wohl die
> Abtastzeit dar. Wenn du an TA schraubst hat das signifikanten Einfluss
> auf das Regler-Verhalten, das ist jetzt nicht grad ungewöhnlich. So
> gefühlt würde ich sagen wenn sich die Abtastzeit um den Faktor 100
> beschleunigt muss KI um den Faktor 100 runter und KD um den Faktor 100
> rauf. Am Besten aber simuliert man das mal durch, z.B. mit Matlab
> Simulink oder, wenn man Matlab nicht hat, mit SciLab (sehr guter
> Matlab/Simulink-Clon)

Das verstehe ich jetzt nicht. Ta muss doch der Zeit zwischen zwei 
Aufrufen der PID Funktion entsprechen, oder?
Oder meinst Du, das ich durch das modifizieren des TA, bei 
gleichbleibenden PID Parametern zufällig zum richtigen Ergebnis gekommen 
bin? Wenn ja,dann müsste mich doch wieder auf 0.01 zurück gehen und an 
der PID Werten hin und her drehen bis es passt.

von Kevin M. (arduinolover)


Lesenswert?

Lyroy schrieb:
> Das verstehe ich jetzt nicht. Ta muss doch der Zeit zwischen zwei
> Aufrufen der PID Funktion entsprechen, oder?

Korrekt.

Lyroy schrieb:
> Oder meinst Du, das ich durch das modifizieren des TA, bei
> gleichbleibenden PID Parametern zufällig zum richtigen Ergebnis gekommen
> bin?

Ebenfalls korrekt -> typischer Fall von mehr Glück als Verstand ;)

Dein I und dein D Anteil hängen nunmal stark von von der Zeit ab. Schau 
dir doch einfach an was die beiden Mathematisch machen. Du kannst nicht 
einfach Verstärkungen wählen und die für alle möglichen Reglerfrequenzen 
nutzen.

Lyroy schrieb:
> Werten hin und her drehen bis es passt.
Es gibt genug einstellverfahren die du nutzen kannst um das etwas 
fundierter als nur mit raten zu machen. Bei Stromreglern nimmt man 
beispielsweise gerne das Betragsoptimum ansonsten gibt es noch das 
Verfahren mit der Wendetangente, uvm.

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

Beim Poster kommt grad vieles zusammen.
- wenig theoretische Ahnung von Reglern
- wenig praktische Ahnung von Reglern
- wenig Ahnung von Mathe

von Lyroy (Gast)


Lesenswert?

Pandur S. schrieb:
> Beim Poster kommt grad vieles zusammen.
> - wenig theoretische Ahnung von Reglern
> - wenig praktische Ahnung von Reglern
> - wenig Ahnung von Mathe

ohneee  ein Klugscheißer der den Sinn einer Community nicht verstanden 
hat.

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.