mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP Tiefpass - Rundungsfehler


Autor: Roland B. (role)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich benutze folgende "Tiefpass" - Formel:

value=(COEFF*value+(100-COEFF)* previous_value)/100;
previous_value=value;

Diese Formel "begrenzt" die max. Änderung je nach COEFF (z.B. COEFF=1 => 
1%)

Hat man einen Sprung von z.B. 0 auf 1000 so läuf das Signal erst schnell 
und dann immer langsamer dem Endwert zu.

Mein Problem sind nun die Rundungsfehler, die bei meinem 8bit 
µController auftauchen. (bei diesem Beispiel von 0 auf 1000 komme ich 
gerade mal auf 95,1% des Endwertes) - da die Änderungen nahe dem Endwert 
natürlich so klein sind, dass sie ständig abgeschnitten werden.

Hat mir jemand eine Lösung??

Ich habs schon versucht in dem oberen Bereich dann zu linearisieren, 
jedoch habe ich Werte, die von 0 bis 18000 sein können (Endwert= z.B. 
100) und der COEFF kann auch zwischen 0 und 100 sein.

Vielen Dank schon mal!

Gruß Roland

Autor: nop(); (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit 16 bit integern rechnen ?

Autor: Role (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nop();

Ich rechne schon mit 16bit integer Zahlen.
Nur durch die prozentuale Annäherung an den Endwert (=> irgendwann 
sollte ich dann bei 99,9999% sein) wird die Änderung so klein, dass mein 
Controller die "Komma-Stellen" abschneidet.

Ich würde gerne ab z.B. einem Endwert von 95% einen linearen Anstieg 
programmieren, jedoch ist der Fehler bei einem kleineren Endwert viel 
viel größer und dort müsste ich schon bei 50% linearisieren.

Leider kennt mein Controller keine float Zahlen!

Gibt es sonst noch eine Möglichkeit?

Gruß Roland

Autor: katzeklo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn der Controller kein Float "hat", dann kümmert sich halt der 
Compiler drum, wie üblich. Oder ist dein Controller so langsam, dass 
sich emuliertes Float bemerkbar macht?

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Gibt es sonst noch eine Möglichkeit?
Ja, die gibt es. Du muß Deine Dynamik besser nutzen.

Deine Formel lautet ein wenig konventioneller hingeschrieben:

previous_value(k+1)=a*value+(1-a)*previous_value(k) mit a=Coeff/100

Für den 'steady state' ist previous_value = value, also value so 
vorskalieren, daß er gut in den Zahlentyp paßt, hängt vom Wertebereich 
von value ab. Für a ne Zweirepotenz in den Nenner nehmen, also z.B. 
1/128, teilen durch 128 ist einfach 7 Stellen nach rechts schieben. 
(1-a) ist dann 127/128, d.h. Du multiplizierst previous_value(k) mit 127 
und shiftest dann 7 Stellen rechts. Bei 16 Bit darf previous_value(k) 
dann höchstens 16-7-1=8Bit groß sein, 1000 für value geht gar nicht 
mehr. Das ist aber sicher mit ner 16*16->32Bit Multiplikation und 
Shifterei zu schaffen.

Cheers
Detlef

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.