Hallo an Alle,
Ich habe ein Problem bei einer 'moving average' Berechnung.
Ich benutze ein CPLD (Coolrunner II ,XC2C256) als eine Art Multiplexer
um auf die Ausgabe zweier 14 Bit ADC zugreifen zu können. Das simple
durchschleifen der ADC Werte und umschalten von mehreren Eingangskanälen
funktioniert auch soweit.
Da ich jetzt noch ein paar Makrozellen frei habe dachte ich daran, noch
eine Mittelung einzubauen. Jedoch klappt die Berechnung nicht.
Vielleicht könnte mal jemand darüberschauen mit etwas mehr Erfahrung:
(die funktionierenden Teile des Programms hab ich rausgenommen)
--IN_REFRESH GIBT LETZTEN GEMESSENEN WERT VON CHANNEL IN_ADR AUS (UNGEMITTELT ODER GEMITTELT)
168
PROCESS_READ_in_refresh:process(CLK,RESET)
169
begin
170
ifrising_edge(CLK)then
171
ifRESET='1'then
172
SIG_IN_REFRESH<="0000";
173
else
174
SIG_IN_REFRESH(0)<=IN_REFRESH_DIRECT;
175
SIG_IN_REFRESH(1)<=SIG_IN_REFRESH(0);
176
SIG_IN_REFRESH(2)<=IN_REFRESH_MEAN;
177
SIG_IN_REFRESH(3)<=SIG_IN_REFRESH(2);
178
endif;
179
OUT_DATA<=SIG_OUT_DATA;
180
endif;
181
endprocess;
182
183
184
PROCESS_in_refresh:process(CLK,RESET)
185
begin
186
ifrising_edge(CLK)then
187
ifRESET='1'then
188
SIG_OUT_DATA<="00000000000000";
189
else
190
CASESIG_IN_REFRESHIS
191
WHEN"0001"=>--REFRESH DIRECT
192
ifSIG_ADR(3)='1'then--wenn > 7 dann ADC2
193
SIG_OUT_DATA<=SIG_ADC2_DATA;
194
else--ansonsten ADC1
195
SIG_OUT_DATA<=SIG_ADC1_DATA;
196
endif;
197
WHEN"0100"=>--REFRESH MEAN --xxxx
198
SIG_OUT_DATA<=SIG_ADC_MEAN;
199
WHENOTHERS=>
200
SIG_OUT_DATA<=SIG_OUT_DATA;
201
ENDCASE;
202
endif;
203
endif;
204
endprocess;
205
206
endBehavioral;
Hier noch etwas Erklärung zum Code:
- Der zustandsautomat liefert den Takt für den ADC und liest die
gemessenen Daten in Z4 ein
- Den FIFO Speicher bilden die vier Signale:
übergeben.
Um etwas konkreter zu fragen:
Ist die Addition in Zustand Z5, bzw die Subtraktion in Z1 korrekt?
Ist die Zuweisung des FIFO's richtig ?
Kann mir dabei Bitte jemand helfen ?
S. K. schrieb:> codefrage.txt
Meine VHDL-Datein heißen hinten raus *.vhdl
Dann klappt das auch mit dem Syntax-Highlighting...
> Ist die Addition in Zustand Z5, bzw die Subtraktion in Z1 korrekt?
Der Simulator ist der Debugger einer VHDL-Beschreibung...
Was sagt die Simulation?
Hast du eine Testbench?
Lothar Miller schrieb:>> codefrage.txt> Meine VHDL-Datein heißen hinten raus *.vhdl> Dann klappt das auch mit dem Syntax-Highlighting...
Hier ist ebenfalls der gekürzte Code enthalten.....
Lothar Miller schrieb:>> Ist die Addition in Zustand Z5, bzw die Subtraktion in Z1 korrekt?> Der Simulator ist der Debugger einer VHDL-Beschreibung...> Was sagt die Simulation?> Hast du eine Testbench?
Naja, eigentlich dachte ich , dass die Berechnung so Simpel wäre, dass
ich mir das Einarbeiten in Testbench/Simulator ersparen könnte....
Na dann muss ich wohl doch,
trotzdem mal danke,
stephan
Mir schein das ganze viel zu aufwendig, auch wenn ich wenig ahnung von
HDL habe. Ich weiss nur wie man's in code macht. In Hardware sollte es
noch viel einfacher sein. Schau mal den code an :
Http://www.ibrtses.com/embedded/exponential.html , im Prinzip nur
schieben und addieren.
Danke nochmal,
habe mir gestern mal ein Tutorial von Xilinx angesehen und ein wenig
ausprobiert. Ist doch wie immer: Wenn man sich mal ransetzt gehts
schneller als zunächst gedacht.
Es sieht aus als wäre da ein Timingproblem, das mir den
Zustandsautomaten aus der Reihe wirft.
mfg stephan
Ohne mir deinen Code genauer angeschaut zu haben, ist deine Methode der
Beschreibung etwas ungünstig, da hier, so wie es zumindest auf den
ersten Blick aussieht, jede Menge Register entstehen, die du vermutlich
gar nicht willst, oder benötigst.
Du beschreibst z.B. in einem CLK-Prozess die Zuweisung von FOLGEZUSTAND
so, dass daraus ein Register entsteht.
In einem anderen Prozess beschreibst du ZUSTAND auch in einem
CLK-Prozess, so dass auch hier ein Register entsteht.
Wenn ich das jetzt richtig überblicke, dann entsteht für FOLGEZUSTAND
und ZUSTAND jeweils ein Register. Und es dauert daher immer 2 Takte, bis
ZUSTAND den eigentlichen Folgezustand angenommen hat.
Solche Konstrukte hast du noch an anderen Stellen. Daher könnte es gut
sein, dass da Dinge passieren, die du dir vielleicht anders vorgestellt
hast.
Empfehlenswert ist meiner Ansicht nach folgende Methode:
Alle Register werden in EINEM Clocked-Process beschrieben.
Die ganze Kombinatorik dazwischen wird entweder komplett concurrend oder
in einem rein kombinatorischen Prozess beschrieben.
Das ist übersichtlicher und man vermeidet, dass Register entstehen, die
man eigentlich gar nicht im Kopf hatte..
@S. K. (Gast)
>Da ich jetzt noch ein paar Makrozellen frei habe dachte ich daran, noch>eine Mittelung einzubauen. Jedoch klappt die Berechnung nicht.
Ein paar? Wieviel denn?
Eine EINFACHSTE Mittlung über N Samples ist ein einfacher Akkumulator.
Addieren und Speichern, nach N Samples Reset bzw Laden mit dem nächsten
Sample. Deine Überschrift spricht aber von moving average, das ist was
anderes. Dafür braucht man mehrere Speicher für die alten Samples. Das
frisst deinen CPLD Ruck Zuck auf. Selbst als IIR Filter wird das SEHR
eng.
Falk Brunner schrieb:> Eine EINFACHSTE Mittlung über N Samples ist ein einfacher Akkumulator.
Ich würde da eher ein RC-Glied nachbilden: den neuen Wert auf den
Akkumulator aufaddieren, und gleichzeitig den Mittelwert abziehen...
Sowas wie das hier also:
http://www.lothar-miller.de/s9y/categories/21-Filter
Der eigentliche Trick: bei geeigneter Wahl der Filtertiefe (als
Zweierpotenz) ist keine wirkliche Division nötig...
Und hier mit Filtertiefe 32 in VHDL:
1
akku <= akku - akku/32 + in_data when rising_edge(clk);
Lothar Miller schrieb:> Der eigentliche Trick: bei geeigneter Wahl der Filtertiefe (als> Zweierpotenz) ist keine wirkliche Division nötig...
Ja, nur so ist es eigentlich auch Sinnvoll. Dann ist es nur noch eine
Schiebeoperation.
Eigentlich ist das Ganze doch nur ein FIFO mit N Werten des ADCs.
Bei jedem neuen Wert des ADCs wird der älteste Wert von SUM_ADC (also
SUM_ADC(N) ) entfernt, der neue Wert ins FIFO geschoben und gleichzeitig
noch zu SUM_ADC addiert.
Dann noch SUM_ADC ld(N) mal nach rechts schieben und der gleitende
Mittelwert ist fertig.
Oder sehe ich das falsch (zumindest mache ich das in C so).
Tachjen schrieb:> Dann ist es nur noch eine Schiebeoperation.
Bei Hardware nicht mal das:
es ist nur eine einmalige Umverdrahtung zum Synthesezeitpunkt...
> Eigentlich ist das Ganze doch nur ein FIFO mit N Werten des ADCs.
Nein, es ist ein Filter, der (wie ein RC-Glied) alte Werte nie
"vergisst". Sie können höchstens so unbedeutend werden, dass sie nicht
mehr mitmachen dürfen. Aber es wird nicht der "älteste" Wert abgezogen
wie bei gleictenden Mittelwert, sondern eben der Mittelwert der letzten
n Werte...
Lothar Miller schrieb:> Bei Hardware nicht mal das:> es ist nur eine einmalige Umverdrahtung zum Synthesezeitpunkt...
:-) stimmt. Ich denke noch zu sehr C
@ Lothar Miller (lkmiller) (Moderator) Benutzerseite
>http://www.lothar-miller.de/s9y/categories/21-Filter
Das ist ja tricky! Ein FIR Filter ohne großen Speicher!
Wie sieht denn die Sprungantwort bzw. der Frequenzgang von so einem Ding
aus im Vergleich zum echten FIR bzw. einfachen Akku? Klar, der einfache
Akku spuckt nur alle N Samples einen neuen Wert aus, nicht sehr
dynamisch.
Falk Brunner schrieb:> Das ist ja tricky!
Blöderweise nicht von mir... ;-)
Ich habe das irgendwann Ende der 80er Jahre des letzten Jahrtausends
gefunden (als Rechenzeit und Speicher noch was kostete). Aber in
Hardware lässt sich das eben supersimpel um- und einsetzen.
Falk Brunner schrieb:> Wie sieht denn die Sprungantwort bzw. der Frequenzgang von so einem Ding> aus
Wie im verlinkten Dokument zu sehen: eine E-Funktion wie beim RC-Glied.
Nur bei negativen Zahlen muss man mit der Schieberei ein wenig
aufpassen, denn z.B. ein (-7)/2 ist nicht das selbe wie ein (-7)>>1 ...
Hallo an Alle,
Zunächst mal danke für die Hilfe, denn zwischenzeitlich hats auch schon
geklappt (Immer diese Fehler ,die sich nach dem "aufräumen"
einschleichen). Die moving average Methode habe ich zufällig ausgewählt,
habe mich aber auch nicht weiter umgesehen welche Filtermethoden es
sonst noch gibt. Jetzt bin ich umgestiegen auf das nachgebildete
RC-Glied.......
Zu der Frage wieviele Makrozellen noch frei sind:
Ohne die Mittelung belege ich ca 100 Makrozellen von 256, also
jedemenge Platz zum Spielen.....
Schlumpf schrieb:> Wenn ich das jetzt richtig überblicke, dann entsteht für FOLGEZUSTAND> und ZUSTAND jeweils ein Register. Und es dauert daher immer 2 Takte, bis> ZUSTAND den eigentlichen Folgezustand angenommen hat.
Ja genau das ist passiert,
Schlumpf schrieb:> Alle Register werden in EINEM Clocked-Process beschrieben.> Die ganze Kombinatorik dazwischen wird entweder komplett concurrend oder> in einem rein kombinatorischen Prozess beschrieben.
Was bedeutet 'komplett concurrend' ?
Hier mal ein beispiel ob ich das jetzt richtig verstanden habe ,was mit
'rein kombinatorisch' gemeint ist:
1
-- INPUT ist der Wert der gemittelt wqerden soll
2
.
3
.
4
.
5
6
signalSUMME_NEU...
7
signalSUMME_ALT...
8
signalMITTELWERT...
9
begin
10
11
12
13
14
rein_kombinatorisch:process(SUMME_ALT,INPUT)
15
begin
16
SUMME_NEU<=SUMME_ALT-SUMME_ALT/32+INPUT
17
endprocess;
18
19
Clocked:process(CLK)
20
begin
21
ifrising_edge(CLK)then
22
MITTELWERT<=SUMME_NEU/32;
23
SUMME_ALT<=SUMME_NEU;
24
endif;
25
endprocess;
Jetzt wird die Summe doch 'immer' (kombinatorisch) berechnet aber nur
bei steigender Flanke von CLK weiterverwendet. Sehe ich das richtig bzw
geht das eleganter ?
S.K. schrieb:> Jetzt wird die Summe doch 'immer' (kombinatorisch) berechnet aber nur> bei steigender Flanke von CLK weiterverwendet. Sehe ich das richtig bzw> geht das eleganter ?
Klar, so wie ich das oben in meinem Zweizeiler gemacht habe. Auch dort
wird "immer" die Summe berechnet (weil der Addierer ja "immer" da ist)
und mit der steigenden Flanke gespeichert. Nur hast du zusätzlich noch
eine Registerebene und damit einen Takt Latency eingeführt. Das ginge
aber auch so:
1
akku<=akku-akku/32+in_datawhenrising_edge(clk);
2
out_data<=akku/32whenrising_edge(clk);
Oder konservativer so:
1
processbegin
2
waituntilrising_edge(clk);
3
akku<=akku-akku/32+in_data;
4
out_data<=akku/32;
5
endprocess;
Oder noch konservativer so:
1
process(clk)begin
2
ifrising_edge(clk)then
3
akku<=akku-akku/32+in_data;
4
out_data<=akku/32;
5
endif;
6
endprocess;
Aber das in zwei Prozesse aufzuteilen (von denen der eine mit dem
Addierer zudem vollkommen unnötig ist) ist absurd. Denn das hier:
1
rein_kombinatorisch:process(SUMME_ALT,INPUT)
2
begin
3
SUMME_NEU<=SUMME_ALT-SUMME_ALT/32+INPUT;
4
endprocess;
Kann funktionsgleich durch diese Concurrent-Beschreibung ersetzt werden:
Hallo S.K.
So wie du es beispielhaft dargestellt hast, ist das, was ich meinte,
richtig verstanden.
Ein Prozess beschreibt nur die Register, also das, was bei der
Taktflanke gespeichert wird.
Der andere Prozess beschreibt die Kombinatorik zwischen den Registern.
Genaugenommen hast du jetzt in deinem Beispiel im Clocked-Process noch
eine kombinatorische Verknüpfung "verbuddelt" (SUMME_NEU/32), welche
man, wenn man die Trennung ganz strikt halten will, auch noch in den
kombinatorischen Prozess ziehen könnte, aber dann müsste man noch ein
zusätzliches Signal einbauen. Da muss man dann einfach abwägen, wie
wichtig einem die absolut strikte Trennung ist.
Ich für meinen Teil halte das in meinen Designs sehr restriktiv und
hätte ein Signal MITTEL_KOMB eingeführt, welchem ich im Kombinatorischen
Prozess SUMME_NEU/32 zugewisen hätte. Und im Clocked-Process hätte ich
dann MITTELWERT <= MITTEL_KOMB zugewiesen.
Aber das ist dann schon sehr haarspalterisch ;-)
Mit "komplett concurrent" meinte ich, dass man bei einfacher Logik für
die Kombinatorik gar keinen Separaten Prozess benötigt, sondern einfach
nur rein concurrent die Zuweisungen machen kann.
In deinem Beispiel würde das so ausshen:
Lothar Miller schrieb:> Markus Wagner schrieb:>> so macht man das eigentlich nicht, weil so ständig falsch gerundet wird.> Warum? Und was sind die Auswirkungen?
Versteh ich auch nicht, was er damit meint...
Mal abgesehen von der Rundungsthematik scheint der Code ein Grundproblem
zu haben:
SIG_ADC_MEAN_VALUE_1 <= SIG_ADC_MEAN_VALUE_1; --begin: speicher
SIG_ADC_MEAN_VALUE_2 <= SIG_ADC_MEAN_VALUE_2;
SIG_ADC_MEAN_VALUE_3 <= SIG_ADC_MEAN_VALUE_3;
SIG_ADC_MEAN_VALUE_4 <= SIG_ADC_MEAN_VALUE_4;
Werte auf sich selber zu kopieren ist nicht so der Bringer. Auch in
FPGAs nicht. Ich denke das sollte mal die Schiebeoperation werden, oder?
SIG_ADC_MEAN_VALUE_1 <= Input_Vaue_primary; -- der neue Wert
SIG_ADC_MEAN_VALUE_2 <= SIG_ADC_MEAN_VALUE_1;
SIG_ADC_MEAN_VALUE_3 <= SIG_ADC_MEAN_VALUE_2;
SIG_ADC_MEAN_VALUE_4 <= SIG_ADC_MEAN_VALUE_3;
Dann kann man einfach Addieren und durch 4 teilen- wobei man vorher 2
addiert, womit wir jetzt doch beim Runden wären: Ich sehe sehr häufig,
dass bei INT Variablen / Signalen munter durchdividiert wird, ohne
vorher zu runden, wodurch man den doppelten Fehler bekommt.
Zu dem zweiten Vorschlag:
Das ist ein träges IIR-ähnliches Filter, das ebenfalls nicht ganz
korrekt gerundet wird: Wenn mit 32 dividiert werden soll, wäre zuvor 16
zu addieren, damit der Fehler geringer wird. Am Besten ist es immer,
eine hochaufgelöste Summe mitzuführen, bei der gar nicht dividert werden
muss bzw. statistisch (toogled) zu runden und zu dividieren:
SUMME_DIF <= ( SUMME_NEU + Teiler/4 + toogle*Teiler/2 ) / Teiler
SUMME_NEU <= SUMME_NEU - SUMME_DIF + INPUT;
Wobei beides in einem Takt erfolgen muss und "Teiler" hier wie immer ein
Binärwert ist. Einen IIR halte ich aber nicht für zweckmässig und das
wäre auch kein gleitender Wert, wie der TE möchte:
Besser ist, einen sauberen FIR einzufügen, mit dem man direkt fenstert!
Das Fenster kann "Ungefähr-Cos-Bogen" sein, das reicht in der Regel.
Summe der Gewichtungen wieder als Binärwert:
Pseudo Code:
IF clockedge
data8 = data7
data7 = data6
...
data2 = data1
data1 = input
term1 = data1 + data8
term2 = data2 + data7
term3 = data3 + data6
term4 = data4 + data5
sum = 1 x term1 + 3 x term2 + 5 x term 3 + 7 x term 4 + 16
erg = sum / 32
END IF
Ein bischen mehr HF-Dämpfung bekommt man mit:
sum = (2 x term1 + 3 x term2 + 5 x term 3 + 6 x term 4 + 16) / 32
Jürgen Schuhmacher schrieb:> Werte auf sich selber zu kopieren ist nicht so der Bringer. Auch in> FPGAs nicht.
Was ist daran verkehrt, wenn man den Ausgang eines Registers auf den
Eingang des Registers zurückkoppelt?
Schlumpf schrieb:> Jürgen Schuhmacher schrieb:>> Werte auf sich selber zu kopieren ist nicht so der Bringer. Auch in>> FPGAs nicht.>> Was ist daran verkehrt, wenn man den Ausgang eines Registers auf den> Eingang des Registers zurückkoppelt?
Es braucht einen zusätzlichen Multiplexer.
Ohne Rückkopplung wird das Synthesetool in der Regel das über
ClockEnable des Registers regeln.
Kann natürlich sein, dass der Synthesier auch den Multiplexer
wegoptimiert und durch ClockEnable ersetzt.
Schlumpf schrieb:> Was ist daran verkehrt, wenn man den Ausgang eines Registers auf den>> Eingang des Registers zurückkoppelt?
Es ist eine nutzlose Aktion. Es tut sich ja nichts. Warum sollte man das
formulieren?
Im Übrigen war meine Anmerkung ja die, dass das funktionell falsch ist.
Irgendwo müssen die Register ja mit Werten gefüttert werden. Das und nur
das sollte man formulieren.
Natürlich sind wir uns einig, dass ein reines Zurückkoppeln des Ausgangs
auf den Eingang sinnlos ist und funktionell so nichts bringt.
Wenn aber der "übliche" Fall eintritt und der Registerausgang anhand
eines bestimmten Systemzustandes geändert wird, so muss entweder das
Register für alle anderen Fälle deaktiviert werden (clk-enable) oder mit
dem Ausgang selbst "gefüttert" werden.
Und dann hat man entweder die Möglichkeit, sich über den
"default-Zustand" auszuschweigen, oder diesen zu beschreiben.
Beschreibt man ihn nicht, so überlässt man der Synthese, was sie daraus
macht. Das kann dann ein Multiplexer, clock-enable, oder im dümmsten
Fall vielleicht sogar ein Latch sein.
Beschreibt man es, dann kann man wenigstens sicher sein, dass kein Latch
entsteht.
Man müsste sich das mal genau anschauen, was die einzelnen Synthesizer
aus unterschiedlichen Beschreibungen zusammenbauen.
Vermutlich könnte es schon darauf hinauslaufen, dass es etwas
ressourcenschonender ist, das Register nicht zurückzukoppeln.
Lothar Miller schrieb:> Falk Brunner schrieb:>>> Das ist ja tricky!> Blöderweise nicht von mir... ;-)> Ich habe das irgendwann Ende der 80er Jahre des letzten Jahrtausends> gefunden
Das haben viele gefunden, ist eine naheliegende Idee und bei genauer
Betrachung nichts anderes, als eine Kondensatorladekurve. Wird in der
SW-Landschaft seit den 60ern eingesetzt, seit sie zum Mond geflogen
sind.
Was mich mehr bewegt ist die Frage, ab das ein "moving average" ist und
ob das der Aufgabe angemessen ist. Was einfach zu programmieren ist,
muss nicht gut sein für die App. Avarage heisst bei mir "Mittelwert"
aber es ist kein Mittelwert von irgendwas sondern eine Summe, bei der
das jüngste Element am meisten zu sagen hat, und das älteste am
wenigsten. Das Problem dieser Methode ist, dass sogar das allererste
Element noch schwach drinsteckt, obwohl das keine Aussage mehr machen
sollte. Eine verbesserte Methode wäre, zwei solcher "Summen"
mitzuschleppen, diese wechselseitig zu resetten, sodass sie nur für
einen bestimmten Zeitraum gelten und dies beide zu mitteln.
Schlumpf schrieb:> Wenn aber der "übliche" Fall eintritt und der Registerausgang anhand> eines bestimmten Systemzustandes geändert wird, so muss entweder das> Register für alle anderen Fälle deaktiviert werden (clk-enable) oder mit> dem Ausgang selbst "gefüttert" werden.
Seit wann denn das? Ist das bei FPGAs so? Ist das nicht so, dass a
automatisch ein enable erzeugt wird, für den IF-WHEN-case, der relevant
ist und ansonsten das enable low ist?
So haben wir das gelernt und so habe ich das immer gemacht.
Meinungen?
Mark F. schrieb:> Schlumpf schrieb:>> Wenn aber der "übliche" Fall eintritt und der Registerausgang anhand>> eines bestimmten Systemzustandes geändert wird, so muss entweder das>> Register für alle anderen Fälle deaktiviert werden (clk-enable) oder mit>> dem Ausgang selbst "gefüttert" werden.>> Seit wann denn das? Ist das bei FPGAs so? Ist das nicht so, dass a> automatisch ein enable erzeugt wird, für den IF-WHEN-case, der relevant> ist und ansonsten das enable low ist?
Du beschreibst doch in deiner Anmerkung genau das Gleiche, was ich auch
gesagt habe (Register wird mit clock enable deaktiviert, wenn es nicht
geändert werden soll). Daher verstehe ich deine Frage "Seit wann denn
das?" nicht so richtig.
Ich habe gerade mal eine simples Konstrukt auf verschiedene Arten
beschrieben (ohne Rückkopplung des Registers auf sich selbst, mit
Rückkopplung, ein-Prozess-Methode, zwei-Prozess-Methode,..) und jedesmal
spuckte die Synthese das identische Ergebnis aus:
Die Steuerung des Registers erfolgte in allen Fällen über clk-enable.
Schlumpf schrieb:> Die Steuerung des Registers erfolgte in allen Fällen über clk-enable.
Ja, zum Glück erkennt die Synthese in den meisten Schreibweisen, was
eigentlich gemeint war...
http://www.lothar-miller.de/s9y/archives/1-Clock-Enable-in-einer-ISE-VHDL-Beschreibung.htmlMark F. schrieb:>> Ich habe das irgendwann Ende der 80er Jahre des letzten Jahrtausends>> gefunden> Das haben viele gefunden, ist eine naheliegende Idee und bei genauer> Betrachung nichts anderes, als eine Kondensatorladekurve.
Ich meine, genau das schon geschrieben zu haben, denn
Lothar Miller schrieb:>>>>> Ich würde da eher ein RC-Glied nachbilden
Aber seis drum, Wiederholung schadet nicht.
> Das Problem dieser Methode ist, dass sogar das allererste Element> noch schwach drinsteckt, obwohl das keine Aussage mehr machen sollte.
Es ist kein Problem, wenn einem dieses Verhaltens bewusst ist. Denn
der älteste Wert verliert exponentiell an Bedeutung. In der Realität ist
er bei einem 8 Bit Wert nach gut 5 tau (im Beispiel mit der Filtertiefe
32 also nach 160 Abtastungen) nicht mehr signifikant wirksam.
> Eine verbesserte Methode wäre, zwei solcher "Summen"> mitzuschleppen, diese wechselseitig zu resetten, sodass sie nur für> einen bestimmten Zeitraum gelten und dies beide zu mitteln.
Anderer Aufwand ergibt andere Ergebnisse, womit sich dann letztlich
wieder mal die Frage stellt:
> ob das der Aufgabe angemessen ist.
Lothar Miller schrieb:> einem 8 Bit Wert nach gut 5 tau
Stimmt schon, aber je nach Datenbestand ist es wenig zielführend,
Methusaleminformationen mitzuschleppen. Bei der BV kümmert es mich
wenig, was ein Pixel 100 Werte weiter links für eine FArbe hatte.
Es gibt ausserm noch ein Problem! Auch wenn gerundet wird, entstehen
jedesmal Fehler:
Beispiel:
Die Werte 74 und 77 bei *15/16: Die konvergieren nach wenigen Schritten
zum selben Wertanteil in der Endsumme. Laut Excel ab Wert 37
Die Werte 73 und 77 halten dagegen ihren 6%-Abstand zu einander und
haben kurzfristig sogar mal eine Differenz von fast 9%. Ein einziges
Digitit führt also zu einem chaotischen Verhalten das den Endwert
komplett anders beeinflusst. Er hilft dann dem anderen Term in der
Endsumme mitunter in die eine oder andere Richtung gerundet zu werden,
wodurch sich das noch verstärken kann.
Nimm Dir mal ein Excel und spiele das mal durch. Du wirst Dich wundern!