www.mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP FFT auf Atmega8


Autor: Kluntje (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Alban (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Kluntje (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Alban (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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):
for i loop over N:
  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.

Autor: Kluntje (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Alban, vielen Dank für deine Hilfe, du hast mir sehr geholfen! 
Dankeschön!

Autor: Kluntje (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Kluntje (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Kluntje (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Kluntje (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich probiers mal mit nem Foto...

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Kluntje (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Alban (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Alban (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Hans-Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Kluntje (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

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.