PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit Tv



Hilfe2010
26.01.2010, 18:37
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

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;

}










#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;






}