Hallo,
ich beschäftige mich gerade mit der FFT-Implementierung auf einem ARM
Cortex-M3. Dazu verwende ich die CMSIS-DSP Bibliothek und habe mich für
die Festkomma-Implementierung entschieden (konkret das Q15-Format).
Über einen 10-Bit-ADC lese ich ein Sinussignal ein. Das Ergebnis wird um
fünf Stellen nach links geschoben, damit möchte ich erreichen, dass der
Maximalwert des ADC dem Maximalwert des Q15-Formats entspricht (ist
nicht ganz korrekt, weil Nullen nachgeschoben werden, aber zumindest nah
dran).
Die Implementierung an sich läuft soweit, ich bekomme plausible
Ergebnisse (soweit ich das beurteilen kann). Ich will das ganze auch
noch separat nachrechnen, damit ich das komplett nachvollziehen kann.
Umgekehrt interessiert mich aber, ob ein FFT-Bin des Ergebnisses
überhaupt den Maximalwert des Festkomma-Datentyps erreichen kann. Beim
DC-Anteil (Bin 0) ist das m.E. der Fall, wenn eben der ADC permanent am
Anschlag ist, aber wie schaut das bei den die Frequenzen angebenden Bins
aus?
Kann man denn aus dem Maximalwert bzw. der maximalen Skala der
Eingangssignale den resultierenden Maximalwert der FFT-Ausgabe
berechnen? Das wäre z.B. nützlich, wenn man das ganze grafisch auf einem
Display darstellen möchte, damit man das obere Ende kennt und passend
"zoomen" kann.
Ralf
Nachtrag:
Ich hab das grad mal durchgerechnet, anhand einer kleinen FFT mit 8
Eingangswerten, jeweils 1+0i. Ich komme im ersten Bin auf 8, alle
anderen 0.
Was heißt das nun bezogen auf einen Festkomma-Datentyp? Im Q15-Format
kann man 8 ja nicht darstellen. Heisst das, dass ich das Ergebnis
eigentlich noch durch 8 ( = Anzahl der Samples) teilen muss? Im
Q15-Format also um drei Stellen nach links schieben?
Ralf
>>>dass der Maximalwert des ADC dem Maximalwert des Q15-Formats entspricht
Ja, dann bekommst Du einen overflow, wie Du mit deinem 1+0*i Beispiel
auch gesehen hast. Eine FFT der Länge 2^n hat n 'stages' und von stage
zu stage gewinnst Du ein Bit hinzu. Bei Q15 hast Du 15Bit Dynamik, ne
1024er FFT macht Dir 9 Bit (oder 10 hm?) hinzu, Du darfst also maximal
mit 6Bit ADC Werten reingehen. In jeder stage machst du auch die cos/sin
Multiplikationen, das ist bei der nötigen Rechendynamik ebenfalls zu
berücksichtigen.
Das ganze ist auch signalabhängig: Dein reiner 'DC' versammelt sich
natürlich im ersten bin, ein reiner Sinus in einem einzigen bin.
Breitbandiges Rauschen verteilt sich auf alle bins, da hat mein keine
'peaks' im Frequenzbereich und kommt nicht so nahe an die Grezen des
Zahlenbereichs.
Wie die von Dir benutzte 'Bibliothek' das macht weiss ich nicht. Es gibt
auch Implementationen, die kucken in jeder stage ob sie an der
Aussteuerungsgrenze sind und renormalisieren.
Pi mal Daumen: m Bit ADC, 2^n Bit FFT Länge
Bitbreite =m+n+2 Sicherheitsbit, Vorzeichen ist ggf auch noch ein Bit.
Beim Rechnen der Sin/Cos auch nicht allzu viel stutzen: 15Bit*15Bit plus
Summe sind 31Bit, die möglichst wenig abschneiden, also nicht wieder
auch 15 Bit runternormieren, sonst Rauscht die Geschichte.
Cheers
Detlef
Hi Detlef,
>> dass der Maximalwert des ADC dem Maximalwert des Q15-Formats>> entspricht> Ja, dann bekommst Du einen overflow, wie Du mit deinem 1+0*i Beispiel> auch gesehen hast. Eine FFT der Länge 2^n hat n 'stages' und von stage> zu stage gewinnst Du ein Bit hinzu. Bei Q15 hast Du 15Bit Dynamik, ne> 1024er FFT macht Dir 9 Bit (oder 10 hm?) hinzu, Du darfst also maximal> mit 6Bit ADC Werten reingehen. In jeder stage machst du auch die cos/sin> Multiplikationen, das ist bei der nötigen Rechendynamik ebenfalls zu> berücksichtigen.
Okay, ich verwende eine 256er FFT, also könnte ich auch auf Q31 gehen.
Das heisst aber dann, dass ich das Eingangssignal nicht schieben sollte.
Wie sorgt man dann dafür, dass das ganze "gescheit" auf einem Display
angezeigt werden kann? Den Bin mit dem höchsten Wert ermitteln und
darauf zoomen?
Aktuell mach ich das so, dass ich den Maximalwert auf den
Displaybereich, den ich vorgesehen habe umrechne. Nur erreichen die Bins
dann gerade mal etwa 20% Ausschlag (Testsignal Sinus, Offset 0.5,
Amplitude 0.5).
Deswegen auch die Frage, unter welchen Bedingungen denn eigentlich der
Maximalwert erreicht wird.
> Das ganze ist auch signalabhängig: Dein reiner 'DC' versammelt sich> natürlich im ersten bin, ein reiner Sinus in einem einzigen bin.> Breitbandiges Rauschen verteilt sich auf alle bins, da hat mein keine> 'peaks' im Frequenzbereich und kommt nicht so nahe an die Grezen des> Zahlenbereichs.>> Wie die von Dir benutzte 'Bibliothek' das macht weiss ich nicht. Es gibt> auch Implementationen, die kucken in jeder stage ob sie an der> Aussteuerungsgrenze sind und renormalisieren.>> Pi mal Daumen: m Bit ADC, 2^n Bit FFT Länge>> Bitbreite =m+n+2 Sicherheitsbit, Vorzeichen ist ggf auch noch ein Bit.>> Beim Rechnen der Sin/Cos auch nicht allzu viel stutzen: 15Bit*15Bit plus> Summe sind 31Bit, die möglichst wenig abschneiden, also nicht wieder> auch 15 Bit runternormieren, sonst Rauscht die Geschichte.
Die Sin/Cos Werte werden auch von der Lib zur Verfügung gestellt. Ich
vermute mal, dass Sättigung da durchaus beachtet und korrigiert wird.
Ralf
Hi,
10Bit ADC, 256er FFT sind 18+x Bit, da passt dann Q31.
>>>
Deswegen auch die Frage, unter welchen Bedingungen denn eigentlich der
Maximalwert erreicht wird.
<<<<
Wenn sich alles in einem bin versammelt, also bei einem Sinus der
richtigen Frequenz.
Anzeige: Muss Du entscheiden, entweder feste Skalierung und schlechte
Aussteuerung oder variable Skalierung und immer bis zum Anschlag
ausgesteuert. Das ist Geschmacksfrage.
Wird schon.
Cheers
Detlef
Hi Detlef,
> 10Bit ADC, 256er FFT sind 18+x Bit, da passt dann Q31.
Danke erstmal für die Erläuterung ganz oben, das war mir erst gar nicht
richtig bewusst, dass sich das pro Stufe aufaddiert.
>> Deswegen auch die Frage, unter welchen Bedingungen denn eigentlich der>> Maximalwert erreicht wird.> Wenn sich alles in einem bin versammelt, also bei einem Sinus der> richtigen Frequenz.
Ich glaub ich hab die Frage falsch formuliert: das o.g. ist klar, die
Frequenz mit der höchsten Amplitude ergibt den höchsten Wert für einen
Bin. Meine Frage bezog sich darauf, wann der Maximalwert des Datentyps
(also Q15 bzw Q31) erreicht wird bzw ob das überhaupt geht. Das mit dem
Schieben muss ich nochmal schauen, wie dann bei meiner aktuell festen
Skalierung das Ergebnis aussieht. Wenn es dann immer noch "nix" ist,
dann werd ich vielleicht doch auf variable Skalierung gehen.
Muss ich bzgl der Schieberei noch etwas beachten -> dass ich mit rein
reellen Werten in die FFT gehe, spielt ja keine Rolle, oder? Nicht dass
dann auch noch Auswirkungen hat.
> Anzeige: Muss Du entscheiden, entweder feste Skalierung und schlechte> Aussteuerung oder variable Skalierung und immer bis zum Anschlag> ausgesteuert. Das ist Geschmacksfrage.
Ja, ich glaub dazwischen gibt's nix =)
> Wird schon.
Japp, vielen Dank für die bisherige Hilfe.
Ralf
Hi,
ich habe mal in meinen Archiven gestöbert und angehängten Code zu einer
16 Bit integer-FFT gefunden, Zwischenergebnisse in 32 Bit. Die
FFT-Längen von 2^5 - 2^10 sind abgedeckt. Die FFT macht die oben
erwähnte dynamische Skalierung: Drht Overflow wird renormiert.
Das ist kein Hexenwerk, statt mich mit den Tücken von 'Bibliotheken' zu
befassen programmier ich sowas lieber selber, das steht in jedem
halbwegs fitten Lehrbuch.
Cheers
Detlef