Forum: Mikrocontroller und Digitale Elektronik einfacher hochpass in C


von ryd11 (Gast)


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

von Antworter (Gast)


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.

von ryd11 (Gast)


Lesenswert?

Nein so funktionierts nicht.
Aber es muss doch eine equivalente Formel für den Hochpass geben oder?
Im Prinzip ist das ja ein IIR Filter 1. Ordnung.

von Coder (Gast)


Lesenswert?

Stichwort FIR-Filter. Die Koeffizienten kann man mit Scilab oder Matlab 
berechnen.

von Michael (Gast)


Lesenswert?

Ersetze in deiner Übertragungsfunktion einfach s durch 1/s (Stichwort 
Tiefpass-Hochpass-Transformation)

Gruß Michael

von Antworter (Gast)


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.

von FIR1 (Gast)


Lesenswert?

y0 = (x0 * k) - (x1 * k);
x1 = x0 * k;

wobei y0 und x0 die aktuiellen Werte sind und x1 der um einen 
Abatstschritt vergangene Wert ...

Gruss

von FIR1 (Gast)


Lesenswert?

sorry, ein k zuviel ;-)

y0 = (x0 * k) - x1;
x1 = x0 * k;

wobei y0 und x0 die aktuiellen Werte sind und x1 der um einen
Abatstschritt vergangene Wert ...

Gruss

von ryd11 (Gast)


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.

von Achim Hussel (Gast)


Lesenswert?

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

kleins bisschen schneller, da nur 1x shift:

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

von Antworter (Gast)


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.

von Gerd (Gast)


Lesenswert?

Mache einfach eine Transformation in superymmetrische Räume, damit 
klappts auf jeden Fall!

von Oliver J. (skriptkiddy)


Lesenswert?

Gerd schrieb:
> Mache einfach eine Transformation in superymmetrische Räume, damit
> klappts auf jeden Fall!
Kannst du das bitte genauer erklären?

von Mathias F. (minglifu)


Lesenswert?

Servus,

was spricht den gegen eine einfache bilinear Transformation?

H(s) = sT / (sT + 1)

mit s = 2  fa  (z - 1)/(z + 1)

MfG
Mathias

von Anja (Gast)


Lesenswert?

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

Zieh doch einfach vom Eingangssignal den gefilterten Wert ab.

Gruß Anja

von Helmut S. (helmuts)


Lesenswert?

Wie wärs denn damit.
http://en.wikipedia.org/wiki/High-pass_filter

fg = Hochpass-Grenzfrequenz, fs Abtastfrequenz

0 < a < 1

a = 1/(1+2*pi*fg/fs)


y[i] := α * (y[i-1] + x[i] - x[i-1])
------------------------------------

von Rene B. (themason) Benutzerseite


Lesenswert?

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

>Zieh doch einfach vom Eingangssignal den gefilterten Wert ab.

So hab ichs damals auf dem Atari mal ausprobiert. Hat geklappt. :-)

von ryd11 (Gast)


Lesenswert?

Hier also die equivalente Version zum Tiefpass im ersten Posting:

r = y + x0 - x1
x1 = x0
y = r >> 4

von Ralli (Gast)


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!

von Frank (Gast)


Lesenswert?

@Ralli: Du solltest noch sagen, 0 <= K <= 1, wobei ==0 und ==1 eher 
sinnfrei sind, aber ausserhalb dieses Intervalls wird's instabil ...

Gruss

von Schnulli (Gast)


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

von Schnulli (Gast)


Lesenswert?

uup's mit T1 verrutscht:

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

nu passt's

von Regelungstechniker (Gast)


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

von Ralli (Gast)


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?

von Helmut S. (helmuts)


Lesenswert?

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

Ich wiederhole mich.


Wie wärs denn damit.
http://en.wikipedia.org/wiki/High-pass_filter

fg = Hochpass-Grenzfrequenz, fs Abtastfrequenz

0 < a < 1

a = 1/(1+2*pi*fg/fs)


y[i] := α * (y[i-1] + x[i] - x[i-1])
------------------------------------

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.