ich bin auf der Suche nach Sourcecode von Regelalgorithmen. Gib es dazu frei verf=FCgbaren Quellcode in C? Der Code sollte nur mit Integerwerten rechen.
Kurz mein 'Problemchen' umrissen:
Jede Sekunde bekomme ich einen Messwert geliefert. Die einzelnen Messwerte schwanken jedoch sehr in ihrer Gr=F6=DFe. Um das zu Mitteln bzw. zu 'gl=E4tten', ist daran gedacht, die Werte durch ein PT1-Filter zu schicken.
Danke f=FCr jeden Tip!
Gru=DF Hans
Didn't find your answer? Ask the community — no account required.
M
Markus
Du willst also Messwerte sammeln und einen Durchschnitt bilden? Das macht man CPU-technisch am effizientesten so:
int Wertesammeln, aktuellerwert = 0;
for i = 1 bis 64 do {(..) Wertesammeln = Wertesammeln + aktuellerwert;} //z.B. für 64 Werte.
aktuellerwert >> 6;
Wenn du aber nur jede Sekunde einen WErt bekommst kannste doch genausogut mit floats rechnen.
Ansonsten s. "gleitender Durchschnitt" und dergleichen, bei dem Du Dir aber Gedanken machen solltest, wie es an den Grenzen aussieht, also z.B. bei t=0.
Gruß, Mario
F
Felix Opatz
Und zwar fortlaufend, so habe ich es verstanden.
Hört hört, der Meister spricht. :-)
Super, dann hat er den Mittelwert der letzten 64 Sekunden. Und was ist eine Sekunde später? Und die danach?
Geschickter ist IMHO einen Ringpuffer zu nehmen, z.B. ein Array mit n Elementen. Das füllt man von Anfang her mit den Messwerten, mit einem Index i = j MOD n, wobei j für jeden Messwert inkrementiert wird. Dann muß man zwar für einen Mittelwert jedesmal n Elemente addieren und durch n teilen, aber dafür hat man in jedem Schritt die letzten n-1 Werte "im Gedächtnis". Auf dem Ringpuffer aufbauend kann man natürlich auch andere Berechnungen durchführen (quadratische Abweichung etc. pp).
Selbstredend ergibt die Ausgabe erst Sinn, wenn jedes Element des Arrays mit einem Meßwert gefüllt ist, und nicht mit Nullen oder meist schlimmer noch: uninitialisiertem Speichermüll. Aufpassen sollte man auch, daß der Datentyp für das Akkumulieren groß genug für n * max_messwert ist, sonst gibt's einen Überlauf, was Ausreißer im Ergebnis erzeugen dürfte.
Wobei je nach Plattform float nicht so richtig Spaß macht.
Gruß, Felix
F
Felix Opatz
Argh, ist wohl schon etwas spät heute. Natürlich kann man auch einen Akkumulator mitlaufen lassen, und den jeweils jüngsten Wert aufaddieren sowie den ältesten subtrahieren. Dann muß man nicht jedesmal das ganze Array aufaddieren. Aber der Ringpuffer als Gedächtnis muß natürlich bleiben, sonst hat man einen Gesamtwert, dem man seine Bestandteile nicht mehr ansieht.
H
Henning Paul
Noch keine Regelungstechnik gehört? PT1 ist simpler Tiefpaß 1. Ordnung.
Gruß Henning
M
Markus
"Henning Paul"
Achso. Ein Glied.
R
Rolf_Bombach
Normaler gleitender Durchschnitt ist auch immer etwas stufig. Will man das wegkriegen, kann man die Werte im Fenster gewichten, dem Verfahren bei FFT-PSE nicht unähnlich. Die Gewichte kann man ja in einer Tabelle ablegen, Form ist nicht mal soo wichtig; Gauss, Dreieck, Parabel, Savitzky- Golay, ...
mfg Rolf Bombach
W
Winfried Salomon
also wenn es nur um Glättung geht, ist eine Tiefpaßfilterung doch eine einfache Sache. Wie man z.B. eine PID-Regelung in der Praxis realisiert, weiß ich nicht, kann aber nicht so schwer sein. Bei einem Tiefpaß würde ich nicht mit gleitendem Mittelwert, Ringpuffer wie bei FIR oder sonstigen abgedrehten Sachen arbeiten, sondern einen simplen Tiefpaß 1. Ordnung nehmen. Digital braucht der genau 1 Variable als Speicherplatz für 1 verzögerten Funktionswert, 3 Koeffizientenmultiplizierer, 2 Addierer. In C ist das doch simpelst zu machen.
Einen Tiefpaß 1. Ordnung läßt sich leicht mit der bilinearen Transformation entwerfen. Nehmen wir 1 Beispiel:
Die Beschreibung sollte eindeutig sein. Frei nach Mildenberger (Tietze/Schenk erklärt da IMHO zu umständlich) geht die bilineare Transformation einfach so:
Verschiebungssatz der Laplace-Transformation, um T verschieben: z=exp**(sT) T=1/fa fa=Abtastfrequenz
nach s umstellen: s=(1/T)*ln(z)
Leider läßt sich mit ln(z) nix anfangen, deshalb abbrechende Reihenentwicklung:
s=(2/T)* (z-1)/(z+1)
Das heißt bilineare Transformation und hat sehr günstige Eigenschaften. Jetzt ersetzen wir
V(s)=V(z)
indem wir einfach jedes s durch obigen Ausdruck von z ersetzen. Dann wird aus
V(s)=V0/(1+s/om_e)
mit aus Tietze/Schenk übernommener Struktur 1. Ordnung das:
Ich hoffe, es ist zu erkennen was gemeint ist. 1/z = exp**(-s*T) und bedeutet Verzögerung um 1 Abtastwert der Periode T. Die Addierer sollten bei Overflow gesättigt arbeiten, sonst wird's instabil.
Diese Struktur sollte sich in C mit wenigen Zeilen erschlagen lassen, alle Variablen sollten natürlich signed integer sein, da der AD-Wandler ja kein float ausgibt, sondern sicher 2er-Komplement. Falls nicht, entsprechend in 2er-Komplement umwandeln, Rest ist dann klar.
Mit om_e wird dann der Glättungsgrad eingestellt, man kann auch Tiefpässe höherer Ordnung entsprechend entwerfen, mit entsprechendem Aufwand und besserer Wirkung. Sinnvollerweise sollte f_e deutlich unter fa/2 liegen.
mfg. Winfried
H
Henning Paul
Glückwunsch, Du hast soeben die Z-Transformation erfunden. ;-)
Gruß Henning
W
Winfried Salomon
Hallo Henning,
das war auch nötig, wenn Du Dir die anderen Antworten anschaust ;-). Welche Vorteil gleitender Mittelwert hier bringen soll, ist mir unklar, vielleicht weil man keine Multiplizierer braucht? Falls das Filter in der Rückkopplung liegen sollte, wäre das Ganze sowieso fatal und es müßte optimiert werden. Aber diese wichtige Information fehlt in der urprünglichen Fragestellung.
mfg. Winfried
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.