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
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.
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
Alle Börsianer machen das mit ihren Kursen, das muss gut sein. http://www.aistockcharts.com/sma_stock_charting_indicator.htm
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?
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.
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
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
Wenn wir schon dabei sind. Wie programmiert man einen gleitenden Mittelwert am günstigsten? Bitte mit Codebeispiel.
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.
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.
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
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.
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
Klaus schrieb: > new = (old *(n-1) + messwert) / n Das ist aber kein gleitender Mittelwert sondern ein Spezialfall einer PT1-Funktion (Tiefpaß). Gruß Anja
Anja schrieb: > Das ist aber kein gleitender Mittelwert sondern ein Spezialfall einer > PT1-Funktion (Tiefpaß). Und was ist im Ergebniss der Unterschied? MfG Klaus
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...
Bassti schrieb: > Funktion, siehe PDF... Wow, ich wusste nicht, dass man einen zweiseitigen Artikel über sowas offensichtliches schreiben kann.
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.
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.
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.
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.
> 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.
> 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.
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.
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.
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
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.
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"
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.
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.
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.
Vielleicht könnte Yalu sein Diagramm des Frequenzganges noch um die anderen Varianten ergänzen?
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.
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.
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.
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
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.
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!
@ 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
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.
@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)
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.
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.
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'.
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; |
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.
'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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.