Ich versuche schon seit Tagen das Beispielprogramm von Microchip zum Laufen zu bekommen. Ich habe das Programm ein wenig aufgeräumt und übertrage die Kurvenform (im Moment ein einfacher Sinus von 0-5kHz, 10kHz Samplerate) vom PC zum dsPIC und das Ergebnis vom dsPIC geht zurück zum PC wo die Werte grafisch dargestellt werden. Das Hamming Fenster passt noch, auch die Umsortierung der Werte in Komplexe Werte müsste noch OK sein. Das Ergebnis der FFT ist aber nicht so ganz das was ich von einem Sinus erwarte. Wenn ich die Frequenz von 0-5kHz durchlaufen lasse, müsste eigentlich eine Spitze von links nach rechts laufen, aber die Spitzen springen hin und her, und es sind immer mehrere große und eine Menge kleiner Spitzen.
Ich habe den Code jetzt nich angesehen, aber folgendes: Die zwei Spitzen beim Sinus erkennst du nur, wenn deine Abtastrate ein ganzes Vielfaches der Sinus Frequenz ist (=> kohärente Signalverarbeitung), sonst geht das bei der Transformation nicht auf, und du kriegst mehrere Spitzen. Also für 1kHz, 2kHz, 5kHz usw. sollte es stimmen, bei 1.5kHz kriegst du nicht das ideale Spektrum. Hat mit der Fensterung und der darauffolgenden Abtastung an falschen Stellen zu tun, siehe zB picket-fence-effect. Wenn es für ein 1kHz Signal immer noch nicht funktioniert, kann das folgende Gründe haben: Abtastrate und Signalfrequenz sind leicht asynchron, das kann dann immer noch schweinerein geben. Oder aber dein Algorithmus ist falsch.
Sollte die Fensterung vor der FFT diese Probleme nicht beheben ? Ich habe schon mit anderen FFT Algorithmen gearbeitet, da hatte ich solche Probleme nie, zumindest nicht in diesem Umfang. Außerdem sind die Werte die aus der FFT herauskommen recht gering: Aus der FFT kommen 16 bit Werte heraus, Werte größer +-400 kommen aber nie raus, selbst bei einem Sinus mit voller Amplitude als Eingangssignal. Der jetzige FFT Algorithmus stammt von Microchip, der sollte also OK sein. Die Schwierigkeit besteht jetzt nur, diesen anzuwenden.
Nein, eine Fensterfunktion beseitigt solche Probleme nicht, sondern verringert lediglich die Energie in den Nebenmaxima und erhöht damit die Ablesbarkeit etwas. Wie gesagt, übertrage mal einen geeigneten Sinus. Also wenn du zB ne 1024 Punkt FFT machst, dann nimm ne Sinus Periodenlänge von 128 oder 256 Punkten. Nur bei solchen geraden vielfachen wirst du nur mit Punkte im Spektrum haben, bei denen die Leistung > 0 ist. Ansonsten gibt es immer ein breiteres Spektrum. Gut wäre es, wenn du das Spektrum deines Signals noch parallel in Matlab oder so berechnen könntest. Dann würdest du sehen, ob dein Pic Programm falsch liegt, oder die Darstellung eben normal ist, aufgrund des Eingangssignals.
Hier mal das Signal (linke 256 Werte) und das Ergebnis (rechte 256 Werte). Das Signal müsste sich periodisch ohne großen Versatz fortsetzen lassen. Das Ergebnis sieht meiner Meinung nach etwas merkwürdig aus.
Hier zum Vergleich mit Matlab. So sieht es schon besser aus. Diesmal sogar ohne Fensterung.
Also am Abbruchfehler liegts damit nicht. Du könntest mal noch ne höhere Amplitude des Signals versuchen, oder auch ne niedrigere. Das könnte helfen wenns am Problem der Rechengenauigkeit oder Übersteuerungen liegt. Ansonsten liegt der Fehler wohl irgendwie im Code. Sehe dort nix auffälliges, habe aber auch keine Ahnung vom dspic
Danke für die Hilfe. Anscheinen sind die dsPICs nicht wirklich weit verbreitet. Die Amplitude habe ich auch schon verändert, aber auch das bringt nichts.
Hallo ich bin auch nicht der dsPIC/DSP - Profi, aber müssen die Daten, die in die FFT geschickt werden, nicht vom Typ "fractional" sein ? Ich kann nicht erkennen, von welchem Typ deine Daten sind. Gerhard
Die Daten sind Fractional Complex (es sind globale Variablen, stehen zwischen main und den Kommentaren). Diese entsprechen aber int, nur der beim Lesen ist der Wertebereich eben -1...+1 und nicht -32768...+32767. Ist reine Definintionssache.
Hi ich will nicht nerven, aber ich seh nur, dass die Daten über den UART eingelesen werden. Und ich meine, dass ich mal gelesen hab, dass die Daten für die FFT nicht zwischen -1 und +1 liegen dürfen, sondern nur zwischen -0,5 und +0,5. Ich schliesse mich "Aufreger deluxe" an und empfehle das http://forum.microchip.com. Wenn die Leute dort gut drauf sind, helfen Sie dir sogar. Du kannst aber auch mal nach FFT suchen, da gibt vermutlich genug die das gleiche Prob haben. Gerhard
>Und ich meine, dass ich mal gelesen hab, dass die Daten für die FFT nicht
zwischen -1 und +1 liegen dürfen, sondern nur zwischen -0,5 und +0,5.
Richtig, daher multiplizierte ich den 8bit Wert vom UART auch nicht mit
256 sondern nur mit 100 um auf der sicheren Seite zu sein.
Und weshalb kann das UART keine 16bit Werte uebertragen ? Sollte allerdings nicht viel machen. Wenn der Wertebereich nur ein aufgeblasener 8 bit Bereich ist, gibt es mehr Oberwellen. Das waeren dann ganzzahlige Vielfache. uu
Ich verwende nur 8bit Werte, da es einfacher ist und ich so Probleme durch vertauschte High/Low Bytes sicher ausschließen kann.
Hallo Benedikt, ich habe gerade ein ähnliches Problem mit den dsPICs. Ich kann nicht nachvollziehen was in der SquareMagnitudeCplx (...) gerechnet wird. Wenn ich im Simulator das Beispielprogramm von Microchip bis nach dem Aufruf von BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]); laufen lasse und den Absolutwert manuell berechne, bekomme ich das erwartete Ergebnis. ( getestet mit dirac,DC und einer cos- funktion.) Ich habe noch nicht weiter in die SquareMagnitudeCplx () hinein gedebuggt, weil es mir im Moment nicht so wichtig ist. Hole Deine Daten doch mal vor der Betragsbildung ab, es würde mich interessieren ob sich dann das Ergebniss verbessert. Viele Grüsse, reimay
Wenn ich den Betrag am PC aus dem komplexen Daten berechne sieht das Ergebnis genauso aus, wie das Ergebnis von SquareMagnitudeCplx(). Daran liegt es also (zumindest bei mir) nicht. Der Fehler muss also während der FFT oder dem Umsortierten der Bits entstehen. Beim FFT Beispielprogramm, dass die Grundfrequenz herausfindet ist es anscheinend Zufall, dass das richtige Ergebnis rauskommt.
Hallo, diesen Sommer hab ich mit einem dsPICDEM Board "gespielt". Allerdings hab ich auch den A/D und das LCD, die auf dem Board sind, benutzt. Mit der FFT-Function von Microchip hatte ich das Problem, dass das Vorzeichen des imaginären Teils im Ergebnis nicht immer korrekt war. Besser gesagt, das ist kein richtiges Problem, weil SquareMagnitudeCplx() macht sowieso ^2. Zu SquareMagnitudeCplx(): diese Function macht folgendes: Re(x(k))^2 + Im(x(k))^2, also sqrt macht sie nicht, das musst du mit Matlab korrigieren. Ich vermute, dass bei einer Auflösung von 8 Bits (USART) das Quantisierungsrauschen so gross ist, dass das schon in so einem 256 langen FFT zu erkennen ist. Mein Vorschlag: mach mit MATLAB so ein Signal (besser gesagt: einen Vektor), das nur aus ganzen Perioden besteht. So kannst du Leakage vermeiden. Dann lass die Fensterfunktionen aus dem Code raus, mal sehen, was dann passiert. Gruss, Unit*
PS: Leakage kannst du in diesem Fall mit Sicherheit nicht haben, weil dein Programm auf jedes Sample wartet... Also wenn das Inputsignal eine ganze Anzahl von Perioden hat, und es keine Datenverluste geben, ist es unmöglich.
Wenn SquareMagnitudeCplx keine Wurzel zieht, dann passt da irgendwas mit Sicherheit nicht in der FFT Routine: Die Ergebnisse von SquareMagnitudeCplx sind bei mir alle kleiner als 256. Wenn ich daraus noch die Wuzel ziehe, komme ich auf einen Wertebereich von 0-15. Und eine Amplitude von 15 ist definitiv falsch, bei einem Sinus mit maximaler Amplitude als Eingangssignal.
Mit Sicherheit zieht SquareMagnitudeCplx() keine Wurzel. Das kannst du mit dem MPLAB Simulator ausprobieren (Debugger/Select Tool/MPLAB SIM). Der Code dafür: #include <p30Fxxxx.h> #include <dsp.h> fractcomplex in[2] _attribute_ ((section (".ydata, data, ymemory"))) = {0x2000,0x2000}; fractional out[1] _attribute_ ((section (".ydata, data, ymemory"))); int main(void) { SquareMagnitudeCplx(8, in, out); } Nach Build und Run geh auf View/Watch, dort suche "out" aus, dann klicke auf "Add Symbol". Das Ergebnis ("in") ist 0x1000 (two's complement, hexa signed fractional), das gleich 0.125 (Dezimal) ist. Was ich geschrieben habe ist richtig, weil .25^2 + .25^2 = .125. Zu deinem letzten Beitrag: die Größe der Diracs im Spektrum (wenn es kein Leakage gibt) sollten 1/N *A*N/2 = A/2 sein, daher hast du Recht. Aber was für Daten kommen durch den UART? Ich vermute, dass der DSP die Daten aus dem PC (bzw. von MATLAB) ohne Umwandlung bekommt. Wenn das so ist, dann brauchst du "-128" nicht: p_real[i] = ((signed int)(uart_getchar()-128))*100; Das verursacht Unlinearitäten im Signal (two's complement overflow), und harmonics im Spektrum, wie auf fft_dspic.gif An deiner Stelle würde ich folgendes machen: mit MATLAB die Datenkonversion erledigen (der MATLAB rechnet mit signed int, der DSP, bzw die Funktionen brauchen fractional, eine MATLAB Funktion zu schreiben braucht keine Minute), *100 versaut die Vorzeichen (fractional!!!) ich würde *256 schreiben und mit MATLAB die Datengröße limitieren, statt "signed int" kommt "fractional". Benutze zuerst keine Fensterfunktionen (überfüssige Fehlerquelle), die Ergebnisse der FFT ebenfalls mit MATLAB zurückkonvertieren.
So wie ich fractional verstanden habe, ist es nichts anderes als "signed int"/32768. Ein signed int Wert 32767 entspricht somit 0,99996948 und -32768 als fractional interpretiert wäre -1. Beide Zahlenformate sind also gleich, nur auf einen anderen Wert normiert. Oder habe ich das falsch verstanden ? Dann würde ich nämlich auch die Ergebnisse falsch interpretieren was diese Fehler erklären würde.
Du hast es richtig verstanden. Was aber du nicht betrachtest (und der Sinn der ganzen Sache ist), daß two's complement fractional left-justified ist! Das heißt (nehmen wir zB 4 Bits): 1100 0000 (fractbin) = C0 (fracthex) = 1*(-2^0) + 1*2^-1 + 0*2^-2 + 0*2^-3 + ... = -.5 (fractdec) Deswegen sind die beiden Zehlenformate gleich dargestellt, aber anders interprtiert. Der DSP hat nicht die leiseste Ahnung, was fractional ist, *100 macht er mit der Gewißheit, das er mit ganzen Zahlen zu tun hat. zB 80 (fracthex) * 100 (dec) = 3200 (fracthex) = +0.3906 (fractdec) obwohl 80 (fracthex) = -1 (fractdec) ist! Wenn du einfach folgendes machen würdest, wäre dein Problem wahrscheinlich gelöst: mit MATLAB auf fracthex konvertieren, und über den UART schicken, dann im DSP mit 256 multiplizieren (dh << 8). zB.: C0 (fracthex) * 256 (dec) = C000 (fracthex) = -.5 (fracthex) Gruß, Unit*
Hi Ist zwar ein alter post aber vieleicht hilfts mal jemandem. Die twiddlefactors von Microchip sind falsch. diese mal updaten und nochmals versuchen. Benedikt - "Der jetzige FFT Algorithmus stammt von Microchip, der sollte also OK sein." Diese Annahme ist ein schwerwiegender Fehler. Siehe die ganzen errata listen von Microchip...
Wo bekommt man die richtigen twiddlefactors her ? Mir fehlt leider das Wissen um diese selbst zu berechnen.
Je nachdem wieviele Punkte deine DFT/FFT hat musst du den Einheitskreis der komplexen Ebene wie einen Kuchen zerteilen. Beispiel: 4 twiddle-Faktoren aus dem Einheitskreis sind [+1, +j, -1, -j]. Beispiel: 8 twiddle-Faktoren: [+1, 0.7+j0.7, +j, -0.7+j0.7, -1, -0.7-j0.7, -j, 0.7-j0.7]. Mathematisch bedeutet dies: W_N = exp(-j*2*pi/N). pumpkin
Jaja, aber die FFT-Funktion von Microchip will nur die Hälfte dieser Punkte haben (genauer gesagt von n=0 bis n = floor((N-1)/2))!!! Die genaue Berechnung: twid(n) = exp(-j*2*pi*n/N) n = 0 .. N-1 z.B. N = 4: twid(0) = exp(0) = 1 twid(1) = exp(-j*2*pi*1/4) = exp(-j*pi/2) = -j twid(2) = exp(-j*2*pi*2/4) = exp(-j) = -1 twid(3) = exp(-j*2*pi*3/4) = exp(-j*3*pi/2) = +j In disem Fall brauchst du nur twid(0) und twid(1), da der Rest "symmetrisch" ist, nur die Vorzeichen sind umgekehrt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.