Forum: Digitale Signalverarbeitung / DSP / Machine Learning SciLab: FFT (falsche Amplitude)


von Mgx (Gast)


Angehängte Dateien:

Lesenswert?

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.
1
Fs=62500;                         // Abtastrate 62.5kHz
2
N=length(x);                            // 4096 FFT-Blocklänge
3
t = 0:1/Fs:(N-1)/Fs;
4
n=length(t);
5
F=linspace(0,Fs,n);                     // Frequenzachse
6
whm=window('hm',n)';                    // Hamming-Fenster
7
xf=x.*whm;                              // Fenster multiplizieren
8
plot(F,xf);                             // x mit Windowfunktion
9
df=Fs/N;                                // 15.3Hz Auflösung
10
fmax=Fs/2;                              // 31.25kHz Nyquistfrequenz
11
X=2/N*abs(fft(x));                      // Transformation [AMPLITUDE FALSCH]

Liebe Grüße Mgx

von Jan K. (jan_k)


Lesenswert?

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?

von Helmut S. (helmuts)


Lesenswert?

Der Faktor 2/N für alle n außer dem Gleichwert ist richtig.
Natürlich reduziert eine Fensterfunktion die Werte.

von Mgx (Gast)


Lesenswert?

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?

von A. F. (elagil)


Lesenswert?

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.

von Mgx (Gast)


Lesenswert?

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!

von A. F. (elagil)


Lesenswert?

Bei einem reinen Sinus schon. Es darf aber auch nur einer sein. Zeig 
doch mal ein Bild ;)

von Mgx (Gast)


Angehängte Dateien:

Lesenswert?

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.

von A. F. (elagil)


Lesenswert?

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?

von Mgx (Gast)


Angehängte Dateien:

Lesenswert?

Sinus wird durch einen Frequenzgenerator erzeugt. Anbei der Sinus ohne 
Fensterung - Amplitude ist hier höher wie zu erwarten.

von Mgx (Gast)


Lesenswert?

Muss mich korrigieren.. ohne Fenster sollte die Amplitude kleiner sein.

von A. F. (elagil)


Lesenswert?

Dann passt die Frequenz vielleicht einfach wirklich nicht und bei der 
Amplitude wäre ich mir nicht sicher. Kannst du das im Zeitbereich 
angucken?

von Mgx (Gast)


Angehängte Dateien:

Lesenswert?

Anbei ein Plot mit dem Sinus im Zeitbereich und überlagerendem 
Hamming-Fenster.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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

von A. F. (elagil)


Lesenswert?

Genau, zeig mal den Realteil/Imaginärteil.

von Wolfgang (Gast)


Lesenswert?

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.

von Mgx (Gast)


Angehängte Dateien:

Lesenswert?

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

von Mgx (Gast)


Lesenswert?

Noch jemand da ? :)

von A. F. (elagil)


Lesenswert?

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.

von Mgx (Gast)


Angehängte Dateien:

Lesenswert?

Okay hab jetzt 2 plots im Anhang

von Denial (Gast)


Lesenswert?

Wenn es dir um die korrekte Amplitude auch bei ungenau getroffenen 
Frequenzen geht, nimm ein Flat-Top-Window.

von Mgx (Gast)


Lesenswert?

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!

von Jan K. (jan_k)


Lesenswert?

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
8
 plot(freq,F);

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.