Forum: Digitale Signalverarbeitung / DSP / Machine Learning Phasenschieber 90 Grad


von Sascha (Gast)


Lesenswert?

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

von Johannes E. (cpt_nemo)


Lesenswert?

Und was genau ist jetzt deine Frage?

von Sascha (Gast)


Lesenswert?

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

von Johannes E. (cpt_nemo)


Lesenswert?

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.

von Sascha (Gast)


Lesenswert?

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

von Detlef_A (Gast)


Lesenswert?

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]);
}

von Sascha (Gast)


Lesenswert?

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

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

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.

von Johannes E. (cpt_nemo)


Lesenswert?

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.

von Sascha (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.