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;  






}