Hallo zusammen ich habe einen PID Regler mit einem Atmega128 realisiert.
Damit regel ich die Drehzahl eines Lüfter.
Für die Parameter des Reglers habe ich Kp=4.8 Tn=2 und Tv=0.13 gewählt.
Mein Problem ist jetzt. Die Sprungantwort des Regelkreises sieht immer
gleich aus egal ob Tv=0 oder Tv=0.13.
Der D-Anteil ist immer Null. Wenn ich das mit dem AVR Studio simuliere, kommt für D=Kd/Ta=624, das Problem liegt halt daran , dass e-ealt=0 bei mir ist. Hat jemand einen Vorschlag oder Idee warum das so ist.
Im Anhang mein Code.
Danke für eure Unterstützung
Code:Das ist die main: #include <avr/io.h> #include "ADC.h" #include "timer.h" #include "adc.h" volatile float temp1; volatile float temp2; volatile float x; volatile float w; volatile float y; volatile float z; volatile float i; volatile float e; volatile float ealt; volatile float esum; volatile float Kd; volatile float Ki; volatile float Kp=4.8; volatile float Tn=2; volatile float Tv=0; volatile float Ta=0.001; int main (void) { if (Tn == 0) { Ki=0; } else { Ki=Kp/Tn; } if (Tv == 0) { Kd=0; } else { Kd=Tv*Kp; } timer1_init(); sei(); DigitalAnalogWandlerInit(); while (1) { temp1 = ReadAdcChannel(1)-512; // Sollwert einlesen temp2 = ReadAdcChannel(0)-512; // Istwert einlesen cli(); w=temp1; x=temp2; sei(); SetDigitalAnalogWandler(DACA, y+512); } return 0; }
Code:#include <avr/interrupt.h> #include "timer.h" Das ist Timer.c #define Anzahl 16; /* jede 1 ms wird ein Interrupt ausgeführt, wenn CPU_F=16MHz,anzahl=16 und Vorteiler=1024 16MHz/1024=15625Hz => 15625Hz/Durchläufe=Timer_Fre 15625Hz/16=976Hz => Abtastzeit_Ta =1/Timer_Fre Ta=1/967Hz=1ms=0,001s jede 10 ms wird ein Interrupt ausgeführt, wenn CPU_F=16MHz,Durchläufe=156 und Vorteiler=1024 16MHz/1024=15625Hz => 15625Hz/Durchläufe=Timer_Fre 15625Hz/156=100Hz => Abtastzeit_Ta =1/Timer_Fre Ta=1/100Hz=10ms=0,01s jede 0,256 ms wird ein Interrupt ausgeführt, wenn CPU_F=16MHz,Durchläufe=16 und Vorteiler=256 */ void timer1_init() { TCNT0 = 256-Anzahl; // TCNT0 = Register in dem man den Startwert festlegt. TCCR0 = (1 << CS02)|(1 << CS00); // Timer Takt // Bei CSO0=1 und CSO2=1 16MHz/1024=15625Hz // Bei Nur CS02 vorteiler gleich 256 // Bei Nur CS01 vorteiler gleich 8, DURCHLÄUFE=8 => 4µs /* Interrupt aktiveren, falls Overflow, z.B. , falls Timer von 0 bis 255 gezählt hat */ /* Oder hier im Bsp.von 99 bis 255 */ TIMSK = (1<< TOIE0); // Deshalb TOIE0 (Timer/Counter0 Overflow Interrupt Enable) = 1 /* Alle Interrupts erlauben mit der Funktion sei () */ sei (); } ISR (TIMER0_OVF_vect) { // Regeldifferenz bilden e = w - x; // aktuelle Regelabweichung bestimmen //if ((y < 511)&&(y > -512)) // bei Übersteuertem stellglied Integration einfrieren //{ // (Anti-Windup) esum = esum + e; // Summe der Regelabweichung aktualisieren //} y = (Kp*e)+(Ki*Ta*esum)+(Ka/Ta*(e-ealt)); //Reglergleichung ealt = e; //Regelabweichung für nächste Abtastung merken if (y > 511) // Stellgröße auf -511...+512 begrenzen (10 bit DAC) { y = 511; } if (y < -511) { y = -512; } // Neu laden, damit Timer nicht bei 0 beginnt TCNT0 = 256-Anzahl; }
Lesezeichen