mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP Wie nach DFT/FFT die Signalfrequenz bestimmen?


Autor: christoph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe folgendes Problem, und finde keine Lösung.

Ich nehme mit dem Digitaloszi eine Messreihe von z.B. 50000 Punkten auf.
Mache davon am PC eine DFT.

Seien z.B. 100 Hz und 101 Hz die Center Frequenzen zweier Bins und ich 
speise 100.5 Hz ins Oszi ein. Dann verteilt sich ja die Leistung der 
100.5 Hz auf die benachbarten Bins.

Wie kann man dann erstens rausfinden
1) dass es 100.5 Hz sind (die Frequenz ist auf 0.5% genau bekannt!)?
2) Die Amplitude des 100.5 Hz Signals bestimmen?

Erhält man diese zwei Informationen aus den Amplituden der benachbarten 
FFT Bins oder wie sonst geht das?

Vielen Dank für Tipps
- Christoph

Autor: Thomas K. (tomthegeek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kommt drauf an mit welcher Fenster-Funktion du das machst.

http://de.wikipedia.org/wiki/Fensterfunktion

Das Problem an den Fensterfunktionen ist, dass sie entweder eine relativ 
gute Frequenzgenauigkeit oder eine relativ gute Amplitudengenauigkeit 
haben.

Sehr Amplitudengenau ist z.B. das Flattop-Fenster.

Autor: Christoph Lechner (clechner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Link. Die Seite mit dem Window Functions kannte ich schon.

Aber das Problem mit der Aufteilung des 100.5Hz Signals auf die Bins 
rund um 100Hz und 101Hz werde ich dadurch ja nicht los, oder?

Oder habe ich ein grundliegendes Verständnisproblem? Mein Verständnis 
ist, dass ich in dem Beispiel nur rausfinden kann, wieviel 100Hz und 
wieviel 101Hz in den 100.5Hz und wieviel von den anderen Frequenzen 
"drin" sind.

Grüße
- Christoph

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber das Problem mit der Aufteilung des 100.5Hz Signals auf die Bins
>rund um 100Hz und 101Hz werde ich dadurch ja nicht los, oder?

Nein. Es könnten ja auch 100Hz und 101Hz Frequenzen im Signal sein.

Autor: Christoph Lechner (clechner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Langsam kommen wir der Sache schon näher.

Aber was wenn ich weis, dass das Signal 100.5Hz hat?

Als Beispielanwendung fällt mir folgendes ein: Ich speise mit dem 
Synthesizer 100.5Hz Sinus in ein Filter mit Opamps ein. Am Ausgang des 
Filters hängt mein Oszi.

Jetzt will ich wissen, welche Amplitude hat das Signal?
Die Auto-Measure Funktion vom Oszi funktioniert aber bei geringeren 
Amplituden nicht mehr, denn dann kommt Noise dazu.

Mit der FFT möchte ich von Frequenz, die ich kenne (bis auf geringen 
Frequenzunterschied zwischen Oszi und Synthesizer) die Amplitude haben. 
Auch von Frequenzen grad zwischen den FFT Bins.

Grüße
- Christoph

Autor: Stefan Kunz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was du machen kannst einfach die Anzahl der Messwerte erhöhen und eine 
geeignete Abtastrate wählen um dann in 0,5 Hz Schritten die DFT auflösen 
zu können.

Autor: Christoph Lechner (clechner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Stefan:

Mein Oszi kann aber nur 50000 Samples am Stück messen, da gibt es also 
eine obere Grenze. Man möchte ja auch eine niedrige Samplerate, damit 
der Bin-Abstand klein wird, z.B. 1kS/s bei rd. 100Hz.

Gibt es wirklich keine andere Lösung fuer dieses Problem, wenn man die 
Frequenz kennt?

Autor: Rolfe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst die Schrittweite der FFT adaptieren, so dass nicht 1Hz, 2Hz, 
... 50000Hz gesampelt werden, sondern z.B. 90Hz, 90.0004Hz, 90.0008Hz 
... 109.9996Hz, 110.0000Hz.
Damit bekommst du bei 50000 Samples eine Auflösung von 0.002%.

Autor: Johann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie genau macht man das Rolfe?

Autor: Dogbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Korreliere doch mit sinus und cosinus der genau bekannten Frequenz.

Also ungefähr so:

double re=0, im=0;
const double fs=1e3;
const double f=100.5;
for (int i=0; i<50000; i++)
{
  re+=sample[i]*cos(i*2*M_PI*f/fs);
  im+=sample[i]*sin(i*2*M_PI*f/fs);
}

double ampl=sqrt(re*re+im*im);

Das ist eine DFT per Korrelation für einen Bin bei 100.5 Hz mit 1KHz 
Samplefrequenz.
Frequenzabweichungen führen aber auch hier zu Amplitudenabweichungen.

So koennte es doch sinnvoller sein eine FFT und eine "center of gravity" 
Berechnung rund um die Zielfrequenzbins zu machen.
Das sollte die Amplitude wie Frequenz genauer erfassen, auf Kosten von 
mehr Rauschen was über mehrere Zielfreqenzbins statt nur einer erfasst 
wird.

Multiplikation im Zeitbereich ist Faltung im Freqenzbereich, so daß sich 
durch Windowing im Zeitbereich die Freqenzbins mehr um die Zielfrequenz 
verteilen. Für genauere Amplituden und Frequenzermittlung muß sowieso 
eine "center of gravity"-Berechung über mehrere Bins erfolgen.

Deshalb ist nach meinem Verständnis Windowing in diesem Fall 
überflüssig, die „center of gravity“ Berechnung ist wesentlich zur 
„genauen“ Bestimmung von Amplitude und Frequenz.

Autor: detlef_a (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht wunderbar mit zwei versetzten ffts , Thema hatten wir im November, 
genaue frequenzbestimmung mittels fft
Cheers
Detlef

Autor: Dogbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber warum 2 "versetzte" FFTs mit Windowing wenn auch eine ohne 
Windowing reicht, Detlef?

Sollen die paar Prozent mehr Samples an Information über methodische 
Schwächen hinwegtrösten?

Autor: Detlef _a (detlef_a)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Dogbert schrieb:

> Sollen die paar Prozent mehr Samples an Information über methodische
> Schwächen hinwegtrösten?

verstehe ich nicht.

> Aber warum 2 "versetzte" FFTs mit Windowing wenn auch eine ohne
> Windowing reicht, Detlef?
>

Deine Methode funzt nicht genau, wenn Du keine ganzzahlige Anzahl 
Sinuswellen im Fenster hast, die ist verfälscht durch das Fenster, in 
Deinem Fall nen Rechteckfenster. Bei 40dB oder so ist da Schluß.

Angehängt ne Matlab Sinusfitroutine. Teile hatte ich schon mal 
eingestellt, neu ist die Amplitudenbestimmung.

Cheers
Detlef

Autor: Dogbert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Detlef _a schrieb:
> Deine Methode funzt nicht genau, wenn Du keine ganzzahlige Anzahl
>
> Sinuswellen im Fenster hast, die ist verfälscht durch das Fenster, in
>
> Deinem Fall nen Rechteckfenster. Bei 40dB oder so ist da Schluß.

Windowing (was ich evtl. für überflüssig hielt) ist wohl nötig, wegen 
spektralem aliasing. Also entweder Windowing im Zeitbereich oder 
komplexe Faltung im Frequenzbereich mit dem transormierten Window. 
Zeitbereich ist einfacher, schneller und praktisch genauer.

Die Wahl des Fensters ist Schlüssel zur Genauigkeit.
"Blackman–Nuttall window" ist wohl gut, es zeichnet sich durch sehr 
günstiges "spektrales aliasing" aus.

Dabei ergibt sich praktisch eine Genauigkeit von ca 0.02% der Amplituden 
bei 4096 Samples zwischen den Signalfrequenzen 1/126 zu 1/128.
Bei Signalfreqeunz 1/32 zu 1/34 ähnlich.
Bei Signalfreqenz 1/512 zu 1/545 weniger.

Die Genauigkeit der Amplitude wird hierbei scheinbar nicht schlechter 
mit größerem Unterschied zwischen Abtast und Meßfrequenz, also nur 
wenigen Perioden Nutzsignal.

Ich denke die Genauigkeit liesse sich durch ein optimiertes Fenster noch 
weiter steigern.

Wichtig ist auch ein zentrierter Bereich um das Zielbin
der Frequenzbins für die COG-Berechnung.

Da du ja viel mit Matlab experimentierst, kannst du das ja jetzt mal für 
dich nachvollziehen.

Autor: christoph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@detlef_a:
Ich habe deinen Code verstanden, bis auf die 1.055542E-5 in der Zeile wo 
c1 berechnet wird. Was ist der Sinn von diesem kleinen Korrekturwert?

Ich habs mit C umgesetzt. Ist zwar laenger als in Matlab aber ich 
brauchs in C!

Grüße
- Christoph

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
christoph schrieb:
> @detlef_a:
> Ich habe deinen Code verstanden, bis auf die 1.055542E-5 in der Zeile wo
> c1 berechnet wird. Was ist der Sinn von diesem kleinen Korrekturwert?

Gute Frage. Keine Ahnung, habe ich nicht verstanden. Macht zwar nur 
-153dB oder so aus, Fehlwert ist mir aber trotzdem nicht klar. Hab ich 
so pragmatisch rausgefummelt, weil ich für nen Beispiel wußte was 
rauskommen sollte.

>>Ich habs mit C umgesetzt. Ist zwar laenger als in Matlab aber ich
>>brauchs in C!

Super, interessiert mich sehr. Kannst/darfst/willst Du den Code 
zugänglich machen?

Cheers
Detlef

Autor: christoph (Gast)
Datum:
Angehängte Dateien:
  • preview image for x.png
    x.png
    9,07 KB, 280 Downloads

Bewertung
0 lesenswert
nicht lesenswert
Der Code wird zugaenglich gemacht werden.

Jetzt habe ich mal meinen 20MHz Synthesizer ans Oszi angeschlossen und 
die Kombination mal durchgeklingelt. Die Messung der Amplitude geschieht 
ueber den FFT Code in C.

Am Synthesizer war 1V Amplitude eingestellt.

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.