einfacher hochpass in C

Gast #2303376
Lesenswert?

Hallo,

einen einfachen Tiefpass kann man programmieren:

filter += ((neuer_messwert - filter) >> 4))

bzw besser für die Implemeniterung mit Ganzzahlen

filter += neuer_messwert - filter >> 4
output = filter >> 4

Jetzt meine Frage: Wie sieht die Formel für den Hochpass aus?

mfg
ryd11
Gast #2303408
Lesenswert?

Das "filter += ..." zu "filter -= ...." tauschen sollte das Ganze zu 
einem Hochpass machen. Teste es aber lieber noch mal nach. Ich habe 
jetzt nur grob im Kopf überschlagen. Über z-Transformation und bisschen 
probieren kommt man aber auch ganz schnell selbst drauf.
Gast #2303775
Lesenswert?

Also. Dann schreib ich mal auf, wie ich darauf kam:

Die Berechnungsvorschrift im Zeitbereich für deinen Tiefpass ist 
folgende:

y(t) = (y(t-1) + x(t)  - y(t-1)*a)*a

Wobei a = 2^-4 wegen des Rechtsshift um 4 beträgt. Der Rechtsshift am 
Schluss ändert an der Filterwirkung an sich eigentlich nicht mehr viel. 
Prinzipiell ist das ganze wegen der Shifts aber auch nicht mehr linear, 
da es ja eine Integer Division ohne Nachkommastellen ist.

Um das Ganze systemtheoretisch als LTI-System zu betrachten, muss man 
diese Nichtlinearitäten vernachlässigen und davon ausgehen, dass keine 
Rundungsfehler auftreten. Eigentlich sollte das aber erst mal nicht viel 
ausmachen.

So. Nun Transformiert man die Rechnungsvorschrift vom Zeitbereich in den 
z-Bereich und erhält:

Y(z) = a*Y(z)*z^-1 + a*X(z) - a^2 * Y(z)*z^-1

Y(z) - a*Y(z)*z^-1 + a^2 * Y(Z)*z^-1 = a*X(z)

Y(Z) * (1 - a*z^-1 + a^2 * Z^-1) = a*X(z)

Y(z)/X(z) = H(z) = a/(1 - a*z^-1 + a^2 * Z^-1) = a/(1 + z^-1 *(-a + 
a^2)) = a/(1+ b* z^-1)

mit b = -a + a^2

H(z) ist also die Übertragungsfunktion deines Tiefpasses. Der 
Frequenzang ergibt sich aus dem Betrag von H(e^-j*w).
Mit eingesetzten werten für a und b also:

H(e^jw) = 2^(-4)/(1 + (-(2^-4) + (2^-4)^2) * e^-jw)

Also haben wir den Frequenzgang:

http://www.wolframalpha.com/input/?i=abs%28+2^%28-4%29%2F%281+%2B+%28-%282^-4%29+%2B+%282^-4%29^2%29+*+e^-iw%29%29+

Ich hoffe ich habe mich bis hierhin noch nicht vertan.

Nun zum Hochpass. Das erfahrene Auge tauscht nun einfach das Vorzeichen 
im Nenner und erhält:

H(z) = a/(1 - b* z^-1)

http://www.wolframalpha.com/input/?i=abs%28+2^%28-4%29%2F%281+-+%28-%282^-4%29+%2B+%282^-4%29^2%29+*+e^-iw%29%29+

Sieht soweit gut aus.

Also zurück in den Zeitbereich:

Y(Z) * (1 - b* z^-1) = X(z) * a

Y(z) - b*Y(z)*z^-1 = X(z)*a

y(t) - b*y(t-1) = x(t)*a

y(t) = x(t)*a + b*y(t-1)

Mit b = -a + a^2 --->

y(t) = x(t)*a - a*y(t-1) + a^2 *y(t-1) = a*(x(t) - y(t-1) + a*y(t-1))

Das wiederrum ist ist in deiner Schreibweise nichts anderes als:

filter = neuer_messwert - filter + filter >> 4
output = filter >>4

Ich hatte also gestern Nacht einen Denkfehler.
Was genau du mit deinen shits bezwecken willst, weiß ich zwar nicht. 
Aber so müsste es funktionieren.
Würde mich freuen, wenn du Rückmeldung gibst obs geklappt hat.
Gast #2303954
Lesenswert?

@ Antworter

Vielen Dank für deine Mühe.

Antworter schrieb:
> filter = neuer_messwert - filter + filter >> 4
> output = filter >>4

scheint zu funtionieren wenn ich output = filter setze, zumindest ändert 
sich die Amplitude meines Sinus Arrays in meinen Testprog das ich 
schnell geschrieben habe.

Die Shifts deswegen weil sie auf einer kleinen MCU halt ziemlich schnell 
sind.
Gast #2304202
Lesenswert?

ryd11 schrieb:
> scheint zu funtionieren wenn ich output = filter setze, zumindest ändert
> sich die Amplitude meines Sinus Arrays in meinen Testprog das ich
> schnell geschrieben habe.

Naja. Die Amplitude ändert sich bei diesem Filter in jedem Fall relativ 
stark, egal welche Frequenz du reinsteckst. Die Filterwirkung an sich 
ist prinzipiell auch nicht soooo super, was einfach an den seltsamen 
Filterkoeffizienten durch die shifts liegt.

Ich gehe mal davon aus, dass du das für deine Anwendung so haben willst, 
aber wenn du wirklich effektiv filtern willst, geht das auf jeden Fall 
auch mit wenig Aufwand besser.
Gast #2304368
Lesenswert?

Wollte ja nur noch mal kurz beim "mikrocontroller.net"
vorbeischauen. - Echt lustig, was hier für Transformationen
und superymmetrische Räume für simple Kinkerlitzchen bemüht
werden.

Die Wirkungsweise des ganz einfachen Tiefpasses ist im Klartext:
Der Ausgabewert wird nur allmählich an den Eingangswert angepasst.
(Wozu braucht man da -prinzipiell- eine Zwischenvariable?)

Tiefpass (in C):

input = new_value();                        // Neuen Wert holen
output += (input - out_old) * K;            // Ausgabe berechnen
out_old = output;                           // Wieder bereit!

Je größer "K", desto tiefer die Grenzfrequenz.

--------------------------------------------------------------------

Die Wirkungsweise eines ganz einfachen Hochpasses ist im Klartext:
Neue Eingangswerte erscheinen sofort am Ausgang, alte Ausgabewerte
verschwinden allmählich.

Hochpass (in C):

input = new_value();                        // Neuen Wert holen
output = (input - in_old) + (output * K);   // Ausgabe berechnen
in_old = input;                             // Wieder bereit!

Je größer "K", desto tiefer die Grenzfrequenz.


--------------------------------------------------------------------

Bei Tief- und Hochpass gilt:
Für definierte Grenzfrequenzen muss "K" entsprechend der
Abtastfrequenz gewählt werden...


Gute Nacht allerseits!
Gast #2304611
Lesenswert?

Hochpass ist nix anderes als ein DT1-Glied. Dafür gilt die 
Differenzengleichung im Zeitbereich:

out = Kd * (dxe/dt)/T1 - T1 * (dout/dt)/T1

Die Divisionen durch T1 kann man sich sparen, wenn man hier die 
Abtastzeit setzt. Somit ergibt sich das gewünschte Verhalten, sich 
ändernde Eingangswerte werden nahezu direkt übernommen und alte Werte 
klingen langsam ab ...
Gast #2304798
Lesenswert?

na, die simpelste Lösung für einen Hochpass (DT1-Glied mit Verstärkung 
1, wobei streng genommen der Hochpass nur ein D-Glied mit Verstärkung 
ist), die auch nur eine Speicherstelle braucht ist:

yneu = (xneu - yalt) * K + yalt; // Tiefpass (PT1), K zwischen 0 und 1
out = (xneu - yneu) * Kd; // Differenz zum PT1 ist Hochpassausgang (Kd = 
1)

Mit Kd kann man die Verstärkung des DT1-Gliedes ändern ...

Gruss
Gast #2305266
Lesenswert?

@ Frank

Da hast du natürlich recht, es war aber schon spät...

Fein, dass es hier auch Leute gibt, die einfache Fragen
gern korrekt, aber (so weit es geht) verständlich und
praktisch nutzbar beantwortet sehen!

Schaun wir mal, ob es noch mehr davon gibt:
-------------------------------------------

Gibts hier jemanden, der uns die Berechnung von K
zeigen kann, wenn F_abtast und F_grenz gegeben sind?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren