www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PID Algorithmus arbeitet instabil


Autor: Gast 2009 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich versuche mit dem Atmega128 mit 16MHz einen PID Regler für eine 
Drehzahlregelung zu programmieren, leider bekomme ich nur instabile 
Regelgrößen raus.
Für die Strecke habe ich Ks=1,06 Tg=2,15s und Tu=0,26s.

Mit den Einstellregel für PID nach Chien, Hrones und Reswick
habe ich folgende Reglerparameter berechnet:
Kp=7,4 Tn=2,9s Tv=0,12s Ta habe 0,01 gewählt, da mein Algorithmus durch 
einen Timer alle 10ms aufgerufen wird.

Sollte doch eigentlich funktionieren.

#include <avr/interrupt.h>
#include "DAC.h"
#include "ADC.h"
#include "Regleralgorithmus.h"




volatile double  Kp=7.4;
volatile double  Tn=2.9;
volatile double   Tv=0.13;
volatile double   Ta=0.01;
volatile double  I;
volatile double   D;


volatile int e;
volatile int esum;
volatile int ealt;
volatile int x;
volatile int y;
volatile int w;



int main (void)
{


timer1_init();
sei();
DACInit();



I=Kp/Tn;
D=Kp*Tv;



while (1)
{


w = ReadAdcChannel(1)-512; // MUX-Bits auf 0b0001 -> Channel 1



// Istwert einlesen
x = ReadAdcChannel(0)-512; // MUX-Bits auf 0b0000 -> Channel 0

// Sollwert einlesen


//y0=w/1.06;




SetDAC(DACA, y+512);


}

return 0;

}


************************************************************************ 
********************
Header Datei von Regleralgorithmus
************************************************************************ 
********************





#include <avr/interrupt.h>
#include "DAC.h"
#include "Regleralgorithmus.h"




#define DURCHLAEUFE 156;

// Alle 10ms soll ein Overflow stattfinden

void timer1_init()
{
               TCNT0 = 256-DURCHLAEUFE;  //  TCNT0 = Register in dem man 
den Startwert festlegt.


    /* 10-Bit Vorzaehler,wir wollten durch 1024 teilen, also CSO0=1 und 
CSO2=1 setzen: 16MHz/1024=15625Hz */


    TCCR0 = (1 << CS02)|(1 << CS00);  // Timer Takt auf 16MHz/1024

    /* Interrupt bei Overflow aktivieren


    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)+(I*Ta*esum)+(D*(e-ealt)/Ta);   //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 < -512)
    {
      y = -512;
    }


//  Neu laden, damit Timer nicht bei 0 beginnt


TCNT0 = 256-DURCHLAEUFE;


}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Formatiere deinen Code erst mal ordentlich. In diesem Sauhaufen findet 
doch kein Mensch irgendwelche Fehler.

Ist es Absicht, dass du hier ...
    TCCR0 = (1 << CS02)|(1 << CS00);  // Timer Takt auf 16MHz/1024

    /* Interrupt bei Overflow aktivieren


    TIMSK = (1<< TOIE0);   // Deshalb TOIE0 (Timer/Counter0 Overflow
Interrupt Enable) = 1


              /* Alle Interrupts erlauben mit der Funktion sei () */

               sei ();
}

... die Einstellung für TIMSK auskommentiert hast?

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
btw. Code sollte nicht in Header-Dateien stehen. Da hinein kommen nur 
die Deklarationen. Also Funktionsprototypen, #defines, etc...

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wobei, du hast da ein "#include "Regleralgorithmus.h" stehen. Ich glaube 
du hast dich nur verschrieben und doch die Regleralgorithmus.c-Datei 
gepostet und nicht den Header, oder?

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt das ist die c-datei ich habe mich nur verschrieben

Sorry

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl heinz Buchegger

Ich muss mich noch mal entschuldigen die ist nicht auskommentiert. Ich 
habe wahrscheinlich bei posten irgenwie das */ gelöscht. Aber bei mir im 
AVR Studio ist es drin.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was mir auffällt (wenn ich das richtig gesehen hab), du aktualisierst in 
der main ständig die werte w und x und benutzt die aber gleichzeitig in 
der ISR. Stichwort atomare Zugriffe. Int ist 2 Bytes. Es kann also 
passieren, dass deine ISR einen Wert liest während in der main gerade 
die Variable geschrieben wird und dann bekommt du unter Umständen Müll. 
um die Schreibzugriffe gehören deswegen ein cli() und sei().

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/interrupt.h>
#include "DAC.h"
#include "ADC.h"
#include "Regleralgorithmus.h"

volatile double  Kp=7.4;
volatile double  Tn=2.9;
volatile double   Tv=0.13;
volatile double   Ta=0.01;
volatile double  I;
volatile double   D;

volatile int e;
volatile int esum;
volatile int ealt;
volatile int x;
volatile int y;
volatile int w;

int main (void)
{
  timer1_init();
  sei();
  DACInit();

  I=Kp/Tn;
  D=Kp*Tv;

  while (1)
  {
    w = ReadAdcChannel(1)-512; // MUX-Bits auf 0b0001 -> Channel 1

    // Istwert einlesen
    x = ReadAdcChannel(0)-512; // MUX-Bits auf 0b0000 -> Channel 0

    // Sollwert einlesen
    //y0=w/1.06;

    SetDAC(DACA, y+512);
  }

  return 0;
}
#include <avr/interrupt.h>
#include "DAC.h"
#include "Regleralgorithmus.h"

#define DURCHLAEUFE 156;

// Alle 10ms soll ein Overflow stattfinden
void timer1_init()
{
  TCNT0 = 256-DURCHLAEUFE;          //  TCNT0 = Register in dem man den Startwert festlegt.

  /* 10-Bit Vorzaehler,wir wollten durch 1024 teilen, also CSO0=1 und
CSO2=1 setzen: 16MHz/1024=15625Hz */
  TCCR0 = (1 << CS02)|(1 << CS00);  // Timer Takt auf 16MHz/1024

  /* Interrupt bei Overflow aktivieren */
  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)+(I*Ta*esum)+(D*(e-ealt)/Ta);  //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 < -512)
  {
    y = -512;
  }

  //  Neu laden, damit Timer nicht bei 0 beginnt
  TCNT0 = 256-DURCHLAEUFE;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist die Signatur von ReadAdcChannel(1)?
Liefert die einen int oder einen unsigned int?

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

erstmal danke.

>>Wie ist die Signatur von ReadAdcChannel(1) Liefert die einen int oder einen 
unsigned int?


Einen int Wert


>>um die Schreibzugriffe gehören deswegen ein cli() und sei().

Was meinst du damit ??

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast 2009 schrieb:
>>>um die Schreibzugriffe gehören deswegen ein cli() und sei().
>
> Was meinst du damit ??

Wenn ein int geschrieben wird werden nacheinander 2 Bytes kopiert. Wenn 
nun nach dem ersten Bytes zufällig dein Interrupt zuschlägt, hast du ein 
int in dem das eine Byte zum alten Wert und das andere Byte zum neuen 
Wert gehört. Und das ist natürlich völliger Datenmüll. Also: Interrupt 
während dem schreiben sperren. Und das geht mit cli() und sei().

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich habe meine Interrupt Routine mal mit cli und sei erweitert, 
allerdings ohne Erfolg.

ISR (TIMER0_OVF_vect)

{

cli();

// 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)+(I*Ta*esum)+(D*(e-ealt)/Ta);   //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 < -512)
    {
      y = -512;
    }


//  Neu laden, damit Timer nicht bei 0 beginnt


TCNT0 = 256-DURCHLAEUFE;

sei();
}


Mich wundern nur, das der reine P-Regler relativ gut funktionert. Liegt 
es nicht vielleicht an Ta=???

Hier der P-Regler Code:

#include <avr/interrupt.h>
#include "DAC.h"
#include "ADC.h"
#include "Regleralgorithmus.h"




volatile double  Kp=7.4;



volatile int e;
volatile int x;
volatile int y;
volatile double y0;
volatile int w;



int main (void)
{


timer1_init();
sei();
DACInit();





while (1)
{


w = ReadAdcChannel(1)-512; // MUX-Bits auf 0b0001 -> Channel 1



// Istwert einlesen
x = ReadAdcChannel(0)-512; // MUX-Bits auf 0b0000 -> Channel 0

// Sollwert einlesen


y0=w/1.06;




SetDAC(DACA, y+512);


}

return 0;

}


************************************************************************ 
********************
c-Datei von Regleralgorithmus
************************************************************************ 
********************





#include <avr/interrupt.h>
#include "ADC.h"
#include "Regleralgorithmus.h"




#define DURCHLAEUFE 156;



void timer1_init()
{
               TCNT0 = 256-DURCHLAEUFE;  //  TCNT0 = Register in dem man 
den Startwert festlegt.


    /* 10-Bit Vorzaehler,wir wollten durch 1024 teilen, also CSO0=1 und 
CSO2=1 setzen: 16MHz/1024=15625Hz */


    TCCR0 = (1 << CS02)|(1 << CS00);  // Timer Takt auf 16MHz/1024

    /* Interrupt bei Overflow aktivieren*/


    TIMSK = (1<< TOIE0);   // Deshalb TOIE0 (Timer/Counter0 Overflow 
Interrupt Enable) = 1


              /* Alle Interrupts erlauben mit der Funktion sei () */

               sei ();
}



ISR (TIMER0_OVF_vect)

{

cli();

// Regeldifferenz bilden
e = w - x;                                    // aktuelle 
Regelabweichung bestimmen


y = (Kp*e)+y0;   //Reglergleichung
                                 //Regelabweichung für nächste Abtastung 
merken
  if (y > 511)                                 // Stellgröße auf 
-511...+512 begrenzen (10 bit DAC)
   {
      y = 511;
    }
  if (y < -512)
    {
      y = -512;
    }


//  Neu laden, damit Timer nicht bei 0 beginnt


TCNT0 = 256-DURCHLAEUFE;

sei();
}

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich habe meine Interrupt Routine mal mit cli und sei erweitert,
> allerdings ohne Erfolg.

Das war auch nicht zu erwarten. :-)
Dieser Fehler ist nur ein Beifang.

> Mich wundern nur, das der reine P-Regler relativ gut funktionert. Liegt
> es nicht vielleicht an Ta=???

Bist du sicher das deine Regelparameter auch stimmen? Wie hast
du die bestimmt? Ausserdem wuerde ich die eher nur als erste
Naeherung ansehen.

Drehst du nur einen Motor oder haengt da noch irgendwas dran?
Gibt es z.B ein Getriebe mit Spiel?

Schaff dir eine Moeglichkeit waehrend dein Regler arbeitet Parameter 
auszugeben. Vielleicht RS232? Oder eine andere PWM?
Dann schaust du dir da mal deine einzelnen Regelparameter an. Vielleicht 
hast du irgendwo einen Sprung weil dir ein Register ueberlaeuft.

> volatile double  Kp=7.4;

Hast du Grund zu der Annahme das dein Controller schnell genug ist
das du mit solchen Zahlen arbeiten kannst? Schalte mal am Anfang deiner
IRQ-Routine einen Port auf High und am Ende auf Low und kuck mal ob du 
am Oszi siehst was du erwartet.

Wo kommt deine Drehzahlinformation her? Tastest du dort schnell genug 
hab?

Olaf

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Olaf schrieb:
>> Mich wundern nur, das der reine P-Regler relativ gut funktionert. Liegt
>
>> es nicht vielleicht an Ta=???
>
> Bist du sicher das deine Regelparameter auch stimmen? Wie hast
>
> du die bestimmt? Ausserdem wuerde ich die eher nur als erste
>
> Naeherung ansehen.

Reglerparameter sollten stimmen, ich habe die wie oben schon 
geschrieben, mit den Einstellregel für PID nach Chien, Hrones und 
Reswick gerechnet.

>> Drehst du nur einen Motor oder haengt da noch irgendwas dran?
>
> Gibt es z.B ein Getriebe mit Spiel?

Nein, ich drehe nur den Motor.
>
> Schaff dir eine Moeglichkeit waehrend dein Regler arbeitet Parameter
>
> auszugeben. Vielleicht RS232? Oder eine andere PWM?

Habe ich schon keine unauffälligkeiten.
>

Autor: Sven K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hehe,

>> Habe ich schon keine unauffälligkeiten.

d.h. Du siehst also nur Unfug ;-)


Also

1. Bitte mal alle! Dateien anhängen in *.c, *.h Form.
   Makefile ? .... etc.

2. Du scheinst ISR Abläufe + main-Programmfluss nicht
   verstanden zu haben.
   Bitte dazu mal ISR lesen, wofür genau braucht man cli(), sei()
   Wann braucht man diese und wie verhindere ich
   falsche Werte in Variablen bei ISRs, wie oben beschrieben ?

Gruß Sven

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast 2009 schrieb:

>> du die bestimmt? Ausserdem wuerde ich die eher nur als erste
>>
>> Naeherung ansehen.
>
> Reglerparameter sollten stimmen, ich habe die wie oben schon
> geschrieben, mit den Einstellregel für PID nach Chien, Hrones und
> Reswick gerechnet.

Ganz ehrlich.
Auf die würde ich keinen Deut geben.

Autor: micha54 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast 2009 schrieb:
> ich habe meine Interrupt Routine mal mit cli und sei erweitert,
>
> allerdings ohne Erfolg.


Hallo,

cli in der Interruptroutinen ist immer unwirksam, während der Routine 
sind die automatisch disabled.

Ich denke, es war main gemeint....

Gruß,
Michael

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dito. Das beste Verständnis für einen PID Regler bekommt man, wenn man 
die Parameter einfach mal etwas herumprobiert und dabei so 
grundsätzliche Sachen im Kopf hat, dass bei höherem D Anteil der P 
Anteil ebenfalls angehoben werden kann.
Den I Anteil kann man Anfangs auch ganz ignorieren und wenn der PD 
Regler gut funktioniert, kann man hier mit herumprobieren.
Diesbezüglich verweise ich auf den Roboternetz-Artikel zu dem Thema. Der 
ist nicht vollständig (wäre auch völlig Overkill), dafür aber leicht 
verständlich und ein paar wichtige Sachen stehen drin.

EDIT: Auch interessant:
http://de.wikipedia.org/wiki/Faustformelverfahren_...

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube wenn ich jetzt alle Dateien dran hänge bringt das nur noch 
mehr durch einander. Kann ich dir das nicht lieber als Email schicken. 
Wenn du nichts dagegen hast.

Meine Email: uc_forum@web.de

Danke

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube nicht, dass er ein persönliches Anliegen an den Dateien hat, 
sondern eher, dass er möchte, dass auch andere Forenbenutzer die Dateien 
einsehen können um dir zu helfen.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie so oft: Die Strecke ist nicht linear! Stellgrößenbegrenzung 
beachten, Mit P-Regler anfangen, Sprungantworten aufnehmen!! 
Einstellregeln vergessen, die taugen für viele Fälle NICHT.

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
micha54 schrieb:
> Hallo,
>
> cli in der Interruptroutinen ist immer unwirksam, während der Routine
>
> sind die automatisch disabled.
>
> Ich denke, es war main gemeint....

Was meinst du mit ich denke main ist gemeint.

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ganz ehrlich.
> Auf die würde ich keinen Deut geben.

Hehe, mich hat der unerschuettliche Glaube an ein paar Formeln
auch ueberrascht. :-)

> Wie so oft: Die Strecke ist nicht linear!

Ah! Guter Einwand. Garnicht dran gedacht. Ich wuerde evenutell
empfehlen den Strom zu regeln, oder den Ausgang zu linearisieren.

Olaf

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast 2009 schrieb:
> micha54 schrieb:
>> Hallo,
>>
>> cli in der Interruptroutinen ist immer unwirksam, während der Routine
>>
>> sind die automatisch disabled.
>>
>> Ich denke, es war main gemeint....
>
> Was meinst du mit ich denke main ist gemeint.

Du greifst auch in main auf die beiden Variablen zu.
Dort sind die Zugriffe aber nicht atomar ausgeführt (mit cli() und 
sei()) geschützt, sodass dir kein Interrupt dazwischen knallen kann, 
wenn das LowByte schon geschrieben ist, das High-Byte aber noch nicht)

Du hast hier zb stehen

x = ReadAdcChannel(0)-512; // MUX-Bits auf 0b0000 -> Channel 0

Der Compiler implementiert das irgendwie so

   call ReadAdcChannel   // returnwert in einem Registerpaar
   lade Adresse von x
   schreibe HighByte vom Ergebnis nach Adresse von x
   schreibe LowByte vom Ergebnis nach (Adresse von x)+1

Das ist alles soweit unproblematisch, bis auf den einen Fall. Nämlich 
dann, wenn ein Interrupt genau zwischen Schritt 3 und Schritt 4 kommt. 
IN dem Fall ist das HighByte schon nach x abgespeichert worden. Aber das 
LowByte noch nicht! Das kümmert aber den Interrupt nicht. Der kommt 
trotzdem. Und als Folge davon rechnet deine ISR mit einem Wert für x, 
der nicht stimmt, weil das Ergebnis vom ADC erst zur Hälfte 
abgespeichert wurde.

Also musst du das abspeichern atomar machen, sodass da kein Interrupt 
reinknallen kann

    tmp = ReadAdcChannel(0)-512;
    cli();
    x = tmp;
    sei();

jetzt ist das eigentliche Abspeichern 'atomar'. Kein Interrupt kann es 
unterbrechen.

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Viele Danke für eure Beiträge !!!

ich habs mit ein bisschen rumprobieren hinbekommen den Motor zu regeln, 
allerdings nur durch rumprobieren und nicht wirklich logisch.

Ich rufen den Algorithmus jede 1ms durch einen Timer Interrupt auf.
Mein ADC Wandlung benötigt 0,1ms

Jetzt meine alles entscheidende Frage :-), Ta muss doch gleich 1ms 
(0,001) sein wie der Overflow vom Timer?? Oder irre ich da.
Also ist die Overflow Zeit meine Abtastzeit oder ist doch die ADC Zeit 
meine Abtastzeit ??? Sorry aber ich bleib bei dieser Frage echt hängen.


Mich wundert nur das es mit 1ms klappt, denn in der Literatur findet man 
bei Wahl der Abtastzeit, eine Tabelle die sagt.
0,2*Tu < Ta < 0,5 Tg und mit einem Tu=0,26s und Tg=2,15s, ist mein 
Ta=1ms kleiner als 0,2*Tu ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast 2009 schrieb:

> Also ist die Overflow Zeit meine Abtastzeit oder ist doch die ADC Zeit
> meine Abtastzeit ??? Sorry aber ich bleib bei dieser Frage echt hängen.

Die Abtastzeit ist in diesem Zusammenhang das Zeitintervall welches von 
einem Feststellen des Istwertes bis zum nächsten Feststellen des 
Istwertes vergeht.

Wie lang dein ADC zur Wandlung braucht interessiert doch keine 
allgemeine Formel!
Interessant ist die Zykluszeit! Wie lange dauert es, bis der Regler mit 
einem Zyklus durch ist und der nächste beginnt
   * Istwert feststellen
   * Reglergleichung auswerten
   * Stellglied einstellen
   * und wieder alles von vorne

Bei dir ist die Zykluszeit daher offensichtlich die Zeit zwischen 2 
Interrupts.

> ich habs mit ein bisschen rumprobieren hinbekommen den Motor zu
> regeln, allerdings nur durch rumprobieren und nicht wirklich logisch.

Das wirst du auch logisch nicht hinkriegen.
Dazu gibt es viel zu viele Unbekannte im Regelkreis.

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich habs mit ein bisschen rumprobieren hinbekommen den Motor zu regeln,
> allerdings nur durch rumprobieren und nicht wirklich logisch.

Naja, ich glaube das ich sicher noch Diskussionsfaehig. :)


> Ta muss doch gleich 1ms
> (0,001) sein wie der Overflow vom Timer?? Oder irre ich da.

Dein Abtastzeit hat nichts mit der Wandlungszeit deines AD-Wandlers 
zutun. Dein AD-Wandler muss nur schneller sein wie deine Abtastzeit.

Die Abtastzeit wird letztlich bestimmt durch die Dynamik deines Systems. 
Wenn du also z.B einen kleinen Motor mit sehr wenig Masse hast dann kann 
er sehr schnell seine Drehzahl aendern. Hast du dagegen einen dicken 
Klotz mit grosser Schwungmasse so reagiert der langsamer. Es ist dir 
dann moeglich auch langsamer abzutasten. Allerdings koenntest du auch 
einfach immer sehr schnell abtasten. Das kostet dich dann halt unoetige 
Rechenzeit.
Ausserdem haengt das natuerlich davon ab was du mit deiner Regelung 
beabsichtigst. Also wie soll dein Regler auf einen Stoergroessensprung 
reagieren, wie schnell soll er sich anpassen wenn du die Solldrehzahl 
aenderst.

Allerdings aendern sich mit einer Aenderung an der Abtastzeit auch deine 
ganzen Regelparameter. Darum legt man die zuerst fest und aendert sie 
dann nie mehr.

Olaf

Autor: Gast 2009 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi

danke für deine schnelle Antwort, hast du denn auch eine Erklärung warum 
es mit  1ms klappt, obwohl man in der Literatur halt diese Tabelle 
findet in der bei Wahl der Abtastzeit steht.
0,2*Tu < Ta < 0,5 Tg und mit einem Tu=0,26s und Tg=2,15s, ist mein
Ta=1ms kleiner als 0,2*Tu ?

kann es sein das meine Abtastzeit so klein ist dass, man sie 
vernachlässigen kann???


Quelle:http://www.rn-wissen.de/index.php/Regelungstechnik

"Ist die Abtastzeit sehr viel kleiner als die dominierende Zeitkonstante 
der Strecke, dann spricht man von quasi-kontinuierlichem Verhalten, da 
sich der digitale Regler ähnlich wie ein analoger Regler verhält. Der 
digitale Regler kann dann wie ein analoger dimensioniert werden"

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast 2009 schrieb:

> "Ist die Abtastzeit sehr viel kleiner als die
> dominierende Zeitkonstante
  **************************

Das ist der alles bestimmende Paramater.

Wenn deine dominierende Zeitkonstante 1 Stunde ist (weil zb am Motor 
eine Schungmasse mit ein paar 100 Tonnen Masse hängt und der Motor seine 
Drehzahl daher in 1 Stunde maximal um 2 U/min verändern kann, dann 
reicht es auch wenn du alle halbe Stunde die Drehzahl feststellst und 
nachregelst um die Drehzahl auf 5 U/min konstant zu halten.

Daher kann das hier
0,2*Tu < Ta < 0,5 Tg und mit einem Tu=0,26s und Tg=2,15s
nur eine Faustformel sein.

Es gibt keine universell einsetzbaren Parameter. Jede Reglerstrecke ist 
anders. Ein anderer Motor ist durchzugsstärker und beschleunigt besser. 
Im nächsten Reglerkreis ist die zu drehende Masse größer und der Motor 
beschleunigt langsamer. Ein Motor hat sein Drehmomentmaximum bei 
niedrigen Drehzahlen, ein anderer hat es bei höheren Drehzahlen, ....

All das erfordert eine andere Abstimmung der Regelparamter. Kennst du 
diese (und nich viel mehr) Werte deines Regelkreises?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.