Forum: Mikrocontroller und Digitale Elektronik Kurze Frage zum PID-Regler


von Christian_H (Gast)


Lesenswert?

Hallo,

ich habe einen ADC und einen DAC am STM32F4. Beide mit 16bit.
ich wollte nun eine Art Regler machen, der einen Spannungsteiler 
belastet und unbelastet auf gleicher Spannung halten soll. Anstatt der 
Belastung wollte ich das ersteinmal mit einem Poti testen. Ich habe 
also:
1
ADC-- 100k Poti -- 10k R -- GND
2
             |
3
             |
4
            DAC

von Christian_H (Gast)


Lesenswert?

Hoppla, wollte nur ansehen ob das so mit dem Code funktioniert, ich 
schreibe schnell eine Antwort, die den Post oben weiterführt

von Christian_H (Gast)


Lesenswert?

1
DAC-- 100k Poti -- 10k R -- GND
2
             |
3
             |
4
            ADC

So soll es natürlich sein.
Nun wird bei einem PID Regler ja immer berechnet, wie stark der Wert vom 
Sollwert abweicht, und wieviel nachgeregelt werden muss.
Ich muss doch nun einfach die berechnete Stellgröße auf den bereits 
ausgegebenen DAC geben, oder?

Also der Regler gibt mir bei 1V am DAC 1,5V zurück. Dann muss ich 2,5V 
auf den DAC geben, oder? Also ich muss auch immer den alten DAC Wert 
speichern, oder? Weil irgendwie liest sich das bei allen Seiten so, als 
ob die Stellgröße auf den DAC gegeben wird, in dem Fall also 1,5V.

von Ulrich H. (lurchi)


Lesenswert?

Beim digitalen PID Regler muss man 2 größen Speichern, einmal für die 
Bildung der Ableitung (typischerweise der letzte ADC-Wert) und einmal 
für das Integral (etwa die Summe der Fehler aus der Vergangenheit).

Es gibt aber verschiedene Umsetzungen. Bei einer wird für das Integral 
der letzte DAC-wert gespeichert, und jeweils berechnet um wieviel man 
den Wert ändern muss.

Der Widerstands wert ist wie gezeigt vermutlich etwas zu hochohmig für 
den ADC - da wäre dann noch ein Kondensator am ADC Eingang hilfreich - 
dann macht auch PID Regler wieder einen gewissen Sinn.

von Christian_H (Gast)


Lesenswert?

Also ein nicht kompilierbarer Codeschnipsel könnte sein:
1
#define ADC_SOLL 6400
2
startADC()
3
while(1){
4
5
if (ADC_ready_flag){
6
  static uint16_t DAC_OUT
7
  static uint16_t esum;
8
  static uint16_t ealt;
9
  uint16_t e;
10
  e=ADC_SOLL - read_ADC() //differenz e
11
  esum = esum + e; //Summe für I-Teil
12
  DAC_OUT+= = Kp * e + Ki * Ta * esum + Kd * (e  ealt)/Ta; //Berechne Stellwert und addiere auf DAC
13
  ealt = e;
14
  DAC_Set(DAC_OUT);
15
  startADC();
16
  ADC_ready_flag=0;
17
  }
18
}

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.