mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik regelalgorithmus implementieren


Autor: Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guten abend zusammen

ich versuche, seit einger zeit einen PI oder PID Regleralgorithmus auf 
einen Atmega128 zu implemtieren.

Ich wollte jetzt mal  allgemein Fragen worauf muss man, besonders achten 
muss.

Was muss man bezüglich Abtastzeit, ADC_Frequen, DAC_Frequenz beachten.

Da ich für die Kp, Tn, Tv Werte Kommazahlen habe, benutze ich 
float-datentyp.

Den Algorithmus rufe ich mittels eines Timer_ Interrupt jede 1ms oder 
jede 10 ms auf´.

Hier ist auch eigentlich mein Problem, wenn ich im Algorithmus Ta=1ms 
klappt die PI Regelung wunderbar (PID nicht). Obwohl ich nicht glaube 
das jede 1ms der Timer aufgerufen wird. Außerdem braucht der DAC 4ms für 
jede ausgabe.

Und es ist ja bekannt, dass die Abtastzeit größer als die ADC_F und 
DAC_F sein muss.

Woran kann es liegen das die PI-Regelung trotzdem klappt.


Danke und schönen Abend noch.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Float ? Vergiss das, bringt nichts. Ich arbeite schon seit jahren mit 
Integern und hatte nie Probleme. Eine Longinteger hat einen dynamischen 
bereich von 9 dezimalstellen und auch soviele signifikanten stellen. 
Waehrend ein Float einen dynamischen Bereich von 308 dezimalstellen hat, 
sind es nur 6 signifikante digits, da 24bit mantisse und 8 bit exponent.
Zudem ist die Eingabe (ADC) und die Ausgabe(DAC) ja auch in Integer.
Die Geschwinikeit des Loops hat einen Zusammenhang mit der 
Systemgeschwinigkeit.

Autor: Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry aber was meinst du genau damit, ich will z.B. für Kp=7.8, kann ich 
das mit int auch realisieren. ich habe ja versucht int zu benutzen aber 
dann habe ich kp=7. Und viel schlimmer ist es es wenn Tn oder Tv= z.b 
=0.56 oder ähnlich sind dann sind  die gleich 0.

Gibt es dann eine MÖglichkeit. Danke ich bin nicht der Programmier 
Profi.

Danke

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kp = 7.8 was soll das ? Braucht man so nicht.

Ich habe den Sollwert als Integer, falls das System linear ist, gleich 
dem ADC wert [0..65536]. Der Istwert ist auch gleich [0..65536].
Fehler = Soll-Ist;
P-Teil = P_Faktor * Fehler;
..
..
PI = P-Teil + I-Teil;
..

Etwas kreativ muss man schon sein.

Autor: PI Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi

was meinst du mit braucht man so nicht ich möchte ein Kp-Wert von 7.8 
einstellen können.

Stell dir von ich will Ki ausrechnen.

Ta=10 ms Tn=3400ms und Kp=eben 7.8

Ki=Kp/Tn*Ta bei float ist das Ergebnis =0.023

bei Int wäre Ki=0

Dann würde der I-Anteil also Null sein

y=Ki*sum+ P-Anteil; // also würde sich nur der P-Anteil bemerkbar 
machen.

Oder habe ich dan was total falsch verstanden.

Danke für deine Antworten

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PI Regler schrieb:
> Oder habe ich dan was total falsch verstanden.

Ja.

Um mit ganzen Zahlen zu rechnen, musst du deine Werte skalieren.

Anstatt also mit 7.8 (z.B. V) zu rechnen, überlegst du wie genau es
sein soll und rechnest halt stattdessen mit 78 Zehntel (also z.B.
0.1V) oder 780 Hundertstel (also 0.01V) oder 7800 Tausendstel
(also mV).

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: um solche Werte zu addieren oder zu subtrahieren, braucht
man nicht viel ändern (ggf. Überlauf berücksichtigen).

Bei Multpikationen, Divisionen etc. ergibt sich ein Fehler durch
die Skalierung, das muß man jeweils manuell korrigieren.

Autor: PI Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay danke

kann mir jemand auch was über die ADC_F und DAC_F sagen, warum die 
PI-Regelung trotz oder nur bei 1ms klappt.


Danke

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nö

wie auch? Keiner kennt das System, wahrscheinlich du selber nicht,
keiner kennt dein Program (du?).

Wie soll man da sagen, warum es mal geht und mal nicht?
Sei froh, wenn es geht.

Autor: PI Regler (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hi

machst du witze zur späten Stunde :-)

Es ist ein Lüfter und ich habe auch die Strecke Identifiziert. Die Frage 
ist mehr warum läuft es bei Ta=1ms und nicht bei Ta=10ms.

Der Algorithmus habe ich aus dem Buch Regelungstechnik für Ingenieure 
von Manfred Reuter.

Danke nochmal und noch eine schöne Nacht mit viele Witzen.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und der Luefter hat eine Bandbreite von 100Hz ? Eher unter 10Hz. Da 
muesste man eigentlich mit einer Abtastzeit von 100ms dabei sein.

Autor: PI Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das würde ich auch sagen, aber es klappt nur bei 1ms nicht bei 10 
oder 100ms.

Woran kann das liegen.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum Code :
Das macht man ganz anders.
1) Eine Berechnung in einem Interrupt gibt es eh nicht.
2) Eine Berechnung in einem Interrupt gibt es eh nicht.
3) Eine Berechnung in einem Interrupt gibt es eh nicht.
4) Eine Berechnung in einem Interrupt gibt es eh nicht.
5) Eine Berechnung in einem Interrupt gibt es eh nicht.


interrupt Timer0() {
 timercame=1;
}


main() {
 ..
 while (1) {
 if (timercame==1){
  ReadADC();
  CalcRegler();
  OutputRegler();
  ..
  StartADC();
  timercame=0;
  {
 }
}

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem macht es Sinn, jeweils die Zeit einer Berechnung
festzuhalten und mit der bei der nächsten zu vergleichen.

Die Differenz braucht man für den I- und ggf. den D-Anteil.
Theoretisch kann man auch vertrauen, immer im x-msec-Raster
zu rechnen und diesen Wert dafür nehmen, aber je nach
Programm kann man es nicht garantieren, deshalb lieber
messen.

Zur Zeitmessung könnte man in einem Interrupt, der
zuverlässig in einem bestimmten Zeitraster statt findet,
einen Zähler weitersetzen. Überlauf beachten!

Das könnte in deinem (leider unvollständigen) Quelltext
die Geschichte mit x und x_alt sein.
Ich habe jetzt aber nicht gefunden, wo x weitergezählt
wird.

PS: man darf auch gerne *.c-Dateien anhängen.
Wenn die dann auch nett formatiert sind, fällt das
Lesen leichter.
Noch schöner, wenn sie vollständig sind...

PPS: ich mache nie Witze.

Autor: Jens G. (jensig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Verschneiter Tag (Firma: vorgestern) (hacky)

>Zum Code :
>Das macht man ganz anders.
>1) Eine Berechnung in einem Interrupt gibt es eh nicht.
>2) Eine Berechnung in einem Interrupt gibt es eh nicht.
>3) Eine Berechnung in einem Interrupt gibt es eh nicht.
>4) Eine Berechnung in einem Interrupt gibt es eh nicht.
>5) Eine Berechnung in einem Interrupt gibt es eh nicht.

Warum nicht? Wenn man genau weiß, wie lange die Berechnung dauert, und 
man genau weiß, daß während dieser Zeit nix anderes stören kann (also 
auch kein anderer Interrupt z.B.), kannst Du doch rechnen, wie du lustig 
bist. Man muß es eben nur im "zeitlichen Überblick" behalten.
In seinen Code oben habe ich aber nicht reingeschaut - weiß also nicht, 
ob dies die Ursache für sein Phenomen sein könnte (denke aber eher 
nicht).

Autor: Di Pi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jens G. schrieb:
> Warum nicht?

Ganz einfach: Zum Zwecke der Übersichtlichkeit (das hat was mit Stil zu 
tun, ähnlich wie Groß- und Kleinschreibung).

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mach doch nen analogen PI regler, dann brauchst du weder AVR, noch 
zeitdiskretisierung oder sachen wie abtasttheorem beachten. 2 op's und 
paar R's und C's würd ich immer ner µC Schaltung vorziehen...

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

Bewertung
0 lesenswert
nicht lesenswert
Di Pi schrieb:
> Jens G. schrieb:
>> Warum nicht?
>
> Ganz einfach: Zum Zwecke der Übersichtlichkeit (das hat was mit Stil zu
> tun, ähnlich wie Groß- und Kleinschreibung).

Nicht wirklich.
Wenn er seine Berechnung nicht in float macht sondern als skalierten 
int, hat er in einem ISR Durchlauf ziemlich viel Zeit übrig.

Stilmässig viel schlimmer finde ich
* dass die internen Variablen der Berechnung nicht in der timer.c sind
  sondern als globale Variablen angelegt wurden
* dass da ein 'volatile' Rundumschlag gemacht wurde
* von der 'saumässigen' Codeformatierung rede ich erst gar nicht

Berechnungen dort hin, wo sie hingehören. Zeitkritische Dinge dürfen 
ruhig in einer ISR sein, sofern man dadurch nicht das Zeitbudget der ISR 
sprengt. ISR klein und kurz bedeutet nicht zwangsläufig, dass man da nur 
ein Flag setzen darf, da muss man nicht päpstlicher als der Papst sein.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weshalb keine (Float-) Berechnungen in einem Interrupt ?

Vielleicht moechte man auch nur zu Debugzwecken kommunizieren. Das Uart 
laeuft aber nicht wenn man mit floatrechnungen den Interrupt verstopft.

Autor: Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo zusammen


ich weiß woran es lag die Timer_F war falsch, ich hatte einen falschen 
Vorteiler drin. Deswegen ging es halt nur wenn ich Ta=1ms hatte.

Ich habe mal eine andere Frage

Wie kann man einen PID-T1 Regler in Code umsetzen.

e=w-x
esum = esum + e
y = (Kp * e) + (Ki  Ta  esum) + (Kv * (e – ealt)) - Kd*(y-yalt)
ealt = e


mit Kv=(Kp*Tv)/Ta  und Kd=(Kp*(Tv/10))/Ta

Das müsste schon der richtig ansatz sein, aber nicht 100%. Kann mir 
jemand mehr zu sagen.

Danke

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was zu rechnen waere steht ja schon da. Man kann es vereinfachen, 
speziell die Konstanten.

Autor: Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meine ist das der richtig Code für PID-T1 gerade bei Kd*(y-yalt) bin 
ich mir da nicht so sicher.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kd*(y-yalt) bedeutet eine Gegenkopplung. Ob die was bringt kann man ja 
schauen. Wenn ich was zu regeln habe, so hab ich meinen Regler 
kommunikationsfaehig, und falls ich nicht probieren kann, schreib ich 
erst eine Simulation fuer den PC. Wenn die simulation dann laeuft, muss 
zuerst ermittelt werden, ob die abgenommenen Paramter der Strecke auch 
hinkommen, dh lass ich den Regler parallel zur Simulation laufen und 
schau die Abweichungen an.
Waehrend des Betriebes schau ich mir das Verhalten an und schraub an den 
Parametern rum.
Im obigen Fall, kann man ja mit Kd=0 beginnen und dann waehrend des 
Betriebes den Wert fuer Kd setzen.

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.