Forum: Digitale Signalverarbeitung / DSP / Machine Learning Tiefpass - Rundungsfehler


von Roland B. (role)


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

von nop(); (Gast)


Lesenswert?

Mit 16 bit integern rechnen ?

von Role (Gast)


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

von katzeklo (Gast)


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?

von Detlef _. (detlef_a)


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

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.