Hallo zusammen,
ich habe von meinen Messdaten eine FFT in SciLab gemacht.
Es handelt sich um ein Rechtecksignal mit 4kHz und 5V Amplitude.
Wie im angehängten Plot zu erkennen, sind meine Frequenzen richtig,
jedoch habe ich wohl einen Fehler in der Normierung meiner Amplituden.
X=2/N*abs(fft(x)); Ich teile durch die Blocklänge N und multipliziere
mit 2. Um nur den Realteil zu erhalten, nutze ich die Funktion abs.
Wäre dankbar für Hinweise wo mein Fehler liegt.
Mit abs bekommst du nicht den realteil sondern den Betrag des komplexen
Vektors, nur als Anmerkungen. Magst du mal den ganzen Code zeigen? Mir
fehlt da der plot des Spektrums und der Frequenzshift.
Die Normierung mit 2 ist eigentlich korrekt, aber vergiss nicht, das
beim dc Anteil nicht zu machen!
Was passiert ohne Fenster?
Der Plot ohne Fensteranwendung ist bereits angehängt. Es sollte eine
Amplitude von 5 herauskommen im Frequenzbereich, aber ich bekomm eine
von ~6,3.
Man kann sehen dass ich nicht xf (x mit Fensterfunktion), sondern von
dem Signal x eine FFT mache. Bei Anwenden der Fensterfunktion bekomme
ich komischerweise eine geringere Amplitude von ca 3,4. Sollte durch das
Reduzieren der Nebenfrequenzen (Leakage) die Amplitude nicht eher höher
werden?
Wie normiere ich meine Amplitude korrekt?
Die Amplitude ist genau richtig! Die Grundschwingung hat eine Amplitude
von mehr als 5. Schau dir die Reihenentwicklung für die Rechteckfunktion
mal an:
http://de.wikipedia.org/wiki/Rechteckschwingung#Spektrale_Betrachtung
Der Scheitelwert der Rechteckfunktion wird erst erzielt, wenn mehrere
Sinusfunktionen überlagert werden.
Okay das klingt einleuchtend bei einem Rechtecksignal, aber sollte ich
bei Anregung durch ein Sinussignal nicht die gleiche Amplitude im Zeit-
wie auch im Frequenzbereich bekommen?
Hab das gleiche Spiel nämlich auch mit einem Sinussignal gemacht.
Danke für die Hilfe!
Das ist jetzt eine FFT mit einer Blocklänge von 1024.
Das Sinussignal hat eine Frequenz von 3kHz und eine Amplitude von 3V.
Fensterfunktion ist angewendet.
Anbei der Plot.
Man kann sehen, dass er die Frequenz nicht richtig trifft.
Ich kann schwer sagen, woran es liegt, dass das ungenau wird, hier ein
paar Vermutungen:
Für den Amplitudenfehler:
- Die Fensterung reduziert den Energiegehalt des Eingangssignals
und/oder erzeugt leakage. Wie sieht das ohne Fenster aus?
Für den Frequenzshift:
- Die FFT Algorithmen übersteuern den Wertebereich zwischendurch.
Beispiel: Radix 2 FFTs können pro Stufe den Eingangswert um bis zu
Faktor 2.8 anheben (wenn ich mich nicht verrechnet habe). Bei 10 Stufen
ist das eine resultierende Amplitude von ca. 90000, die nicht mehr in
ein int16 passt.
Wenn das Programm auf einem Computer läuft ist das wohl irrelevant
(float)
Wie sieht denn der Sinus aus? Wie wird der erzeugt?
Kann es sein dass der fehlende teil im "zweiten" (gespiegelten)
FFT-Fenster steckt (welches normalerweise ausgeblendet wird)
es fehlen nämlich genau sqrt(2)
sqrt(2.1*2.1 + 2.1*2.1) = 3
Mgx schrieb:> Sinus wird durch einen Frequenzgenerator erzeugt. Anbei der Sinus ohne> Fensterung - Amplitude ist hier höher wie zu erwarten.http://www.wie-als.de/Mgx schrieb:> Muss mich korrigieren.. ohne Fenster sollte die Amplitude kleiner sein.
Sollte sie nicht, sofern das Fenster richtig normiert ist.
Durch den Leakage-Effekt treten Nebenfrequenzen auf, die Enerige
verteilt sich somit auf diese und die Amplitude meiner eigentlichen
Grundschwingung nimmt dadurch ab - oder hab ich da was falsch
verstanden? Der Energiegehalt wäre ohne Nebenfrequenzen komplett in
meiner Amplitude der Grundschwingung wiedergespiegelt!?
Anbei ein Plot von Real-/Imaginär-Teil oder soll ich euch alle 1024
Werte meines Ergebnisses der FFT hier reinposten? ^^
plot gibt X=fft(x) wieder - ohne Fensterung, ohne abs
Mgx schrieb:> Durch den Leakage-Effekt treten Nebenfrequenzen auf, die Enerige> verteilt sich somit auf diese und die Amplitude meiner eigentlichen> Grundschwingung nimmt dadurch ab
das stimmt.
Mgx schrieb:> Der Energiegehalt wäre ohne Nebenfrequenzen komplett in> meiner Amplitude der Grundschwingung wiedergespiegelt!
das auch. ;)
Mgx schrieb:> Anbei ein Plot von Real-/Imaginär-Teil
Das ist nur eins von beiden! Du müsstest wohl zwei plots haben.
Also zum Beispiel plot(real(fft(X))) und plot(imag(fft(X))). Sonst wäre
auf der y-Achse auch nicht die Amplitude, sondern der Imaginärteil.
Was ist genau gemeint mit ungenau getroffenen Frequenzen? Bedeutet, dass
die FFT durch ihren Algorithmus die Frequenzen aus dem Zeitbereich nicht
genau ermitteln kann?
Ich möchte nach der FFT Filter anwenden um Pegel in bestimmten
Frequenzbereichen zu ermitteln und hätte daher gerne die "richtigen"
Amplituden ;) - in SciLab habe ich mir hierfür gewisse Filter gebaut und
angewendet, jedoch gehen die Filter-"Amplituden" nur bis 1 (weil Ua/Ue),
meine Amplituden des Frequenzbereichs haben jedoch ihre eigenen Werte
(z.B. 3,8V) - wie kann ich die Filter hier korrekt anwenden? Muss ich
meine Amplituden vorher normieren? Eine weitere Frage wäre, ob durch
diese digitalen Filter eine Phasenverschiebung entsteht, welche ich
berücksichtigen muss, obwohl ich NUR den Betrag errechnet habe.
Danke für die Hilfe soweit!
Ich denke die falsche Amplitude löst du durch eine weitere Normierung
über die Summe des Fensters.
Die Wahl des Fensters bleibt dir überlassen, flattop ist gut, wenn du
starke leakage Effekte hast, macht aber die Frequenzauflösung ziemlich
mies. Hanning läuft ganz gut bei mir.
1
fun = rect(...); % oder sinus oder was auch immer
2
N = length(fun) * paddingfactor; % zeropadding für factor > 1
3
winfun = flattopwin(length(fun));
4
fun = fun.*winfun*length(fun)/sum(winfun);
5
F=abs(fft(fun,N));
6
F=2*F./length(fun); %normieren, Faktor 2, damit Peaks Amplitude wiederspiegeln
7
F(1)=F(1)/2; % DC Anteil anpassen, da zwei Peaks auf f=0 fallen