PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Software PID Regler



Martin.
07.09.2010, 21:11
Hallo!

Ich habe leider Probleme mit dem Integralteil meines PID Reglers:

Initialisierung und variablen Definition:


uint16_t ADC0;
uint16_t ADC1;
uint16_t ADC2;
uint16_t ADC3;
uint16_t ADC4;
uint16_t ADC5;

long int Strom;
long int m_Sollwert;

long int m_Kp;
long int m_Ki;
long int m_Kd;

long int m_Abweichung;
long int m_Abweichung_Summe;
long int m_Abweichung_Alt;
long int m_Stellwert;

long int IAnteil = 0;

void Init_Regler(uint16_t Sollwert)
{
m_Sollwert = 90;
m_Kp = 15900; //Kp kritisch 28500 Tkritisch = 6ms Abtastung 0.45ms
m_Ki = 2100;
m_Kd = 14300;

m_Abweichung = 0;
m_Abweichung_Summe = 0;
m_Abweichung_Alt = 0;
m_Stellwert = 0;
}


Der Regelalgorithmus ans sich:



int PID_Berechnung (uint16_t Istwert)
{

m_Abweichung = m_Sollwert - Istwert;

if ((m_Stellwert < 1023)&&(m_Stellwert > 0))
m_Abweichung_Summe += m_Abweichung;

m_Stellwert = m_Kp*m_Abweichung;
m_Stellwert += m_Ki*m_Abweichung_Summe;
m_Stellwert += m_Kd*(m_Abweichung - m_Abweichung_Alt);

m_Abweichung_Alt = m_Abweichung;

m_Stellwert /= 10000;

if (m_Stellwert > 1023)
m_Stellwert = 1023;
if (m_Stellwert < 1)
m_Stellwert = 0;

return m_Stellwert;
}


Symptomatik:

ich wollte den Regler nach Ziegler Nichols Schwingungsmethode einstelle. Integralteil habe ich weggelassen und konnte schön Kp kritisch und Tkritisch bestimmen. Daraus habe ich Ki und Kd ausgerechnet. Leider geht der Regler sofort an den oberen Anschlag. Also habe ich Kd=0 gesetzt und Ki sehr klein. Nun kann ich zuschauen wie der Asymptotische Wert des Proportionalreglers langsam nach oben geschoben wird. Jedoch Steigt der Istwert wieder bis ans maximum an und verharrt oben. Auch nach langer Zeit sinkt er nicht wieder ab.
Deswegen dachte ich wärs das Anti windup.

Bei den Software-Reglern habe ich an dieses Thema gehalten: http://www.mikrocontroller.net/topic/82685#new

Irgendwie habe ich das gefühl, dass der I-Anteil immer weiter nach oben regeln möchte.

Da das ganze eine Regelung für ein Schaltnetzteil werden soll, habe ich nur (long) ints verwendet um ein bisschen Rechenzeit und Speicherplatz zu sparen. Wer Optimierungsmöglichkeiten sieht, darf das gerne auch sagen!

Danke

Martin

PS: Mit kleinen Sollwerten funktionierte es eigentlich schon ganz gut, nur bei größeren hats aufgehört.[/code]

Mohikaner
08.09.2010, 01:10
mhh ich wuerd mal das erste if ausklammern, also das hier:

if ((m_Stellwert < 1023)&&(m_Stellwert > 0))
m_Abweichung_Summe += m_Abweichung;

oder warum machst du das rein? der ianteil soll ja immer addiert/subtrahiert werden, und wenn die abweichung 0 ist, passiert ja da eh nix...

Martin.
08.09.2010, 12:35
Ja aber das ist doch gerade das Anti-Windup. Der Integralteil soll begrenzt werden, damit er nicht zu groß wird. Siehe dazu hier:

http://de.wikipedia.org/wiki/Regler#I-Regler_.28I-Anteil.29

ist der vorletzte blaue punkt.

Apropos: Ich habe es auch mal auskommentiert, aber dadurch wird es nicht besser.

Mohikaner
08.09.2010, 17:35
mhh ok. das mit dem wind up hatte ich noch net sry ;) ich bin zwar kein experte aber eig muesste der code schon stimmen, solang longint negative zahlen zulaesst, was ich net weiss, und du den stellwert als absolut- und nicht realtivwert nimmst (hatte ich ganz zu anfang mal gemacht bei nem projekt :/...). aber wie gesagt eig hab ich auch nicht so viel ahung.

Martin.
08.09.2010, 18:55
Kein Problem. Ich freu mich bei so reger Beteiligung über jede Antwort!

long int ist nur eine Erweiterung von int auf 32bit. es gibt auch unsigned long int mit einem größeren Werte Bereich.

Ich habe gerade meinen Fehler gefunden:

Ich wollte eigentlich alles so effizient wie möglich programmieren und habe deswegen die gemessenen ADC Werte als uint16_t abgespeichert. Bei der weiteren Berechnung habe ich zwar immer long ints, also Vorzeichenbehaftete Zahlen verwendet, aber das uint16_t hat die leider immernoch als unsigned gecastet.
Eine Definition aller uint16_t als long ints hat gereicht.