Hallo,
ich habe da mal eine kleine Frage. Ich habe ein Mikro an meinem Atmega 8
angeschlossen, weil ich das Frequenzspektrum zu einem Geräusch
feststellen möchte, mittels einer FFT. Den Quellcode in C (im Anhang)
habe ich bereits gefunden und auch schon in den µc gebrannt. Ich nehme
nun ein Feld mit [128] Werten (Realteil) auf und fülle das Imaginärfeld
komplett mit Nullen. Mit diesen Werten lasse ich denn die FFT
durchführen. Anschließend lasse ich mir das Real-Feld wieder ausgeben
und es stehen auch Werte drin, aber jetzt meine Frage, weiß jemand wie
diese Werte zu interprtieren sind? Ich wäre für eure Hilfe und Antwort
sehr dankbar!
Es kommt darauf an was du genau wissen willst von dem Signal. Allgemein
brauchst du aber erst mal den real und imaginär Teil.
Interessiert dich der Frequenzgang, dann kannst du den Absolutwert
nehmen, also
.
Damit bekommst du ein Bild über die Amplitude der einzelnen
Frequenzkomponenten, aber die Phasenbeziehung geht verloren.
x(t) ist reel, insofern ist es ok mit den Imagenärteil
mit Nullen aufzufüllen.
Nach FFT hast X(f). Über welche Eigenschaften X(f)
verfügt kann man nichts aussagen.
Das könnte man, wenn man über weitere Eigenschaften
von x(t) verfügen würde. Wie zB x(t)=x(-t) usw.
Das ist eher theoretisch und wahrscheinlich hat
dein x(t) Signal keine Symmetrien.
Deswegen muss man X(f) im allgemeinen als
komplexwertig ansehen, ausser vielleicht X(0).
X(0) ist Gleichanteil deines Zeitsignals und ist
auch reelwertig (das erkennt man wenn man in
Fouriertransformation f=0 direkt einsetzt)
|X(f)| gibt dir den Überblick über die enthaltenen
Frequenzen. Ist |X(f')| = 0, dann ist f' nicht
im Signal enthalten.
Vielleicht kannst du über uart die Werte übergeben
und auf PC darstellen. Cool wäre auch
Signalquellen mit bekannter Frequenz aufzuzeichen
um das ganze am Ende zu überprüfen.
Gruss, Daniel
Erst einmal vielen Dank für eure schnelle und gute Hilfe!
ich habe mir das reelle Feld (die 128 Werte) vorhin auch schon mal auf
einem Display nach der FFT wieder ausgeben lassen, es stehen dort
positive und negative Werte drin, sind dies denn die Amplituden der
jeweiligen Frequenzkomponenten? Wenn ja, woher weiß ich zu welchen
Frequenzen die jeweiligen Amplituden gehören, wenn z.B. der erste Wert
des Feldes 10dB ist, zu welcher Frequenz gehört diese Amplitude? Wenn
ich die Werte im Imag-Feld "Null" setze vor der FFT, habe ich denn
später meine Amplituden direkt im Real-Feld?
>ich habe mir das reelle Feld (die 128 Werte) vorhin auch schon mal auf>einem Display nach der FFT wieder ausgeben lassen, es stehen dort>positive und negative Werte drin, sind dies denn die Amplituden der>jeweiligen Frequenzkomponenten?
Die Amplitude erhälst du wenn du rechnest (pseudocode):
1
foriloopoverN:
2
amplitude[i]=sqrt(real[i]^2+imag[i]^2);
Drucke das mal aus.
>Wenn ja, woher weiß ich zu welchen>Frequenzen die jeweiligen Amplituden gehören, wenn z.B. der erste Wert>des Feldes 10dB ist, zu welcher Frequenz gehört diese Amplitude?
Der Index im FFT Ergebnis hängt mit der Abtastfrequenz zusammen. Mit
einer Abtastrate von Fs representiert jeder Wert im FFT Ergebnis eine
Bandbreite von Fs/N. Also der Index 0 representiert den
Gleichstromanteil, Index 1 von 0 bis Fs/N, Index 2 von Fs/N bis 2 * Fs/N
usw.
Jetzt ist es so, dass wenn ein Signal mit Fs abgetastet wird, dann ist
die maximale Frequenz Fs/2, die mit den Samples representiert werden
kann. D.h. nur die ersten N/2 Indizes im FFT Ergebnis sind eindeutig.
Nach N/2+1 wiederholt sich das Spektrum spiegelverkehrt. Das solltest du
sehen wenn du die Werte ausdruckst.
>Wenn ich die Werte im Imag-Feld "Null" setze vor der FFT, habe ich denn>später meine Amplituden direkt im Real-Feld?
Nein, siehe oben, du benötigst Real und Imaginär Daten und musst die
Amplitude daraus erst errechen.
Hallo,
ich habe nun ein Grafikdisplay am µC angeschlossen, um das Spektrum
darstellen zu können. Leider sind die dort dargestllten Amplituden zu
den jeweiligen Frequenzen überhaupt nicht konstant. Man merkt zwar, dass
wenn man den Geräuschpegel anhebt, auch die Amplituden der
Frequenzanteile größer werden, aber diese schwanken sehr stark. Ich habe
auch bereits mit einem Tongenerator verschiedene Sinusfrequenzen
dasrstellen lassen, aber auch in diesem Fall erhöhen sich sehr viele
Frequenzanteile, und nicht nur ein bestimmter.
Ich übergebe der FFT Funktion das Real Array mit den vom ADC Wandler
gemessenen Werten und multipliziere diese denn mit 32,also mit maximal
32768 (1024 * 32) und das Imag Array fülle ich wie oben schon mal
beschrieben mit Nullen. Liegt der Fehler vielleicht in der Übergabe des
Real Feldes?
Ich taste das Analogsignal mit 5 kHz ab.
Hat schon mal jemand die von mir benutzte FFT erfolgreich auf einem µC
getestet?
Wenn mir noch mal jemand bei meinem Problem helfen könnte wäre ich sehr
dankbar, schon einmal vielen Dank im voraus!
Hi,
im Kommentar steht
"
For the forward FFT (time -> freq), fixed scaling is
performed to prevent arithmetic overflow, and to map a 0dB
sine/cosine wave (i.e. amplitude = 32767) to two -6dB freq
coefficients; the one in the lower half is reported as 0dB
by fix_loud(). The return value is always 0.
"
ich nehme an dein AD Wandler löst zu 10bit auf.
Dann multiplizierst Du mit 32 mit dem Gedanken
die fixpoint Range von -1.0 bis 1.0 auszufüllen.
Allerdings bin ich mir nicht sicher, dass es nötig ist.
Wie es im Kommentar steht, muss fix_fft Funktion sicher
gehen, dass das Ergebnis wieder in range -1.0 bis 1.0 passt.
Rein theoretisch sollte es für deine Zwecke egal sein, da
Fouriertransformation linear ist. Also es gilt immer
x(t) o-o X(f)
a*x(t) o-o a*X(f)
Man verändert theoretisch nur die Signalenergie. Die wird
dann um den Faktor a^2 grösser als ursprunglich.
Was mir noch in den Kopf gekommen ist ...
Du tastest mit 5kHz, das heisst im Klartext, dass
deine Signalquelle keine Signalanteile mit Frequenzen
über 2.5kHz enthalten darf.
Wenn sie es doch tut (zb Du sprichst in mikro), dann
werden Signalanteile mit Frequenz grösser 2.5kHz
sich für "falsche Frequenzen" ausgeben.
Zb würde sich eine im Signal vorhandene Schwingung mit f0=5kHz
für die Frequenz 0 ausgeben. Ergo wäre damit X(0) nicht mehr
eindeutig. Und das weil die 5kHz Abtastung immer auf
gleiche Phasenlage der 5kHZ Schwingung trifft.
Diesen Effekt nennt man Aliasing.
Um es loszuwerden am besten Tiefpass einbauen, der
alle Anteile über 2.5kHz unterdrückt. Dann wirkt
sich Aliasing nicht mehr so stark aus.
Ich hab mal eine gute Anschauung für Aliasing im Netz gelesen.
Man stelle sich ein Rad, dass 30 mal in der Sekunde sich dreht.
Das ganze wird mit einer Kamera aufgezeichnet, die 30
Bilder in der Sekunde macht. Das Rad "steht" dann.
Man kann nicht unterscheiden ob das Rad wirkllich steht
oder sich mit 30,60,90... Umdrehungen pro Minute dreht.
Genauso 1 und 31 Umdrehungen. Hier wird halt <die Welt>
mit der Frequenz 30Hz abgetastet.
Kannst du eventuell Foto oder kleines Video uploaden?
Es würde mich interessieren wie das ganze dann aussieht.
Gruss, Daniel
Hallo,
ich habe jetzt mal ein kleines Video von der FFT Ausgabe auf dem Display
gedreht bei einer am Tongenerator eingestellten Frequenz von 500Hz. Man
kann gut erkennen dass die FFT wohl noch nicht richtig funktioniert. Es
erhöhen sich zwar die Amplituden verschiedener Frequenzen wenn man einen
Ton erzeugt, aber diese Amplituden sind total willkürlich und haben
nichts mit der vom Tongenerator erzeugten Frequenz zu tun. Es ist auch
egal welche Frequenz ich erzeuge, die auf dem Display dargestellten
Frequenzen sehen immer sehr ähnlich aus wie in dem Video.
Einen Tiefpass habe ich auch schon in der Schaltung eingebaut, er
schneidet mir alle Frequenzen über 2,5 kHz weg, da die Frequenzen die
ich aufnehmen möchte um einiges kleiner sind. Hat jemand vielleicht eine
Idee was ich falsch machen könnte?
Wenn ich die FFT mit einem Array füttere das ich selber mit Nullen
gefüllt habe scheint die FFT korrekt zu funktionieren, sie zeigt
zumindest keine Frequenzanteile an. Ich habe das Array auch schon mal
mit einem konstanten Wert beschrieben, denn zeigte mit das Display nur
einen Gleichanteil an, dies ist ja ebenfalls korrekt?!
Hat jemand vielleicht eine Idee?
Das mit dem Hochladen vom Video hat wohl leider nicht funktioniert, aber
wenn es jemand haben möchte kann er mir gerne seine emailadresse geben,
denn schicke ich es per mail
meine addy ist ed.xmgATleinaday
AT = @
und rückwärts geschrieben (wegen spambekämpfung)
ich würde mir das Video gerne anschauen
>Wenn ich die FFT mit einem Array füttere das ich selber mit Nullen>gefüllt habe scheint die FFT korrekt zu funktionieren, sie zeigt>zumindest keine Frequenzanteile an. Ich habe das Array auch schon mal>mit einem konstanten Wert beschrieben, denn zeigte mit das Display nur>einen Gleichanteil an, dies ist ja ebenfalls korrekt?!
Richtig.
Wenn beide real/imag Arrays mit Nullen gefüllt sind, dann
sollte nichts angezeigt werden.
Wenn real Array nur mit einem konstanten Wert gefüllt ist, dann
müsste nur der Gleichanteil angezeigt werden.
>Hat jemand vielleicht eine Idee?
das mit Tiefpass hat sich erledigt.
Interessenhalber wie hast du ihn implementiert?
Bleiben dann meiner Meinung nach die fixpoint Zahlen
und der Algorithmus selber.
Den Algorithmus könnte man auf dem PC testen.
Ich probiere das mal heute Abend.
Achso was ich komplett vergessen habe :)
Vielleicht ist das der Leckeffekt.
Wenn man die Abtastfrequenz konstant hält
und diese auch Nyquesttheorem erfüllt, dann
bekommt man für ein Zeitsignal von 1 Minute
in deinem Fall 5000 Samples.
Wenn man diese auf einmal der FFT unterzieht, dann
ergibt sich was anderes als wenn man 128 Samples
stückchenweise der FFT unterzieht.
N ist dann wie eine Fensterfunktion die durch
1 Minute Zeitsignal geschoben wird.
128/5e3 => 0.0256
0.0256 Sekunden Fenster sozusagen.
Hmm, mein Buch sagt
auflösungsFrequenz = 1/Beobachtzeit = 39.0625 Hz
Wieviel Balken hat dein Display für die Darstellung
der Frequenzklassen?
Aber alles in allem 39 ist "fein" genüg.
Wenn es 10 Balken sind, für Frequenzen 0 bis 500
dann dürften im worst case nur 2 von denen sich erheben.
f_auflösung = 1/Beobachtzeit = f_abtast/N
N grösser machen oder fabtast kleiner sollte f_auflösung
feiner machen. Aber je feiner desto mehr Balken sollte
Display bieten.
Das ist im Moment alles was mir einfällt.
Gruss, Daniel
Hallo,
ich wollte mal fragen ob vielleicht jemand einen FFT Code hat den er
selber schon erfolgreich getestet hat und mir empfehlen kann? Ich würde
mich sehr über eine Antwort freuen.
> Wenn ich die FFT mit einem Array füttere das ich selber mit Nullen> gefüllt habe scheint die FFT korrekt zu funktionieren, sie zeigt> zumindest keine Frequenzanteile an. Ich habe das Array auch schon mal> mit einem konstanten Wert beschrieben, denn zeigte mit das Display nur> einen Gleichanteil an, dies ist ja ebenfalls korrekt?!> Hat jemand vielleicht eine Idee?
Versuche doch mal das Array mit einer Wechselgröße zu belegen. Also
fülle z.B. 1/4 mit dem Wert 5000, das nächste 1/4 mit -5000, dann wieder
mit 5000, etc.
Dann solltest du erst mal eine stehendes Bild auf deinem Display
erhalten.
Eine gute Sache währe auch mal den Code einfach auf dem PC zum laufen zu
bringen, da du dann mehr Zugriffsmöglichkeiten hast.
Auf jeden Fall solltest du kontrollieren wie groß deine Daten sind die
in die FFT rein gehen. Wenn ich den Code richtig verstehe, dann müssen
die im Bereich -32768...32767 sein.
Kannst du vielleicht die Daten die in die FFT rein sollen mal auf dem
Display ausgeben? Dass sollte dir zeigen ob das Signal überhaupt einen
Sinn macht oder ob am FFT Eingang schon nur rauschen anliegt.
Ich habe mir den Code mal genauer angeschaut und meines Erarchtens ist
das Problem die Skalierung die in jedem Rank durchgeführt wird um einen
Überlauf zu vermeiden. Für kleinere Signale kann das ein Problem sein
und sie werden praktisch weg skaliert, so das am Ausgang nur noch
Rauschen ankommt.
Da die Skalierung in der FFT fest ist und in jedem Rank durchgeführt
wird, musst du also sicher stellen das dein Eingangssignal genug groß
ist damit es nicht weg skaliert wird.
Vielleicht würde es Sinn machen eine automatische Verstärkungskontrolle
der FFT vor zu schalten. Also du misst die Energie von den letzten N
Samples und passt dann jeden Sample der in die FFT geht entsprechend dem
Wert an.
Hallo Kluntje,
wenn Du Signale abtastest, deren Periode(n) nicht genau in Deinen
Samplebuffer passen, bekommst Du immer Artefakte durch das Abschneiden
des Signals. Um das zu umgehen, kann man das Signal mit einer
"Windowing" Funktion multiplizieren. Sie dämpft Deine Samples am Anfang
und am Ende etwas, so daß der Einfluß dieser Samples auf das Ergebnis
geringer ist. Typische Windowing-Funktionen sind Hamming und Hanning.
Ich probiere gerade die FFT von elm-chan aus
(http://elm-chan.org/works/akilcd/report_e.html) und bin recht
begeistert ob der Geschwindigkeit. Dort ist diese Windowing-Funktion
bereits eingebaut, und Du solltest schnell zum Ziel kommen.
Gruss
Hans-Christian
Hallo,
und noch mal vielen Dank für eure Hilfe! Ich habe jetzt auch den FFT
Code von ELM-CHAN in meinem µC gebrannt, es funktioniert wirklich
hervorragend!
Viele Grüße
Kluntje