Forum: Analoge Elektronik und Schaltungstechnik Goertzel Phasenbestimmung


von Detlef (Gast)


Lesenswert?

Hallo,
hat jemand eigentlich schon mal die Phase eines Sinus über Goertzel 
richtig berechnet? Die Amplitude bekomme ich genau hin doch die Phase 
ist immer Mist. Ich habe mich genau an diese Vorschrift gehalten.
http://www.eetimes.com/design/embedded/4024443/The-Goertzel-Algorithm
Gruß D.

von Holger (Gast)


Lesenswert?

Das wird Dir ohne weitere Infos niemand beantworten können.

Warum meinst Du ist die Phase nicht OK? Wie stellt sich das Problem 
genau dar?

Berechnest Du kontinuierlich, oder blockweise?

Wie sieht Dein Code aus?

von Detlef (Gast)


Angehängte Dateien:

Lesenswert?

Ich berechne Blockweise. Nach der Berechnung stimmt der Betrag der 
Amplitude exakt mit dem Sinus überein. Die Phase hat jedoch einen 
konstanten Fehler in Abhängigkeit der Blocklänge und der Abtastzeit.

von holger (Gast)


Lesenswert?

>Nach der Berechnung stimmt der Betrag der
>Amplitude exakt mit dem Sinus überein. Die Phase hat jedoch einen
>konstanten Fehler in Abhängigkeit der Blocklänge und der Abtastzeit.

Was willst du mit der Phase? Soweit ich Goertzel und FFT
verstanden habe kann man damit feststellen ob eine Frequenz
in den Samples vorhanden ist. Man kann auch feststellen mit welchem
Energieinhalt. Man kann nicht feststellen zu welchem Zeitpunkt
sie in den Samples vorhanden ist. Sie kann in der ersten Hälfte
der Samples mit sehr hohem Pegel vorhanden sein und in der
zweiten gar nicht. Wenn sie über alle Samples mit halber Amplitude
vorhanden ist bekommst du das gleiche Ergebnis. Eine Phase kannst du
damit nicht feststellen. In Bezug auch was auch?

von holger (Gast)


Lesenswert?

>In Bezug auch was auch?

In Bezug auf was auch?

von Holger (Gast)


Lesenswert?

Natürlich kann man mit FFT, Goertzel oder SDFT Algorithmen die Phase 
bestimmen.

@Detlef: Ist der Fehler zufällig ein Vielfaches von "pi"?



<der Holger mit Grossbuchstaben>

von Detlef (Gast)


Lesenswert?

Holger schrieb:
> @Detlef: Ist der Fehler zufällig ein Vielfaches von "pi"?

Ja, danke! Die atan-Berechnung benötigt noch die Korrektur um pi. Das 
war aber nicht der Fehler. Der korrekte Amplitudenwert ist gegenüber den 
korrekten Phasenwert genau um ZWEI Abtastschritte verschoben.

von Holger (Gast)


Lesenswert?

Wieviel Werte shcibest Du denn rein und welche Frequenz interessiert 
dich?

von Alex (Gast)


Lesenswert?

Hi

ich verwende den G. zum Berechnen von Phase und Amplitude und hab keine 
Probleme.
Es geistern aber im Netz aber einige falsche Implementierungen herum.

Häufig hakt es an folgenden Umständen:

- die Speicher-Zellen müssen vor dem Starten mit 0 initialisiert sein.
- im letzten Durchlauf muss dem Eingangssignal eine 0 angehängt werden. 
Um den G. einer Sequenz mit N Samples zu berechnen benötigt man also N+1 
Durchläufe des Filters.

Grüße,
Alex

von Detlef (Gast)


Lesenswert?

@Alex
Danke! Das war es. Die Verschiebung von N-2 deutete irgendwie schon 
darauf hin. Nun läuft es perfekt.
Detlef

von Detlef (Gast)


Angehängte Dateien:

Lesenswert?

Dank der kompetenten Hilfe hier im Forum nun ein Goertzelalgorithmus der 
fehlerfrei arbeitet. Für alle Wiederholungstäter - siehe Anhang ;-)
Detlef

von Marcus M. (marcus)


Lesenswert?

Hallo,

ich versuche gerade verzweifelt den Görtzel Algorithmus auf einem 
Microcrontoller zu implemetieren. Habe aber noch Verständnisfragen.

Ich möchte nur die Phase von zwei Sinus Signalen auslesen. Beide Signale 
liegen bei etwa 25 kHz. Das Original Signal ist ein Sinus mit einer 
Amplitude von ca. 1,25 Volt. Das verschobene Signal ein Sinus der etwa 
um 40 bis 60 Grad verschoben ist und eine Amplitude von ca. 0,8 Volt 
hat. Und ich taste mit 120 kHz ab. Ich gebe immer 100 Abtastwerte auf 
den Algorithmus. Ich möchte die Differenz der Phasenlagen berechnen. 
Jedoch ändert sich diese ständig, obwohl die Signale immer die gleiche 
Phasenlage zueinander haben.

Was muss ich beachten bezüglich Abtastwerte oder besser gesagt 
Blockgröße?

Danke für eventuelle Tipps!

Gruß Marcus

von Detlef (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Marcus,

deine Filterbandbreite ist zu groß. Du musst entweder die Abtastfrequenz 
kleiner machen oder die Blockgröße erhöhen. Anbei mal zwei Varianten.
1.  120 kHz Abtastfrequenz und Blockgröße 600
2.  20 kHz Abtastfrequenz und Blockgröße 100
Der Vorteil von Görtzel liegt ja gerade in der Unterabtastung.

von nides (Gast)


Lesenswert?

Der Goertzel (wie auch der FFT) Algorithmus liefert nur korrekte Werte 
für ganzzahlige Frequenzen (1/2/3/4... Schwingungen pro Block (bzw. 
Fenster)).

Falls die Frequenz nicht ganzzahlig im Fenster ist -> leakage effect
( http://de.wikipedia.org/wiki/Leck-Effekt ).

Gruß,
Alex

von Marcus M. (marcus)


Lesenswert?

Hallo,

@Detlef: danke für den Hinweis. Werde dies berücksichtigen. Hängt dies 
dann nicht auch an der benötigten Bandbreite. Was wäre wenn ich 120 Hz 
Bandbreite annehme?

@Alex: danke für den Hinweis. Sollte ich eventuell sogar das Signal mit 
diversen Fensterfunktionen (Hamming usw.) multiplizieren oder ist der 
Algorithmus auch mit einem normales Rechteckfenster zu gebrauchen?

Danke für die Hinweise.

Gruß Marcus

von Detlef (Gast)


Lesenswert?

Marcus Moser schrieb:
> Was wäre wenn ich 120 Hz
> Bandbreite annehme?

Das kannst du natürlich machen. Bei einer Abtastfrequenz von 20 kHz 
kommst du bei B=120 aber nicht auf ein ganzzahlige Blockgröße. Bei B=125 
erhältst du jedoch für die Blockgröße N=160.  Außerdem muss, wie Niedes 
schon sagte, immer eine ganzzahlige Periode der Schwingungen in den 
Block passen. Das ist bei N=160 auch erfüllt. Das „fenstern“ kannst du 
dir damit sparen, es ist ja somit ein Rechteckfenster.

von Marcus M. (marcus)


Lesenswert?

Alles klar danke. Werde es gleich mal mit Matlab simulieren.
Das mit der Fensterfunktion war klar. Meinte nur ob ich eventuell das 
Signal an den Rändern nicht so "hart" (Rechteckfenster) fenstern soll, 
sondern durch Hamming usw.

Gruß Marcus

von Detlef (Gast)


Lesenswert?

Marcus Moser schrieb:
> Meinte nur ob ich eventuell das
> Signal an den Rändern nicht so "hart" (Rechteckfenster) fenstern soll

Wenn du dafür sorgst, dass immer eine volle Periode oder ein Vielfaches 
davon in den Block passt (Phasenlage egal), dann musst du nicht 
fenstern. Wenn du nun virtuell die Blöcke ins positive und ins negative 
aneinander hängen würdest, entsteht an den Blockgrenzen keine 
Unstetigkeit. Damit ist existiert das Signal von Minus Unendlich bis 
Plus Unendlich. Somit tritt kein Leakage auf.

von Marcus M. (marcus)


Lesenswert?

Hallo Detlef,

ich hätte da noch eine Frage:

Ich erzeuge in Matlab einen Sinus mit der Frequenz 25 kHz und
nehme von diesem alle 4*10^-6 sec (entspricht einer Samplefrequenz von 
250 kHz) eine Stützstelle. Dann muss ich schauen, dass ich ein 
ganzzahliges Vielfaches von Perioden im "Fenster" habe. Dies wären doch 
dann n*T = n* 40*10^-6. Bandbreite = fs/N. Wie groß sollte die 
Bandbreite maximal sein? Und wenn ich an der Samplefrequenz nichts 
ändern möchte, muss ich ich die Blockgröße N dann auf z.B. auf 1250 
erhöhen? Dann hätte ich eine Bandbreite von 200 Hz. Und in N=1250 würden 
125*T hineinpassen.

Gruß Marcus

von Detlef (Gast)


Angehängte Dateien:

Lesenswert?

@Marcus

Deine Überlegung ist richtig. Du musst nur die Bedingung n*T = N*Ts 
einfach einhalten. Ist wie in deinem Fall n=125 dann ist N=1250. Es geht 
natürlich auch mit n=1 und damit mit N=10. Allerdings wird die 
Bandbreite katastrophal. Praktisch würde ich zunächst meine maximale 
Bandbreite ermitteln und dann das zugehörige n bzw. N ermitteln.

von Martin S. (strubi)


Lesenswert?

Nur so'n Kommentar, wo ich grade mitlese: Unter dem Stichwort "Sliding 
Goertzel" gibt's einige Erkenntnisse zu Phase und beliebigen Frequenzen 
(müssen nicht ins "Fenster" passen. Zeitliche Änderungen und laufende 
Ermittlung der Phase ist also ansich kein Problem.

von Marcus M. (marcus)


Lesenswert?

Hallo zusammen,
hallo Detlef,

ich habe den Görtzel nun in Matlab realisieren können. Nun geht es 
darum, diesen Code auch im Controller zu implementieren.

Bis jetzt habe ich folgenden Code:
1
        double Fs = 229840;
2
  double k;
3
  double coeff;
4
  double cos_coeff;
5
  double realteil;
6
  double imagteil;
7
  double phi_rad;
8
  double phi_grad;
9
  double s0 = 0.0;
10
  double s1 = 0.0;
11
  double s2 = 0.0;
12
        int ind;
13
14
  k = round(f/Fs*N)+1; 
15
  coeff = 2*M_PI*(1/N)*k;
16
  cos_coeff = cos(coeff) * 2;
17
  
18
  x[N+1]=0;
19
  for (ind=1; ind==N+1; ind++) 
20
          {
21
      s0 = x[ind] + cos_coeff*s1 - s2;
22
          s2 = s1;
23
          s1 = s0;
24
      }
25
  realteil = s1 - s2*cos_coeff/2;
26
  imagteil = s2*sin(coeff);
27
  phi_rad= atan(imagteil/realteil);
28
    
29
  if (realteil < 0)
30
    {
31
    phi_rad = phi_rad - (M_PI/2);
32
    }
33
    else 
34
    {
35
    phi_rad = phi_rad + (M_PI/2);   
36
    }
37
  
38
  phi_grad = 180*phi_rad/M_PI;
39
40
41
  if (phi_grad > 180)
42
      {phi_grad = phi_grad - 360;}
43
        if (phi_grad < -180)
44
      {phi_grad = phi_grad +360;}
45
      
46
  
47
  return phi_grad;

Jedoch erhalte ich keine gescheiten Zahlen. Liegt wohl an den 
Nicht-Integer Berechnungen. Aber ich dachte, dass ich dies mit double 
Variablen richitg mache.
Kann mir da jemand auf die Sprünge helfen?
Danke.
Gruß Marcus

von Alex (Gast)


Lesenswert?

Hallo!

Also im Görtzel-Teil sehe ich auf die Schnelle keinen Fehler.

Was meinst du mit "keine gescheiten Zahlen"?
Hast du die Berechnung in Matlab genau so gemacht?

Alex

von SFT - Slow Fourier Transform (Gast)


Lesenswert?

Hi,
arbeitest Du mit MathCad? Das Ablaufdiagramm in den ersten Posts sieht 
zumindest danach aus.
Wenn es MathCad ist, könnte es vielleicht am
    atan (imag / real)
liegen, wenn die Phase "komisch" ist, da sich dieses "atan(...)" immer 
auf den 1. Quadranten des komplexen Ebene bezieht. Wenn die komplexe 
Zahl dort nicht liegt, produziert der "atan(...)" halt Käse.
Probier die Phase mal anders zu berechnen. Ich glaube, in MathCad gibt's 
noch den Befehl "angle(...)" (oder so). Dabei wird automaisch der 
richtige Quadrant bestimmt.
Dann klappt's auch  mit der Phase ;-)

von Detlef (Gast)


Lesenswert?

Marcus Moser schrieb:
> Jedoch erhalte ich keine gescheiten Zahlen.

Der Code sieht korrekt aus. Was ist dein Fehler? Gebe mal ein Bsp. an.

von Marcus M. (marcus)


Lesenswert?

Hi Alex, SFT.., Detlef,

sorry, dass ich mich erst jetzt melde, hatte letzte Woche keine Zeit 
mehr.

Ja ich habe diesen Code in Matlab so laufen und er tut auch was er soll. 
Nur im Controller gab er mir die Phasen entweder gar nicht aus oder 
falsch. Ich habe mittlerweile den Code im Controller soweit am Laufen, 
dass er nun auch die Phase ausgibt. Nur habe ich bei der Berechnnung 
irgendwelche Schwankungen, so dass er immer zwischen 10 bis 20 Grad 
schwankt, aber stabil. Dieselbe Hardware nur mit Matlab über UART an Com 
Schnittstelle angesteuert und ausgelesen gibt mir exaktere Werte. D.h. 
es muss an der Berechnung im Controller liegen. Deswegen habe ich die 
float Zahlen in meiner Berechnung unter verdacht.
Hat da eventuell schon jemand den Görtzel auf dem Controller am Laufen 
mit Integer Zahlen (Code in C)?
Den Code habe ich gerade auf dem anderen Rechner und kann diesen 
deswegen jetzt nicht anhängen, aber ich werde dies morgen früh noch 
nachholen.


Gruß Marcus

von Detlef (Gast)


Lesenswert?

Ich habe gerade mal mit unterschiedlichen Rundungsvarianten gerechnet.
3 Nachkommastellen 0.1 % Phasenfehler
2 Nachkommastellen 1 % Phasenfehler
1 Nachkommastelle 4.5 % Phasenfehler
0 Nachkommastellen 18 % Phasenfehler

von Marcus M. (marcus)


Lesenswert?

Hallo Detlef,

danke für die tolle Hilfe.
Die Lösung meines Problems haben wir nun herausgefunden. Der 
µ-Controller
hatte Probleme bei der Abtastung. Zuerst war der Kerntakt zu langsam 
eingestellt und dann der Timer für die Abtastung durch den ADC.

Die Schwankungen sind soweit weg, da ich die Signale nun auch gescheit 
abtaste.

@alle anderen:
Wer diesen Thread zufällig liest und auch mit dem AdµC 7128/ 7129 
arbeitet und Hilfe braucht. Ich habe den C-Code nun fertig. Einfach 
anfragen.

Gruß Marcus

von Mr. Q. (lunza)


Lesenswert?

Hallo,

welchen unterschied würde es machen, wenn ich keine Blöcke durch den 
Filter schicke, sondern jedes Sample einzeln berechne.

Gruß

von Detlef (Gast)


Lesenswert?

keinen

von Mr. Q. (lunza)


Lesenswert?

Also irgendwie ist das Ergebniss sehr unbefriedigend.
Ich möchte ja quasi den maximalen Amplitudenwert einer Sinusschwingung 
haben und die Phasenverschiebung dieser Schwingung gegenüber einem 
absoluten Wert.
Ob nach einem oder 8 Samples ist im Grunde egal, nur mehr oder weniger 
schnell sollte es sein..

Gruß QB

von Detlef (Gast)


Lesenswert?

Mr. Qb schrieb:
> Also irgendwie ist das Ergebniss sehr unbefriedigend.

Dann hast du noch einen Fehler in deiner Rechnung. Der Algorithmus 
rechnet exakt.

Mr. Qb schrieb:
> Ob nach einem oder 8 Samples ist im Grunde egal, nur mehr oder weniger
> schnell sollte es sein..

Das ist ein Widerspruch. Der Algorithmus benötigt je nach Abtastfrequenz 
und Filterbandbreite eine exakt darauf abgestimmte Anzahl von Sampels, 
irgendeine Anzahl zu nehmen produziert mit Sicherheit keine richtige 
Lösung.

von Mr. Q. (lunza)


Lesenswert?

Ok,

dann ist klar, dass das Ergebniss unbefriedigend ist.
Abtasten tue ich mit 8,3Mhz. Der abzutastende Sinus hat 1Mhz.
Wie kann ich die Anzahl der benötigten Samples den bestimmen?
Ich benötige nur die 1Mhz alles andere kan wegfallen bzw. werde ich 
später versuchen dieses mit einem Vorgeschalteten bandpass noch 
rauszufiltern.

Gruß

von Mr. Q. (lunza)


Lesenswert?

Ok,

ich glaube so langsahm blicke ich dahinter.
mit der Anzazhl der Samples gebe ich im Brinzip meine Bandbreite vor. 
Die Frage ist, worauf bezieht sich diese?
Bei 8,3Mhz Abtastrate, und 100 Samples, wäre meine bandbreit somit 
800Hz?
Also 0 - 800Hz, oder 1Mhz +- 400Hz? Irgendwie leicht verwirrend.

von Detlef (Gast)


Lesenswert?

Du musst zunächst dafür sorgen, dass in einem Datenblock immer ein 
n-faches einer Periode ist. Hältst du diese Bedingung nicht ein, so 
springt deine Phase von Block zu Block. Weiterhin benötigst du eine 
entsprechende Bandbreite. Ein Goertzelfilter ist ja nur eine 
vereinfachte FFT mit genau einer Frequenz. Die Bandbreite bestimmt 
sozusagen die Filterbandbreite. Um es in Formeln zu pressen:
f0 Frequenz welche detektiert werden soll, der Kehrwert T0
fs Sampelfrequenz, der Kehrwert TS
n Anzahl der zu erfassenden Perioden

Blocklänge: N = n * (T0/TS)
Bandbreite: B = fs/N

von Mr. Q. (lunza)


Lesenswert?

Spielt es eine Rolle an welche Stelle des Signals ich Abtaste?
Ich meine, muss quasi synchron abgetastet werden, oder reicht es das die 
Anzahl der Samples pro periode gleich ist?

von Detlef (Gast)


Lesenswert?

1. Die Stelle spielt eine Rolle, z.B. immer im Nulldurchgang wird 
natürlich nichts.
2. Grundvoraussetzung sind natürlich äquidistante Abtastschritte.

von Mr. Q. (lunza)


Lesenswert?

Ich meinte nur, wenn ich nicht genau mit einem Vielfachen von F0 
abtaste, verschieben sich meine Samples ja von periode zu periode.

von Detlef (Gast)


Lesenswert?

Vielleicht verstehe ich ja dein Problem nicht. Ein Block ist immer so 
aufgebaut, dass die Blöcke aneinander gehangen werden können und sich 
damit ein stetiges Signal ergeben würde, d.h. auf den letzten Sampelwert 
folgt wieder der erste Wert. Ansonsten bekommst du den Leakage effect. 
Ist diese Bedingung eingehalten, berechnet Goertzel exakt Amplitude und 
Phasenlage dieses Blockes. Sind im nächsten Block die Sampels 
verschoben, bekommst du selbstverständlich eine andere Phasenlage für 
diesen Block.

von Mr. Q. (lunza)


Lesenswert?

Vielleicht habe ich auch kein Problem und ich verstehe auch was du mir 
sagst... also:

Sagen wir ich Taste immer mit einem Mehrfachen meiner Messfrequenz ab.
meine Abtastwerte sind somit bei jeder Periode z.B. bei:
1/4Pi, 1/2Pi, pi, 3/4 Pi.... es wiedreholt sich bei jeder periode.
Nun Taste ich um ein wenig mehr, als ein Mehrfaches der Abtastfrequnz 
ab:
(1/4+0.1)Pi, (1/2+0.2)Pi, pi+0.3, 3/4(0.4)Pi...
bei der nächsten Periode wäre dann mein erster abtastwert nicht mehr bei 
(1/4+0.1)Pi, sondern bei 1/4+0.5)Pi....
Für eine normale Abtastung spielt es keine Rolle, ich bin mir nur nicht 
sicher ob ich den Goerzel richtig verstanden habe.

von Detlef (Gast)


Lesenswert?

Mr. Qb schrieb:
> Für eine normale Abtastung spielt es keine Rolle, ich bin mir nur nicht
> sicher ob ich den Goerzel richtig verstanden habe.

Tatsächlich spielt es für die FFT auch eine Rolle.
Mache dazu das einfache Gedankenmodell. Die abgetastete Funktion ist ein 
reiner Sinus also eine ungerade Funktion. Dann besitzt das Spektrum nur 
einen Imaginärteil. Ist die abgetastete Funktion ein reiner Cosinus, 
also eine gerade Funktion, dann besitzt das Spektrum nur einen Realteil. 
Verschiebt sich also dein Abtastwert leicht, ändert sich das Spektrum 
kontinuierlich zwischen Imaginärteil und Realteil. Wenn du aus diesen 
beiden Werten nur den Betrag der Amplitude berechnest, merkst du es 
natürlich nicht, doch die Phase ändert sich trotzdem ständig. Da der 
Goertzel nur eine vereinfachte FFT ist, macht sich eine 
Abtastverschiebung nicht im Betrag der Amplitude bemerkbar, sehr wohl 
jedoch in der Auswertung der Phase. Fazit: Bei der Abtastung ist eine 
kontinuierliche Verschiebung der Sampels verboten!

von Mr. Q. (lunza)


Lesenswert?

Wie kann ich mir das berechnete Spektum anschauen? Wären das Betrag und 
Phase nach jedem Schleifendurchlauf?

von Detlef (Gast)


Lesenswert?

Mr. Qb schrieb:
> Wie kann ich mir das berechnete Spektum anschauen? Wären das Betrag und
> Phase nach jedem Schleifendurchlauf?

Immer dann wenn ein kompletter Block berechnet ist.

von Mr. Q. (lunza)


Lesenswert?

Ich hab immernoch Probleme eine Plausible Amplidue und Phase zu 
bestimmen, die Werte springen stark. Hier mein Code:

#define F0    1000000    // Abgetastete Freq
#define FS    5000000    // Sampelfreq
#define T0    ((float)1/F0)
#define TS    ((float)1/FS)

void init_goerzel(_u32 n)
{
  _u32 k;
  float w;

  N = n*(T0/TS);
  B= FS/N;
  k = 0.5 + N*F0/FS;
  w = ((2*PI)/N)*k;
  cosine = cos(w) ;
  cos_coeff = 2*cosine;
  sine = sin(w);
}

void goerzel(_u16* x)
{
  float realteil;
  float imagteil;
  float phi_rad;
  float s0;
  float s1 = 0;    // bei jedem Block neu initialisieren
  float s2 = 0;    // bei jedem Block neu initialisieren
  int i =0;
  static int j=0;


  for (i=0;i<N;i++)
  {
    s0 = x[i] + cos_coeff*s1 - s2;
      s2 = s1;
      s1 = s0;
  }

    realteil = s1 - s2*cosine;
    imagteil = s2*sine;

  amplitude = sqrt(pow(realteil,2) + pow(imagteil,2));
    phi_rad= atan(imagteil/realteil);

    phi_grad = (phi_rad*180)/PI;
}

Derzeit ist die Blockgröße 15 also 3 Perioden.

Im ergebniss habe ich aber irgendwie nur schwachsinn...

von Detlef (Gast)


Lesenswert?

Wenn die Blocklänge N ist, so muss die Schleife von 0 bis N laufen. Der 
Wert x[N] muss Null sein.

von Mr. Q. (lunza)


Lesenswert?

Stimmt, habe ich schon gefunden den fehler, die Phase scheint nun zu 
stimmen, leider noch ein wenig verrauscht, ich muss noch ein wenig mit 
der Bandbreite Spielen. Leider habe ich nicht allzuviel Zeit um eine 
große Anzahl an Samples zu bestimmen am liebsten wären mit Amplitude und 
Phase schon nach einer Periode, ansonsten muss ich über eine 
Spitzenwertdetektion in Hardware nachdenken, was mir die möglichkeit 
rauben würde das Signal noch Digital zu Filtern... mal sehen.
Mit der Phase habe ich noch Probleme, aber ich glaube meine Abtastblöcke 
sind nicht Synchron. Ich werde heute versuchen dieses Problem zu lösen.

von Mr. Q. (lunza)


Angehängte Dateien:

Lesenswert?

Ich hab mal ein Paar Messergebnisse angehängt.
Also die Schwankungen in der Amplitude mögen vorhanden sein, aber der 
Rest erscheint mir sehr verwirrend.
Ich nehme immer 32 Werte auf und beginne die Aufnahme dan von neuem. Ich 
verstehe nicht, warum die Phase so wandert.
Die sichbaren grenzen im Real- und Imaginärteil sind in der Berechnung 
nicht vorhanden. Mein Zahlenbereich hat für die Ausgabe nur nicht 
ausgereicht.

von Mr. Q. (lunza)


Lesenswert?

So, hab noch ein wenig was ausgebügelt, aber meine Phase ist ein 
Sägezahn. Einer ne Idee?

von Detlef (Gast)


Lesenswert?

Mr. Qb schrieb:
> aber meine Phase ist ein
> Sägezahn. Einer ne Idee?

Nun das sieht so aus, als ob du eine Phasenverschiebung von Block zu 
Block hast.

von Mr. Q. (lunza)


Lesenswert?

Könnte sein, dass meine Abtastfrequenz nicht genau ein vielfaches meines 
Signals ist oder?

von Detlef (Gast)


Lesenswert?

Ja, es schein so auszusehen

von Mr. Q. (lunza)


Lesenswert?

Nun es scheint tatsächlich zu zu sein.
Kann ich den Filter auch als eine art Bandpass sehen? Oder brauche ich 
zusätzliche Filter um weitere Störungen auszugleichen?

von Detlef (Gast)


Lesenswert?

Mr. Qb schrieb:
> Kann ich den Filter auch als eine art Bandpass sehen?

Das Filter realisiert exakt die FFT auf genau einer Frequemz mit der 
vorgegebenen Bandbreite.

von Mr. Q. (lunza)


Lesenswert?

Hm, also irgendwo muss da noch ein Wurm drin sein.
Auch wenn ich die Frequenz nachjustiere, komme ich nie genau auf den 
Wert, dass die Phase stehen bleibt. Mache ich eine "normale" FFT ist 
meine Phase bei 10Mhz ca. bei -3°, was auch der richtige wert sein 
Sollte. Mit dem Goerzel wandert sie aber.
Ich habe überlegt für diese stetige wanderung eine korrektufaktor 
einzubauen, gefallen tut mir dies aber nicht.

von Mr. Q. (lunza)


Lesenswert?

Kann es an einer "noch" fehlenden Fensterung liegen?

von Joe G. (feinmechaniker) Benutzerseite


Lesenswert?

Mr. Qb schrieb:
> Kann es an einer "noch" fehlenden Fensterung liegen?

Nein, wenn du die Bedingungen bezüglich Blocklänge, Abtastung, 
Bandbreite ... einhältst ist es ja schon ein Rechteckfenster.

von Mr. Q. (lunza)


Lesenswert?

So richtig verstehe ich die Phasenberechnung vom Goerzel nicht.
Warum muss die Abtastfrequenz ein vielfaches der Samplefrequenz sein? 
Auch wenn ich asynchron abtaste, bleibt die Phase doch immer gleich. Es 
macht für mich keinen Sinn.

von Mr. Q. (lunza)


Lesenswert?

Hm ich verstehe es doch... lößt leider nicht mein Problem...

von MrPPI (Gast)


Lesenswert?

Hi,
ich habe auch noch eine Frage zum Goertzel.
Ich möchte diesen zur Amplituden- und Phasenbestimmung nutzen, leider 
passt schon die Amplitude nicht wirklich und ich weiß nicht warum. 
Letztlich verwende ich den Code aus dem Thread:
1
void SignalProcessing::testIt()
2
{
3
    //Signal generieren
4
    QList<double> sign;
5
    int sampleRate=1000;
6
    int periods=1;
7
    int frequency=100;
8
    int amp=1000;
9
    double measuredAmplitude;
10
    double measuredPhase;
11
    int sampleCount=(sampleRate/frequency)*periods;
12
    for (int i=0; i<sampleCount; i++)
13
    {
14
        sign << amp*sin((2*M_PI*i)/(sampleRate/frequency));
15
    }
16
    goertzel(&test,frequency,sampleRate,&measuredAmplitude,&measuredPhase);
17
    qDebug() << "Görzel:" << measuredAmplitude << measuredPhase;
18
}
19
20
void SignalProcessing::goertzel(QList<double> *inPutSignal, int frequency, int sampleRate, double *amplitude, double *phase)
21
{
22
    inPutSignal->append(0);
23
    int N=inPutSignal->count();
24
    double D0=0;
25
    double D1=0;
26
    double D2=0;
27
    double realPart;
28
    double imagPart;
29
30
    double a1=2.0*cos(2.0*M_PI*frequency/sampleRate);
31
    for(int i=0; i< N; i++)
32
    {
33
        D0=inPutSignal->value(i)+a1*D1-D2;
34
        D2=D1;
35
        D1=D0;
36
    }
37
    realPart=D1-(a1/2)*D2;
38
    imagPart=D2*sin(2*M_PI*frequency);
39
    *amplitude=sqrt(realPart*realPart+imagPart*imagPart);
40
    *phase=atan(imagPart/realPart);
41
    if (realPart<0)
42
    {
43
        *phase=*phase-M_PI/2;
44
    }
45
    else
46
    {
47
        *phase=*phase-M_PI/2;
48
    }
49
}


Für Amplitude kommt  0.000437114  und für die Phase kommt -1.5708 raus, 
was ja nicht stimmen kann. Hat jemand diesbezüglich eine Idee?

Grüße

MrPPI

von Joe G. (feinmechaniker) Benutzerseite


Lesenswert?

MrPPI schrieb:
> Hat jemand diesbezüglich eine Idee?

Beitrag "Re: Goertzel Phasenbestimmung"

von Joe G. (feinmechaniker) Benutzerseite


Angehängte Dateien:

Lesenswert?

Noch ein Nachtrag

von MrPPI (Gast)


Lesenswert?

Hallo Joe,

vielen Dank für die schnelle Antwort.

Ich generiere mir ja mit der ersten Funktion einen sinus (eine Periode).

Mit
1
inPutSignal->append(0);
2
int N=inPutSignal->count();

in der Goertzel-Funktion füge ich einen weiteren Punkt mit dem Wert 0 
hinzu.
Das sollte doch stimmen oder?

Grüße

MrPPI

von Joe G. (feinmechaniker) Benutzerseite


Lesenswert?

Ohne deinen Code zu verstehen, wenn dein Abtastblock z.B. 50 Werte 
enthät, muß der 51(!) Wert Null enthalten und das Filtervon 0 bis 51 
laufen.

Gruß Joe

von MrPPI (Gast)


Lesenswert?

Genau das machen die zwei Codezeilen!

von Joe G. (feinmechaniker) Benutzerseite


Lesenswert?

Dann sollte es laufen...

von MrPPI (Gast)


Lesenswert?

sollte.. .

von MrPPI (Gast)


Lesenswert?

So ich bin weitergekommen:
1
void SignalProcessing::goertzel(QList<double> *inPutSignal, int frequency, int sampleRate, double *amplitude, double *phase)
2
{
3
    inPutSignal->append(0);
4
    int N=inPutSignal->count();
5
    double D0=0;
6
    double D1=0;
7
    double D2=0;
8
    double realPart;
9
    double imagPart;
10
11
    double a1=2.0*cos(2.0*M_PI*frequency/sampleRate);
12
    for(int i=0; i< N; i++)
13
    {
14
        D0=inPutSignal->value(i)+a1*D1-D2;+a1*D1-D2;
15
        qDebug() << inPutSignal->value(i);
16
        D2=D1;
17
        D1=D0;
18
    }
19
20
    realPart=D1-(a1/2)*D2;
21
    imagPart=D2*sin(2*M_PI*frequency/sampleRate);
22
    *amplitude=sqrt(realPart*realPart+imagPart*imagPart);
23
    *phase=atan(imagPart/realPart);
24
    if (realPart<0)
25
    {
26
        *phase=*phase-M_PI/2;
27
    }
28
    else
29
    {
30
        *phase=*phase-M_PI/2;
31
    }
32
}

Ich musste bei "imagePart=D2*sin(2*M_PI*frequency) das / sampleRate
eintragen.
Jetzt ist noch folgendes: Wenn ich mir mit dem Signalgenerator eine 
Periode des Signals genierer (z.B. mit Amplitude=10) kommt 50 raus.
Bei 2 Perioden: 100;
D.h. ich muss durch 10 teilen und die Anzahl der Perioden mit 
einrechnen, was ja aber eigentlich nicht sein kann. Irgendwo ist noch 
der Wurm drin.

Grüße

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.