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
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
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...
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.
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.
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:
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.