Hallo, da ich leider kein DSP Mathematiker bin, such ich mal hier um Hilfe. Ich will für ein kleines Projekt eine Einseitenbandmodulation mit dem IQ-Mischer realisieren. Dazu brauche ich einen Phasenschieber, der das oder die Signale um 90 Grad verschiebt. Nun steht mal so im Raum eine Hilberttransformation, All-pass, IIR oder Ähnliches. Ich habe schon einige IIR-Filter realisiert und auf einem ARM7 umgesetzt. Jetzt steht ein Cortex M4F zur Verfügung, der um einiges schneller ist. Ich habe leider im WEB keine Implementierung dafür gefunden. Nur etliche verzettelte Theorien. Ich konnte bis jetzt nichts brauchbares ableiten. Gerne bin ich dann auch Bereit den Code hier fürs Forum offen zu legen. Programmieren tu ich in Assembler mit FPU oder Fixpoint, je nach.... Frequenzspektrum ca. 200Hz...5KHz Samplefrequenz 22,32,44KHz je nach Quantisierung der ADC-Werte 16Bit Gruß Sascha
Hallo Johannes, ja ganz einfach ich suche nach einem Lösungsweg um einen solchen Phasenschieber programmieren zu können. Gibt es Berechnungsprogramme für die Faktoren? Welche Art von Filter eignet sich dafür am besten? Hat jemand Erfahrung damit? Gruß Sascha
Sascha schrieb: > Gibt es Berechnungsprogramme für die Faktoren? Für eine Hilbert-Transformation braucht man einen FIR-Filter, die Filterkoeffizienten kann man z.B. mit Scilab berechnen, die Funktion heist "hilb()". Die Implementierung eines FIR-Filters auf einen Controller/DSP ist im Prinzip relativ einfach, wenn man schon mal einen IIR-Filter programmiert hat. Eine fertige Implementierung, die man im Internet herunterladen kann, kenne ich allerdings auch nicht. Hier ist ein Beispiel-Skript für Scilab: (Koeffizientenberechnung und Simulation)
1 | L=500; |
2 | t=[0:1:L-1]; |
3 | x=sin(2*%pi*0.02*t); |
4 | |
5 | n=40; |
6 | c_hilb = hilb(n); |
7 | |
8 | z=poly(0, 'z'); |
9 | h=poly(c_hilb, 'z', "coeff")/z^(n-1); |
10 | |
11 | y=flts(x, h); |
12 | x_delay = [zeros(1,n/2), x(1:L-n/2)]; |
13 | clf(); |
14 | plot([x_delay', y']); |
Die Filterkoeffizienten stehen in der Variablen c_hilb. Das sind Fließkommazahlen, für Festkomma-Rechnung muss man die entsprechend normieren und umwandeln.
Hallo Johannes, das ist ja super, werde ich morgen ausprobieren. FIR filter ist kein Problem, kann ich sogar als Fixed Point mit 64 Bit durchlaufen lassen. Oder mit der FPU als 32 Bit IEEE754. Ich habe gerade bei Freescale die AN4265 gefunden, hier gehts zwar um Stromzähler, aber es ist auch eine recht intresannte Vorlage dafür. Habe im Web gesehen das ein FIR Filter mit 64 Taps ausreichend genug ist. Gruß Sascha
Hilbert Filter treten gerne mal als Paar auf, d.h. man nimmt zwei Filter, die zueinander eine Phasenverschiebung von 90° haben. Folgenden hack habe ich mir letztens irgendwo aus dem Netz gezogen, funktioniert sehr gut. hth Cheers Detlef #define FAK (32768) int16_t hilbert_I[32]={ // Inphase Filter Hilbert Transformation (int16_t)(FAK*0.000210129754790+0.5), // inPhase (int16_t)(FAK*0.000435686890851+0.5), // inPhase (int16_t)(FAK*0.001141127330285+0.5), // inPhase (int16_t)(FAK*-0.000474463384430+0.5), // inPhase (int16_t)(FAK*0.003228639378579+0.5), // inPhase (int16_t)(FAK*0.015798773063932+0.5), // inPhase (int16_t)(FAK*0.016068342201175+0.5), // inPhase (int16_t)(FAK*-0.008791323992589+0.5), // inPhase (int16_t)(FAK*-0.023622650882713+0.5), // inPhase (int16_t)(FAK*-0.002444248072844+0.5), // inPhase (int16_t)(FAK*-0.003613471987776+0.5), // inPhase (int16_t)(FAK*-0.082509515298895+0.5), // inPhase (int16_t)(FAK*-0.141251242309150+0.5), // inPhase (int16_t)(FAK*-0.022156774160222+0.5), // inPhase (int16_t)(FAK*0.215723703269164+0.5), // inPhase (int16_t)(FAK*0.295359239543522+0.5), // inPhase (int16_t)(FAK*0.089596245788314+0.5), // inPhase (int16_t)(FAK*-0.177039867952018+0.5), // inPhase (int16_t)(FAK*-0.224961503288498+0.5), // inPhase (int16_t)(FAK*-0.075500361981124+0.5), // inPhase (int16_t)(FAK*0.044102254749162+0.5), // inPhase (int16_t)(FAK*0.036688196782744+0.5), // inPhase (int16_t)(FAK*-0.002005942552907+0.5), // inPhase (int16_t)(FAK*0.007165852803285+0.5), // inPhase (int16_t)(FAK*0.028981111275206+0.5), // inPhase (int16_t)(FAK*0.019579331622486+0.5), // inPhase (int16_t)(FAK*-0.001556043330388+0.5), // inPhase (int16_t)(FAK*-0.006040359426444+0.5), // inPhase (int16_t)(FAK*-0.000887658558481+0.5), // inPhase (int16_t)(FAK*0.000112391232169+0.5), // inPhase (int16_t)(FAK*-0.000530886012554+0.5), // inPhase (int16_t)(FAK*0.000692704968094+0.5)}; int16_t hilbert_Q[32]={ // Quadratur Filter Hilbert Transformation (int16_t)(FAK*0.000692704968094+0.5), // quadraturePhase (int16_t)(FAK*-0.000530886012554+0.5), // quadraturePhase (int16_t)(FAK*0.000112391232169+0.5), // quadraturePhase (int16_t)(FAK*-0.000887658558481+0.5), // quadraturePhase (int16_t)(FAK*-0.006040359426444+0.5), // quadraturePhase (int16_t)(FAK*-0.001556043330388+0.5), // quadraturePhase (int16_t)(FAK*0.019579331622486+0.5), // quadraturePhase (int16_t)(FAK*0.028981111275206+0.5), // quadraturePhase (int16_t)(FAK*0.007165852803285+0.5), // quadraturePhase (int16_t)(FAK*-0.002005942552907+0.5), // quadraturePhase (int16_t)(FAK*0.036688196782744+0.5), // quadraturePhase (int16_t)(FAK*0.044102254749162+0.5), // quadraturePhase (int16_t)(FAK*-0.075500361981124+0.5), // quadraturePhase (int16_t)(FAK*-0.224961503288498+0.5), // quadraturePhase (int16_t)(FAK*-0.177039867952018+0.5), // quadraturePhase (int16_t)(FAK*0.089596245788314+0.5), // quadraturePhase (int16_t)(FAK*0.295359239543522+0.5), // quadraturePhase (int16_t)(FAK*0.215723703269164+0.5), // quadraturePhase (int16_t)(FAK*-0.022156774160222+0.5), // quadraturePhase (int16_t)(FAK*-0.141251242309150+0.5), // quadraturePhase (int16_t)(FAK*-0.082509515298895+0.5), // quadraturePhase (int16_t)(FAK*-0.003613471987776+0.5), // quadraturePhase (int16_t)(FAK*-0.002444248072844+0.5), // quadraturePhase (int16_t)(FAK*-0.023622650882713+0.5), // quadraturePhase (int16_t)(FAK*-0.008791323992589+0.5), // quadraturePhase (int16_t)(FAK*0.016068342201175+0.5), // quadraturePhase (int16_t)(FAK*0.015798773063932+0.5), // quadraturePhase (int16_t)(FAK*0.003228639378579+0.5), // quadraturePhase (int16_t)(FAK*-0.000474463384430+0.5), // quadraturePhase (int16_t)(FAK*0.001141127330285+0.5), // quadraturePhase (int16_t)(FAK*0.000435686890851+0.5), // quadraturePhase (int16_t)(FAK*0.000210129754790+0.5)}; #undef FAK for(k=32;k<128;k++){ x1=0;x2=0; //12Bit+16Bit+5Bit for(m=0;m<32;m++){ x1 += ((int32_t)hilbert_I[m]*(trace[k-m-1]-xy))>>3; x2 += ((int32_t)hilbert_Q[m]*(trace[k-m-1]-xy))>>3; } /* fx1=0.0;fx2=0.0; //12Bit+16Bit*5Bit for(m=0;m<32;m++){ fx1 += ((double)hilbert_I[m]*(trace[k-m-1]-xy)); fx2 += ((double)hilbert_Q[m]*(trace[k-m-1]-xy)); } */ dd[k]= (int16_t)((int32_t)(sqrt((double)x2*x2+(double)x1*x1))>>12); //fdd[k]= sqrt(fx2*fx2+fx1*fx1); //printf("%d %.3f %d\n",k,fdd[k],dd[k]); }
Hallo, ja sieht auch sehr interessant aus, man kann sich sogar die zweite Tabelle einsparen, ist ja nur eine Spiegelung der ersten. Die Faktoren scheinen sehr intressant aufgebaut zu sein, muss ich mal unbedingt testen. Gruß Sascha
Ich habe zum Thema mal Literatur gesucht und diesen Artikel angefangen: http://www.mikrocontroller.net/articles/Hilbert-Transformator_%28Phasenschieber%29_mit_ATmega Es gibt auch IIR-Phasenschieber, die in der Musikelektronik verwendet werden, das kostet weniger Aufwand als die bekannteren FIR-Filter.
Christoph Kessler (db1uq) schrieb: > Ich habe zum Thema mal Literatur gesucht und diesen Artikel angefangen: Das ist ein sehr interessanter Artikel, da habe ich einige noch dazu gelernt. Danke für den Hinweis.
Ja, der Artikel ist sehr Interessant, nur mit IIR-Filter bin ich noch etwas vorsichtig, da wie auch im Artikel zu lesen ist schwingt die Sache. Es ist sicherlich einfacher mit einem IIR-Filter einen wirksamen Tiefpassfilder zu bauen, aber Phasenshieber mit IIR sehe ich immer sehr kritisch. Aber ich arbeite mich stetig an das Thema heran. Folgende Anforderungen habe ich jetzt auch ausfindig machen können: Der Phasenfehler muss (sollte) unter 1 Grad liegen, der Amplitudenfehler sollte bei 1dB liegen. Das müsste doch zu schaffen sein. Gruß Sascha
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.