mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP Skalierung auf Int bei einer FFT (128-Punkte)


Autor: tiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ich hab da glaub ich ein kleines Verständbisproblem beim skalieren 
auf Int Werte bei einer FFT.

Also ich habe eine FFT implementiert, die mit float zahlen auch richtig 
rechnet. Nun möchte ich diese auf Int "umbauen".
Ich bekomme vom ADC 12-Bit Zahlen, im Bereich von 2047 bis -2048.
Diese werden entsprechend umsortiert und gehen dann in den FFT 
Algorithmus.
Ein Int Wert ist auf meinem µC 16 Bit (MSP430).
Als Int Werte werden die ADC-Zahlen in eine 16-Bit Variable gespeichert.
Da die Werte der "Twiddlefaktoren" zwischen -1 und 1 liegen müsste ich 
diese skalieren. Ich kann diese dann doch mit 2^15 skalieren und dann 
nach jeder Multiplikation mit dem Hardware-Multiplizierer (16-bit *16 
bit) nur das Higher Word (also die oberen 16 Bit) des Ergebnisses für 
die weitere Berechnung nutzen oder verstehe ich das falsch? Wenn ich 
noch eine Fensterfunktion einsetze kann ich doch analog vorgehen oder?

: Verschoben durch Admin
Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hängt vom Format ab, das du wählst.

Deine Zahlen sind 13 Bit signed, also im 1.12 signed Q-Format. Um das in 
16 Bits einzubetten hast du 4 mögliche Positionen für den Dezimalpunkt, 
d.h. du hast die Wahl zwischen
1.15
2.14
3.13 und
4.12

1.15 bringt dir die maximale Genauigkeit an Nachkommastellen. ALlerdings 
ist zu bedenken, daß auch Überläufe aufteten könnten. So ist -1 = 0x8000 
= -0x8000 = -(-1) weil 1 = -1 ist.

Daher ist es u.U. günstiger, 2.14 zu wählen oder 4.12 wenn es um 
Effizienz geht. Da 2.14*2.14 = 4.28 ergibt sich der Ergebnis einer 
Multiplikation aus den oberen 16 Bit nach einem Linksshift um 2. Analog 
ergibt sich das Ergebnis bei 4.12*4.12 = 8.24 aus dem High-Word nach 
einem L-Shift um 4 und bei 1.15*1.15 = 2.30 nach einem L-Shift um 1.

Johann

Autor: tiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Als muss ich auch an den adc werten skalieren und nicht nur an den 
Twiddlefaktoren? Diese würde ich mit 2^15 erweitern, dann hätte ich ja 
das 1.15 Format richtig?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tiffy schrieb:
> Als muss ich auch an den adc werten skalieren und nicht nur an den
> Twiddlefaktoren? Diese würde ich mit 2^15 erweitern, dann hätte ich ja
> das 1.15 Format richtig?

Ja. Wobei die Berechnung der 128-ten Einheitswurzeln und deren 
Skalierung mit 2¹⁵ zur Compilezeit (oder vorher) geschehen kann, also 
nicht auf dem µC berechnet werden muss.

Johann

Autor: tiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja über look-up tabel dann halt. Könnte ich dir evtl. mal den Code 
schicken den ich bis jetzt habe? Kan ihn hier natürlicha uch posten. Ich 
bin mir nämlich nicht ganz sicher, wie ich das Ergebnis so zu 
interpretieren habe.

Autor: bingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich nix an den Eingangswerten aus dem ADC aendere, also sie einfach 
so in eine 16 bit int variable speicher, und diese anschliessend mit der 
mit 2^15 skalierten Zahl (dem twiddlefaktor) multipliziere bekomme ich 
dann als Ergebnis eine 2.30 Zahl ?

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tiffy schrieb:

> Als Int Werte werden die ADC-Zahlen in eine 16-Bit Variable gespeichert.
> Da die Werte der "Twiddlefaktoren" zwischen -1 und 1 liegen müsste ich
> diese skalieren. Ich kann diese dann doch mit 2^15 skalieren und dann
> nach jeder Multiplikation mit dem Hardware-Multiplizierer (16-bit *16
> bit) nur das Higher Word (also die oberen 16 Bit) des Ergebnisses für
> die weitere Berechnung nutzen oder verstehe ich das falsch?

Was Du sagst ist richtig, Du verlierst natürlich Genauigkeit, i.e. Dein 
Rauschfloor geht hoch, aber das geht so.

Was nicht geht: Du kommst mit 12Bit Zahlen rein und machst eine 128er 
FFT, entsprechend 7 stages des Algorithmus. In jeder stage gewinnst Du 
maximal 1 Bit hinzu, selbst wenn Du die twiddle Faktoren skalierst, hast 
Du als Ergebnis der FFT 12+7 = 19 Bit Werte, die passen nicht in 16Bit 
Variablen rein. Der Overflow ist aber signalabhängig, breitbandiges 
Signal macht breitbandiges Spektrum, also nix mit Spitzen, Sinus macht 
einen peak, der zum Overflow führt. Entweder 32Bit rechnen oder 
dynamisch skalieren: runtershiften, wenn Overflow droht.

Cheers
Detlef

Autor: tiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um dem vorzubeugen werden die Eingangsgroessen in jeder Stufe halbiert. 
Ich kanns ja m,al posten:
MPYS = (eingangsvektor_real[q]);
        OP2 = W_faktoren_128_real[W_exponent];
        MACS = -(eingangsvektor_imag[q]);
        OP2 = W_faktoren_128_imag[W_exponent];
        buffer_real = (RESHI);                         //dies entspricht der Haelfte des Ergebnisses der eigentlichen
                                                       //Multiplikation -->(Q_real*W_real-Q_imag*W_imag)/2
  
        MPYS = (eingangsvektor_real[q]);
        OP2 = W_faktoren_128_imag[W_exponent];
        MACS = (eingangsvektor_imag[q]);
        OP2 = W_faktoren_128_real[W_exponent];
        buffer_imag = (RESHI);                         //dies entspricht der Haelfte des Ergebnisses der eigentlichen
                                                       //Multiplikation -->(Q_real*W_imag+Q_imag*W_real)/2
        
        eingangsvektor_real[q] = ((eingangsvektor_real[p] >>1) - buffer_real);  //Q_real'=Q_real/2 - (Q_real*W_real-Q_imag*W_imag)/2
        eingangsvektor_imag[q] = ((eingangsvektor_imag[p] >>1) - buffer_imag);  //Q_imag'=Q_imag/2 - (Q_real*W_imag+Q_imag*W_real)/2
        eingangsvektor_real[p] = ((eingangsvektor_real[p] >>1) + buffer_real);  //P_real'=P_real/2 + (Q_real*W_real-Q_imag*W_imag)/2
        eingangsvektor_imag[p] = ((eingangsvektor_imag[p] >>1) + buffer_imag);  //P_imag'=P_imag/2 + (Q_real*W_imag+Q_imag*W_real)/2
so sieht bei mir die berechnung eines butterfly aus.

Autor: tiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist aus engelehnt an einem application note von ti (SLAA042)

Autor: tiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und jemand ne meinung dazu?

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tiffy schrieb:
> Und jemand ne meinung dazu?
Das verschenkt jede Menge Genauigkeit. Ich weiß nicht, was Du willst und 
Dir leisten kannst: Schnelle Berechnung mit hohem eingeschlepptem 
Rauschen oder langsamer und genauer oder irgendwas dazwischen.

Cheers
Detlef

Autor: tiffy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sehr genau muesste es im Prinzip nicht sein, kann man den Fehler den man 
sich einheimst irgendwie beziffern?

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sicher gibts Aussagen zur Genauigkeit und Fehlerfortpflanzung in 
integer-FFTs, konkrete Literatur ist mir aber nicht bekannt. Ich würds 
einfach in C auf einem PC ausprobieren.

Cheers
Detlef

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.