www.mikrocontroller.net

Forum: Analogelektronik und Schaltungstechnik Goertzel Phasenbestimmung


Autor: Detlef (Gast)
Datum:

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...
Gruß D.
Autor: Holger (Gast)
Datum:

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?
Autor: Detlef (Gast)
Datum:
Angehängte Dateien:

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.
Autor: holger (Gast)
Datum:

>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?
Autor: holger (Gast)
Datum:

>In Bezug auch was auch?

In Bezug auf was auch?
Autor: Holger (Gast)
Datum:

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>
Autor: Detlef (Gast)
Datum:

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.
Autor: Holger (Gast)
Datum:

Wieviel Werte shcibest Du denn rein und welche Frequenz interessiert
dich?
Autor: Alex (Gast)
Datum:

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
Autor: Detlef (Gast)
Datum:

@Alex
Danke! Das war es. Die Verschiebung von N-2 deutete irgendwie schon
darauf hin. Nun läuft es perfekt.
Detlef
Autor: Detlef (Gast)
Datum:
Angehängte Dateien:

Dank der kompetenten Hilfe hier im Forum nun ein Goertzelalgorithmus der
fehlerfrei arbeitet. Für alle Wiederholungstäter - siehe Anhang ;-)
Detlef
Autor: Marcus Moser (marcus)
Datum:

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
Autor: Detlef (Gast)
Datum:
Angehängte Dateien:

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.
Autor: nides (Gast)
Datum:

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
Autor: Marcus Moser (marcus)
Datum:

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
Autor: Detlef (Gast)
Datum:

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.
Autor: Marcus Moser (marcus)
Datum:

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
Autor: Detlef (Gast)
Datum:

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.
Autor: Marcus Moser (marcus)
Datum:

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
Autor: Detlef (Gast)
Datum:
Angehängte Dateien:

@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.
Autor: Martin S. (strubi)
Datum:

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.
Autor: Marcus Moser (marcus)
Datum:

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:
        double Fs = 229840;
  double k;
  double coeff;
  double cos_coeff;
  double realteil;
  double imagteil;
  double phi_rad;
  double phi_grad;
  double s0 = 0.0;
  double s1 = 0.0;
  double s2 = 0.0;
        int ind;

  k = round(f/Fs*N)+1; 
  coeff = 2*M_PI*(1/N)*k;
  cos_coeff = cos(coeff) * 2;
  
  x[N+1]=0;
  for (ind=1; ind==N+1; ind++) 
          {
      s0 = x[ind] + cos_coeff*s1 - s2;
          s2 = s1;
          s1 = s0;
      }
  realteil = s1 - s2*cos_coeff/2;
  imagteil = s2*sin(coeff);
  phi_rad= atan(imagteil/realteil);
    
  if (realteil < 0)
    {
    phi_rad = phi_rad - (M_PI/2);
    }
    else 
    {
    phi_rad = phi_rad + (M_PI/2);   
    }
  
  phi_grad = 180*phi_rad/M_PI;


  if (phi_grad > 180)
      {phi_grad = phi_grad - 360;}
        if (phi_grad < -180)
      {phi_grad = phi_grad +360;}
      
  
  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
Autor: Alex (Gast)
Datum:

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
Autor: SFT - Slow Fourier Transform (Gast)
Datum:

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 ;-)
Autor: Detlef (Gast)
Datum:

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

Der Code sieht korrekt aus. Was ist dein Fehler? Gebe mal ein Bsp. an.
Autor: Marcus Moser (marcus)
Datum:

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
Autor: Detlef (Gast)
Datum:

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
Autor: Marcus Moser (marcus)
Datum:

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

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




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net