Forum: Mikrocontroller und Digitale Elektronik gleitender Mittelwert


von MW (Gast)


Lesenswert?

Hallo allerseits,


ich hatte mal einen Prof erlebt, der hatte kein gutes Haar an dem 
Einsatz eines gleitenden Mittelwertes gelassen und meinte, man 
verfälscht, verschleift und zerstört damit ein Signal.

Das doofe ist aber doch, dass ein Signal mit gleitendem Mittelwert, 
selbst wenn es nur ein sehr sehr kurzer ist meistens wesentlich 
angenehmer anzusehen und letztlich auch auszuwerten ist.
Für mich ist das daher irgendwie immer ein Mittel der Wahl.

Wie steht ihr zu diesem Thema?
Schonmal Gedanken drüber gemacht?

mfg

von Floh (Gast)


Lesenswert?

MW schrieb:
> Wie steht ihr zu diesem Thema?
> Schonmal Gedanken drüber gemacht?

Gleitender Mittelwert ist eine einfache Art, einen digitalen 
Tiefpassfilter zu erzeugen.
Kann manchmal nützlich, manchmal nötig und manchmal falsch sein, das 
kommt ganz auf das Signal drauf an.

von Anja (Gast)


Lesenswert?

MW schrieb:
> Wie steht ihr zu diesem Thema?

Der Prof wollte euch nur provozieren.

Versuche mal ein Signal auszuwerten das mit 50Hz Brumm verseucht ist. 
Ein gleitender Mittelwert über 20 ms ist da die einzige Rettung.

Gruß Anja

von MaWin (Gast)


Lesenswert?

Alle Börsianer machen das mit ihren Kursen, das muss gut sein.

http://www.aistockcharts.com/sma_stock_charting_indicator.htm

von MW (Gast)


Lesenswert?

Als digitalen Tiefpass habe ich das noch nie betrachtet, aber 
tatsächlich ist es das wohl.

Wie berechnet man denn einen digitalen Tiefpass?
Was sind die Kennzahlen?

von Verwirrter Anfänger (Gast)


Lesenswert?

Den gleitenden Mittelwert zu verteufeln ist für mich das Gleiche wie zu 
behaupten Addition oder Fouriertransform wären Unsinn.

Der gleitende Mittelwert ist genau so ein Werkzeug wie jeder andere 
auch. Wenn ich mir die Temperatur meiner Heimatstadt über den Zeitraum 
eines Jahres angucke, hoffe ich, dass das ganze irgendwie geglättet ist. 
Ich will nicht für jede Stunde einen Pixel haben, und ich will auch 
nicht das für jeden Tag ein x-beliebiger Wert genommen wird.

Manchmal kann es in der Bildverarbeitung nützlich sein, die Bilder 
leicht unscharf zu machen, statt da jetzt ne Fouriertransformation 
drüberlaufen zu lassen, nehm ich lieber einen schnellen Mittelwert, 
etc...

Wenn ich natürlich am Auftreffen einzelner Photonen bei einen 
Physikexperiment interessiert bin, und ca. 1 Photon pro Stunde erwarte, 
würde ich vielleicht kein Mittelwert auf das Ergebnis anwenden.

von Klaus (Gast)


Lesenswert?

MW schrieb:
> Wie steht ihr zu diesem Thema?
> Schonmal Gedanken drüber gemacht?

Wie schon geschrieben, ist das ein Tiefpass. Wenn dein Messignal in den 
Frequenzbereich fällt, in dem der Tiefpass Wirkung zeigt, wird er es 
verfälschen.

Anja schrieb:
> Ein gleitender Mittelwert über 20 ms ist da die einzige Rettung.

Dann muß das Nutzsignal weit unterhalb von 50Hz sein. Früher hat man da 
Notchfilter für 50 resp. 60 Hz eingebaut. Das geht auch in SW, ist aber 
aufwändiger als ein gleitender Mittelwert.

MfG Klaus

von Klaus (Gast)


Lesenswert?

Verwirrter Anfänger schrieb:
> irgendwie geglättet ist.
> Ich will nicht für jede Stunde einen Pixel haben, und ich will auch
> nicht das für jeden Tag ein x-beliebiger Wert genommen wird.

"irgendwie" ist aber "x-beliebig". Ich erwarte schon eine zur Messgröße 
und der Messmethode passende wissentschaftlich schlüssige Begründung für 
die Glättung. Ansonsten ist es nicht besser als der Mittelwert der 
Lottozahlen.

MfG Klaus

von martin (Gast)


Lesenswert?

Wenn wir schon dabei sind.
Wie programmiert man einen gleitenden Mittelwert am günstigsten?
Bitte mit Codebeispiel.

von Der Horst (Gast)


Lesenswert?

Klaus schrieb:
> Das geht auch in SW, ist aber
> aufwändiger als ein gleitender Mittelwert.

Nö, du brauchst nur jeweils 2 Werte zu addieren, die 20ms auseinander 
sind.

von Ulrich (Gast)


Lesenswert?

Die Summe aus 2 Werten mit 20 ms Abstand gibt einen Notch bei 25 Hz, 
nicht 50 Hz.

Programmieren kann man den Gleitenden Mittelwert z.B. mit einem 
Ringpuffer für die Daten. Die Berechnung geht dann entwerder jedesmal 
neu, oder auch durch Addieren des neuen Wertes und subtrahieren des 
Wertes der rausfällt. Die 2. Methode setzt aber vorraus, dass es nicht 
zu Rundungsfehlern kommt - es geht also mit ganzen Zahlen, aber nicht so 
ohne weiteres mit Fließkommawerten.

von Klaus (Gast)


Lesenswert?

Der Horst schrieb:
> Nö, du brauchst nur jeweils 2 Werte zu addieren, die 20ms auseinander
> sind.

Richtig.

Ulrich schrieb:
> Programmieren kann man den Gleitenden Mittelwert z.B. mit einem
> Ringpuffer für die Daten.

Für einen gleitenden Mittelwert braucht man eigentlich nur den 
vorherigen Messwert, oder genauer den aus dem vorigen Messwert 
ermittelten aktuellen Mittelwert.

so eine art pseudocode:
1
new = (old + messwert)/ 2
2
use_for_your_application(new)   // damit das ganze überhaupt einen Sinn hat
3
old = new
4
wait_for_next_measurement

Wenn man das mal ins analoge transformiert: ein Tiefpass hat ein 
Element, daß wie ein Speicher wirkt, den Kondensator. Die Nachbildung in 
Software braucht also auch nur eine Variable. Ein Ringpuffer ist also 
aufwendiger als ein gleitender Mittelwert.

MfG Klaus

von Kevin K. (nemon) Benutzerseite


Lesenswert?

Naja, ich hab das mal für einen RMS-Wandler implementiert, was ungefähr 
so aussah (Speicher war 256 Speicherzellen lang)

i=i+1; (character)
Messwertesumme = Messwertesumme - Messwertspeicher(i);
Messwertespeicher(i) = neuer_Messwert;
Messwertesumme = Messwertesumme + Messwertspeicher(i);
Mittelwert = Messwertesumme >> 8;

Für den RMS musste noch eine Wurzel berechnet werden. Das hat mit großem 
Abstand am längsten gedauert. Selbst der ADC und der DAC waren 
schneller.

von Klaus (Gast)


Lesenswert?

Für einen gleitenden Mittelwert braucht man keinen Buffer, die 
allgemeine Formel ist

new = (old *(n-1) + messwert) / n

Die Eckfrequenz bestimmt sich aus der Samplingrate und n. Da die 
Samplingrate meist gegeben ist, kann man mit n (das Equivalent zum 
analogen Wert von C im Tiefpass) spielen. Und da teilen bei einem µC 
teuer ist, sollte n eine Potenz von 2 sein.

MfG Klaus

von Purzel H. (hacky)


Lesenswert?


von Bassti (Gast)


Angehängte Dateien:

Lesenswert?

Funktion, siehe PDF...

von Anja (Gast)


Lesenswert?

Klaus schrieb:
> new = (old *(n-1) + messwert) / n

Das ist aber kein gleitender Mittelwert sondern ein Spezialfall einer 
PT1-Funktion (Tiefpaß).

Gruß Anja

von Klaus (Gast)


Lesenswert?

Anja schrieb:
> Das ist aber kein gleitender Mittelwert sondern ein Spezialfall einer
> PT1-Funktion (Tiefpaß).

Und was ist im Ergebniss der Unterschied?

MfG Klaus

von Bassti (Gast)


Lesenswert?

Erreicht nie den Endwert... was theo. real auch so ist... aber digital 
mit höherem Abstand, wenn man nicht vorher was auf multipliziert und 
dann rundet...

von Daniel (Gast)


Lesenswert?

Bassti schrieb:
> Funktion, siehe PDF...

Wow, ich wusste nicht, dass man einen zweiseitigen Artikel über sowas 
offensichtliches schreiben kann.

von Karl H. (kbuchegg)


Lesenswert?

MW schrieb:

> ich hatte mal einen Prof erlebt, der hatte kein gutes Haar an dem
> Einsatz eines gleitenden Mittelwertes gelassen und meinte, man
> verfälscht, verschleift und zerstört damit ein Signal.

Rein interessehalber: Was hat er statt dessen vorgeschlagen?


Warum ich frage:
Viele hier haben schon erlebt, dass die Profs an den Unis zwar super in 
der Theorie sind, von der Praxis mit verrauschten Signalen, die dann 
eben nicht so wunderbar aussehen, wie die Beispiele mit denen sie in den 
Vorlesungen kommen, haben sie aber keine Ahnung.

von Kevin K. (nemon) Benutzerseite


Lesenswert?

Klaus schrieb:
> Für einen gleitenden Mittelwert braucht man keinen Buffer, die
> allgemeine Formel ist
>
> new = (old *(n-1) + messwert) / n
>
> Die Eckfrequenz bestimmt sich aus der Samplingrate und n. Da die
> Samplingrate meist gegeben ist, kann man mit n (das Equivalent zum
> analogen Wert von C im Tiefpass) spielen. Und da teilen bei einem µC
> teuer ist, sollte n eine Potenz von 2 sein.
>
> MfG Klaus

Das, was du da hast, ist ein IIR-Filter. Der gleitende Mittelwert ist 
aber ein FIR-Filter. Außerdem hast du eine für kleine 8-Bit rechenwerte 
ungünstige Operation drin, denn entweder die Multiplikation, oder die 
Division erfolgt durch eine Zahl, die kein Zweierexponent ist.

von pito (Gast)


Lesenswert?

Try this low pass:

new = A*new + B*old

where A+B=1.0

For example A=0.05, B=0.95. The smaller the A the stronger filter 
effect. P.

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

So sieht der Frequenzgang eines Gleitenden-Mittelwert-Tiefpasses im
Vergleich zu einem RC-Tiefpass 1. Ordnung (bzw. einem IIR-Tiefpass 1.
Ordnung oder einem PT1-Glied in der Regelungstechnik) bei gleicher
3dB-Grenzfrequenz (1 kHz) aus.

von MaWin (Gast)


Lesenswert?

> Wenn dein Messignal in den Frequenzbereich fällt, in dem der
> Tiefpass Wirkung zeigt, wird er es verfälschen.

Wie schrecklich.

Wenn du die Wahrheit in deine Worte fasst, wirst du sie verfälschen.

von MaWin (Gast)


Lesenswert?

> new = (old *(n-1) + messwert) / n

Das ist erkennbar nicht der Mittelwert der letzten n Samples.

Dazu müsste man ja das n+1-te Sample wieder aus der bisherigen Summe 
entfernen.

von eProfi (Gast)


Lesenswert?

Wenn ich einen 10Bit-ADC filtern will:

UInt16_t adcsum+=adc-(result=adcsum/64);

adcsum steigt auf das 64-fache von adc, solange adcsum/64 kleiner als 
adc ist.

Der Vorteil dieser Rechnung ist, dass result den ADC-Wert erreicht!
Ist wie gesagt aber ein PT1 und kein gleitender Mittelwert.

Beim gMw haben alle Inputs das selbe Gewicht, beim PT1 hat der aktuelle 
Input mehr Gewicht als die vergangenen.

Ist eine elegantere Schreibweise des im oben genannten PDF 
schift-filter.

von P. M. (o-o)


Lesenswert?

Anja schrieb:
> Versuche mal ein Signal auszuwerten das mit 50Hz Brumm verseucht ist.
> Ein gleitender Mittelwert über 20 ms ist da die einzige Rettung.

"Einzige Rettung" kann man so nicht sagen. Man braucht irgend ein 
Tiefpassfilter. Ein gleitender Mittelwert ist die einfachste Form, 
allerdings alles andere als ein optimaler Tiefpass. Für gute 
Tiefpassfilterung gewichtet man jedes Sample mit einem für jeden 
Zeitpunkt (relativ zur aktuellen Zeit) bestimmten Koeffizienten. Ein 
sogenanntes FIR-Filter. Die Koeffizienten für optimale Tiefpassfilterung 
(im Sinne des Frequenzgangens) entsprechen einer sinc-Kurve


Klaus schrieb:
> Für einen gleitenden Mittelwert braucht man keinen Buffer, die
> allgemeine Formel ist
>
> new = (old *(n-1) + messwert) / n

Das ist falsch. Ein gleitender Mittelwert über n Samples enthält nur 
Informationen aus diesen n Samples. Angenommen, du hast einen gleitenden 
Mittelwert über 5 Samples, du hast eine 1 bei Sample 1 und danach bloss 
Nullen. Demzufolge müsste dein Mittelwert bei Sample 50 eine 0 
ausspucken, deine Formel wird aber 1 / 50 generieren.

von (prx) A. K. (prx)


Lesenswert?

Kevin K. schrieb:

> Außerdem hast du eine für kleine 8-Bit rechenwerte
> ungünstige Operation drin, denn entweder die Multiplikation, oder die
> Division erfolgt durch eine Zahl, die kein Zweierexponent ist.

Nicht wenn man
      new = (old *(n-1) + messwert) / n
umformt zu
      new = (old * n - old + messwert) / n

von Yalu X. (yalu) (Moderator)


Lesenswert?

P. M. schrieb:
> Anja schrieb:
>> Versuche mal ein Signal auszuwerten das mit 50Hz Brumm verseucht ist.
>> Ein gleitender Mittelwert über 20 ms ist da die einzige Rettung.
>
> "Einzige Rettung" kann man so nicht sagen. Man braucht irgend ein
> Tiefpassfilter. Ein gleitender Mittelwert ist die einfachste Form,
> allerdings alles andere als ein optimaler Tiefpass.

Ein auf die richtige Periodendauer ausgelegter gleitender Mittelwert hat
immerhin die Eigenschaft, dass er den Brumm einschließlich aller seiner
Obertöne vollständig herausfiltert. Mit "irgendeinem" Tiefpass schaffst
du das nicht. Deswegen würde würde ich diese Methode nicht als "alles
andere als optimal" bezeichnen.

von (prx) A. K. (prx)


Lesenswert?

P. M. schrieb:

> Das ist falsch. Ein gleitender Mittelwert über n Samples enthält nur
> Informationen aus diesen n Samples.

Klaus hat nirgends behauptet, dass seine Formel ein gleitender 
Mittelwert über n Samples oder ein FIR Filter sei. Nur dass es ein 
gleitender Mittelwert sei. Und davon gibt es verschiedene Arten. Hier 
handelt es sich um einen exponentiell geglätteten Mittelwert, siehe 
http://en.wikipedia.org/wiki/Moving_average#Modified_moving_average.

Siehe auch Beitrag "Re: Tiefpaß mit C programmieren"

von W.S. (Gast)


Lesenswert?

A. K. schrieb:
> Klaus hat nirgends behauptet, dass seine Formel ein gleitender
> Mittelwert ... sei. Nur dass es ein gleitender Mittelwert sei.

Klingt ein bissel seltsam.

Ein gleitender Mittelwert ist programmiertechnisch ne einfache Sache, 
wenn man über eine Zweierpotenz von Werten mittelt und man kann damit 
auch auf einfacheren uC damit einen recht passablen Tiefpaß bilden. Der 
gleitende MW ist ansonsten der beste Tiefpaß, wenn es um den Erhalt der 
prinzipiellen Kurvenform (im Zeitbereich also) geht. Alle anderen 
Filterarten haben nämlich größere Verfälschungen der Kurvenform drauf: 
Überschwingen usw. Dafür ist der gleitende MW der schlechteste Tiefpaß, 
wenn man im Frequenzbereich einen möglichst scharfen Übergang vom 
Durchlaßbereich zum Sperrbereich sucht. Da wäre eher ein Chebyscheff 
oder elliptisch geeignet, aber die setzen wiederum mehr Rechenarbeit 
voraus.

Zum Glattmachen von oftmals verrauschten Werten vom eingebauten ADC im 
uC finde ich nen gleitenden MW über 4 oder 8 Werte unübertroffen gut, 
weil recht wirksam und dennoch ohne großen Aufwand zu machen. Ich setze 
sowas in meinen Geräten recht oft ein.

W.S.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:

>> Klaus hat nirgends behauptet, dass seine Formel ein gleitender
>> Mittelwert ... sei. Nur dass es ein gleitender Mittelwert sei.
>
> Klingt ein bissel seltsam.

Nur wenn man den entscheidenden Punkt weglässt.

Wer hier meist als gleitender (FIR) Mittelwert bezeichnet wurde ist ein 
ungewichteter Mittelwert der letzten n Samples, berücksichtigt keine 
vorigen Samples.

Der von Klaus angeführte (IIR) Mittelwert gewichtet die Samples jedoch 
abnehmend nach dem Alter. Dies entspricht einem R/C Tiefpass, der ja 
auch gewichtet und kein definiert begrenztes Gedächtnis hat.

Es gibt eben unterschiedliche Arten von gleitenden Mittelwerten. Und 
damit klingt mein Satz vielleicht weniger seltsam, weil ein "gleitender
Mittelwert über n Samples" eine Spezialisierung des Begriffs "gleitender
Mittelwert" ist.

von Hermann (Gast)


Angehängte Dateien:

Lesenswert?

MW schrieb:
> Wie berechnet man denn einen digitalen Tiefpass?
> Was sind die Kennzahlen?

Die Berechnung für die digitale Simulation eines PT1-Gliedes ist:
X[n] = X[n-1]*(1-Ta/T)+Y[n]*Ta/T*V
Dabei ist:
X[n] der neue Ausgangswert, X[n-1] der vorhergehende Wert
Y[n] der Eingangswert
Ta die Abtastzeit
T die Zeitkonstante
V die Verstärkung

Einen gleitenden Mittelwert würde ich wie schon beschrieben mit dem 
Ringspeicher machen.

von Thomas (Gast)


Lesenswert?

Vielleicht könnte Yalu sein Diagramm des Frequenzganges noch um die 
anderen Varianten ergänzen?

von Karl H. (kbuchegg)


Lesenswert?

Da dieses Thema immer wieder mal hochkommt, wie wärs mit einem 
Wiki-Artikel? Seltsamerweise gibt es dazu noch nichts. Der Artikel 
Digitale Signalverarbeitung ist in der Beziehung nicht besonders 
ergiebig.

von Hermann (Gast)


Angehängte Dateien:

Lesenswert?

Karl Heinz Buchegger schrieb:
> Seltsamerweise gibt es dazu noch nichts.

Den gleitenden Mittelwert gibt es aber schon:
http://de.wikipedia.org/wiki/Gleitender_Mittelwert

Ich verstehe die Diskussion um den gleitenden Mittelwert nicht, da das 
meiner Meinung nach nur mit dem Ringspeicher gelöst werden kann. Wenn 
einer bessere Erkenntnisse hat, soll er doch mal den Wiki-Artikel 
korrigieren.

Der gleitende Mittelwert hat den Vorteil (oder Nachteil), dass er die 
Vorgeschichte nach den n Werten des Ringspeichers vergisst und damit 
schneller als PT1 ist.

Das Verhalten lässt sich wunderbar mit einer Excel-Tabelle verifizieren 
(siehe Anhang). Auf diese Weise simuliere ich ganze Regelkreise. Die 
Optimierung geht dann sehr einfach mit Parametervariation.

von (prx) A. K. (prx)


Lesenswert?

Hermann schrieb:

> Den gleitenden Mittelwert gibt es aber schon:
> http://de.wikipedia.org/wiki/Gleitender_Mittelwert

Die englische Version macht auf mich einen besseren Eindruck:
http://en.wikipedia.org/wiki/Moving_average

> Ich verstehe die Diskussion um den gleitenden Mittelwert nicht, da das
> meiner Meinung nach nur mit dem Ringspeicher gelöst werden kann.

Eine bestimmte Version davon.

Es ist wie beim allgemeinen Begriff "Mittelwert" auch. Da gibt es 
mehrere, u.A. die arithmetischen, geometrischen und quadratischen 
Mittelwerte.

Daher ist es etwas vermessen, einen bestimmten davon als den einzig 
gültigen Mittelwert zu definieren. Beim gleitenden Mittelwert ist es 
nicht anders.

von Karl H. (kbuchegg)


Lesenswert?

Hermann schrieb:
> meiner Meinung nach nur mit dem Ringspeicher gelöst werden kann. Wenn
> einer bessere Erkenntnisse hat, soll er doch mal den Wiki-Artikel
> korrigieren.

Ich meinte eigentlich einen Artikel hier im µC-Wiki

von W.S. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich meinte eigentlich einen Artikel hier im µC-Wiki

Ist nett gedacht, aber eigentlich überflüssig.

Wer sich für sowas interessiert, sollte besser dies hier herunterladen 
(ist dort auch als PDF zu finden, man muß nur genau hinschauen):
"http://www.dspguide.com/pdfbook.htm";

und lesen. Ist gut und leicht leserlich geschrieben, aber beleuchtet die 
Dinge eher von der theoretischen Seite. Trotzdem meine Empfehlung, wenn 
man die Zusammenhänge verstehen will.

(Ich bin auf der Suche nach praktisch umsetzbaren Rezepten für die 
Softwareseite bei Software definiertem Radio. Dafür ist das Buch etwas 
zu theoretisch)

W.S.

von Bruder Paul (Gast)


Lesenswert?

MaWin schrieb:
> Wenn du die Wahrheit in deine Worte fasst, wirst du sie verfälschen.

Ich programmiere gerade die Sonntags-Predigt für morgen. Der heilige 
Google-Geist hat mich hierher geführt. Darf ich diesen wunderbaren Satz 
für meine Predigt verwenden? Selbstverständlich mit korrekter 
Quellenangabe?

Gott segne Dich!

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Angehängte Dateien:

Lesenswert?

@ Karl Heinz
Ich hab ein bisschen was zusammengeschrieben über die Herleitung der 
Grenzfrequenz. Über die Implementierung könnt ich auch noch schrteiben, 
ist mir aber heute schon zu spät. Bitte um Anregungen, 
Korrekturen,Verdammnisse....

Grüsse

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

A. K. schrieb:
> Der von Klaus angeführte (IIR) Mittelwert gewichtet die Samples jedoch
> abnehmend nach dem Alter. Dies entspricht einem R/C Tiefpass, der ja
> auch gewichtet und kein definiert begrenztes Gedächtnis hat.
>

Das begrenzte Gedächtnis ergibt sich aufgrund der Wortbreite! Einfach 
mal ausprobieren.


> Es gibt eben unterschiedliche Arten von gleitenden Mittelwerten. Und
> damit klingt mein Satz vielleicht weniger seltsam, weil ein "gleitender
> Mittelwert über n Samples" eine Spezialisierung des Begriffs "gleitender
> Mittelwert" ist.

Der Ansatz ist praxisnah, da man an den neueren Meßergebnissen im 
allgemeinen interessierter ist.

Ich benutze es auch. Geht gut mit 8-Bitter und Integer. Gute Mischung 
zwischen sauberer Sprungantwort und Rauschunterdrückung. Na besser: 
Störunterdrückung.

von Hermann (Gast)


Lesenswert?

@Gebhard:
Das ist aber kein gleitender Mittelwert!!
Das sieht nicht nur verdächtig wie ein Tiefpass aus, sondern es ist 
einer.
Wenn du jetzt noch K=Tabtast/Tzeitkonstante setzt, bist du genau bei der 
richtigen digitalen Simulation des PT1-Gliedes (siehe meine Berechnung 
von gestern).
Wie es zu dieser Berechnung kommt, kann ich auch noch ableiten (wenn's 
interessiert)

von (prx) A. K. (prx)


Lesenswert?

Abdul K. schrieb:

> Das begrenzte Gedächtnis ergibt sich aufgrund der Wortbreite! Einfach
> mal ausprobieren.

Aufgrund der begrenzten Genauigkeit der Rechnung. Natürlich. Das ist 
aber ein Nebeneffekt der praktischen Implementierung, nicht des zugrunde 
liegenden Algorithmus.

von Finsbury (Gast)


Lesenswert?

Also mein Ansatz war ganz ohne Filtertheorie im Zeitbereich: Eine 
wählbare Fensterbreite (prozentual über die Messwertanzahl angebbar), 
darüber den fortschreitenden Mittelwert, bei Überschreitung der Rändern 
werden Anfangs bzw Endwert vorgehalten. Dazu kommt noch eine 
gleichbreite Cosinusgewichtung damit starke lokale Maxima/Minima sich 
nicht über die gesamte Reihe ziehen. Lässt sich natürlich bestimmt auch 
prima mit Faltungssätzen und Polnullstellendiagrammen formulieren. 
Funktioniert aber auch so super.

von Pustekuchen (Gast)


Lesenswert?

eProfi schrieb:
> UInt16_t adcsum+=adc-(result=adcsum/64);

Das gefällt mir!
Aber eine Warnung an vermeintliche Programmbeschleuniger. Wer 
Schiebeoperationen bevorzugt schreibt besser
int adcsum += adc - (result = (adcsum+32) >> 6);

Anderfalls gibt es keine stabile '0' Anzeige sondern ein Flackern 
zwischen '-1' und '0'.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Thomas schrieb:
> Vielleicht könnte Yalu sein Diagramm des Frequenzganges noch um die
> anderen Varianten ergänzen?

Welche anderen Varianten? Das Diagramm enthält die Frequenzgänge für den
gleitenden Mittelwert (den arithmetischen, um genau zu sein) und für den
RC-Tiefpass 1. Ordnung (entspricht einem PT1-Glied in der Regelungstech-
nik). Ein IIR-Tiefpass 1. Ordnung (auch exponentielle Glättung genannt)
hat praktisch die gleichen Eigenschaften wie der RC-Tiefpass, solange
die Abtastfrequenz höher als der höchste Frequenzanteil des Eingangssig-
nals ist, ist also durch das Diagramm ebenfalls abgedeckt.

Pustekuchen schrieb:
> Aber eine Warnung an vermeintliche Programmbeschleuniger. Wer
> Schiebeoperationen bevorzugt schreibt besser
> int adcsum += adc - (result = (adcsum+32) >> 6);
>
> Anderfalls gibt es keine stabile '0' Anzeige sondern ein Flackern
> zwischen '-1' und '0'.

Das kann ich jetzt nicht ganz nachvollziehen. Da adcsum unsigned ist,
sollten die Division und die Shift-Operation das gleiche Ergebnis
liefern. Ist adcsum signed und negativ, ist das Ergebnis der Shift-
Operation implementation defined. Auf einem i86-PC entspricht >>6 einer
Division durch 64 mit Abrunden (bei /64 werden positive Ergebnisse ab-
und negative aufgerundet). Ein instabiles Ergebnis bei konstantem
ADC-Wert kann ich weder bei der Divisions- noch bei der Shift-Methode
beobachten.

Unabhängig davon würde ich das Aufsummieren vor der Skalierung des
Ergebnisses vornehmen, da damit die Totzeit des Filters um eine Abtast-
periode reduziert wird:
1
    adcsum += adc - result;
2
    result = adcsum >> 6;

oder wenn's undbedingt in eine einzelne Anweisung gepackt werden soll:
1
    result = (adcsum += adc - result) >> 6;

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

A. K. schrieb:
> Abdul K. schrieb:
>
>> Das begrenzte Gedächtnis ergibt sich aufgrund der Wortbreite! Einfach
>> mal ausprobieren.
>
> Aufgrund der begrenzten Genauigkeit der Rechnung. Natürlich. Das ist
> aber ein Nebeneffekt der praktischen Implementierung, nicht des zugrunde
> liegenden Algorithmus.

Hm. So betrachtet einer der wenigen Fälle wo die reale Hardware sogar 
'besser' ist als die Theorie ;-) Ich kenne sonst keinen weiteren Fall.

von Pustekuchen (Gast)


Lesenswert?

'adcsum' hatte ich als 'singed int' angenommen, um vorzeichenbehaftete 
Werte filtern zu können. Was ein I86-PC beim Schieben daraus macht, weiß 
ich nicht.
Beim AVR-GCC wird für eine 'signed int' Variable (hier timer) folgender 
Code erzeugt:

  timer= timer>> 6;
 10a:  80 91 68 00   lds  r24, 0x0068
 10e:  90 91 69 00   lds  r25, 0x0069
 112:  26 e0         ldi  r18, 0x06  ; 6
 114:  95 95         asr  r25
 116:  87 95         ror  r24
 118:  2a 95         dec  r18
 11a:  e1 f7         brne  .-8

Man sieht, dass durch asr r25 das Vorzeichen beim Schieben erhalten 
bleibt. Alle Werte von -1 bis -63 werden durchs Schieben zu -1. Daher 
meine Empfehlung, vorher zu runden.
timer/64 hätte als Ergebnis wie erwartet eine 0.

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

Pustekuchen schrieb:
> Beim AVR-GCC wird für eine 'signed int' Variable (hier timer) folgender
> Code erzeugt:
> ...

Also entsprechend wie beim PC.

> Man sieht, dass durch asr r25 das Vorzeichen beim Schieben erhalten
> bleibt. Alle Werte von -1 bis -63 werden durchs Schieben zu -1. Daher
> meine Empfehlung, vorher zu runden.

Bei vielen Anwendungen ist das Runden zur nächstliegenden ganze Zahl
besser (max. Fehler 0,5) als das generelle Auf- oder Abrunden (max.
Fehler 1), nicht jedoch bei dem Filter, um das es hier geht.

Hier ist die Art der Rundung (auf, ab oder zum nächsten Nachbarn) egal,
solange alle Zahlenwerte konsequent nach dem gleichen Verfahren gerundet
werden. Beim Aufrunden wird adcsum generell um 31 kleiner ausfallen als
beim Runden zum nächsten Nachbarn, beim Abrunden um 32 größer. Am
Ergebnis res ändert das aber nichts. Damit die Ergebnisse in allen drei
Fällen von Anfang an gleich sind, kann man diesen Unterschied von -31
bzw. +32 bereits beim Startwert von adcsum berücksichtigen. Nachdem das
System "eingelaufen" ist (d.h. res mindestens einmal erhöht und
erniedrigt worden ist), spielt der Startwert aber keine Rolle mehr.

Ungünstig ist bei diesem Filter allerdings die Verwendung der Division
anstelle der Shift-Operation. Da die Integer-Division in C negative
Ergebnisse auf- und positive abrundet, enstehen an den  Nulldurchgängen
des Ausgangssignals Unregelmäßigkeiten. Das angehängte Bild zeigt dies
anhand des Ausgangssignals bei einem Sprung des Eingangsignals von -5
nach +5. Aber wie gesagt, das ist nur ein Problem, wenn man man mit
negativen Zahlen rechnet. Da der Vorschlag von eProfi aber von unsigned
Werte ausgeht, ist die Division durch 64 völlig in Ordnung.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Es gibt auch noch die Rundung gerade/ungerade bei 0,5. Glaube auch ein 
Standard IEEE754. Fällt wohl in die Kategorie Noise-Shaping.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.