Goertzel auf ATMega1280: Seltsames Problem

Gast #1459539
Hi,

einige hier haben ja Erfahrung mit dem Goertzel-Algorithmus bzw. DTFM. 
Ich habe den Görtzel ähnlich dem Beispiel von Helmut Lenzen in folgendem 
Thread implementiert, um eine bestimmte Frequenz in einem Audiosignal zu 
detektieren (ATMega 1280):

Beitrag "Wo Welchen DTMF Decoder"
außerdem gut zur Auffrischung:
http://www.answers.com/topic/goertzel-algorithm

Leider habe ich jetzt das Problem, dass der Algorithmus nur für eine 
bestimmte Frequenz funktioniert, egal wie ich den Koeffizienten A setze. 
Das heißt, egal ob A 3 oder 7000 ist, ich bekomme immer nur für ca. 5,5 
kHz ein Maximum.
Sample-Frequenz ist konstant bei ca. 22038 Hz (16 Bit Timer1 triggert 
ADC-Wandlung, Algorithmus ist in der ADC-Interrupt-Routine).

Ich habe den Code mal genau so in MATLAB reingehauen, da funktioniert 
er. Es muss also irgendwas 8bit-µC-Spezifisches sein, aber ich komme 
gerade echt nicht dahinter - irgendwie verscheindet die Wirkung des 
Faktors A.

So sieht mein Code aus:

#define N  200  // goertzel filter length; frequency resolution B = Fs/N
#define A  54   // filter coefficient: 2*cos(4761Hz*2*pi/Fs)*128
                // scaled with 128

[..]

// goertzel algorithm in ADC conversion complete ISR
ISR(ADC_vect) {
  uint16_t adclval, adchval;

  //read 16bit ADC value
  adclval = ADCL;
  adchval = ADCH<<8;
  adcval = adclval | adchval;

  //goertzel
  if (filtidx == N)      // outer filter
  {
    filtidx = 0;

    v1 = v1/1024;        // scaling with 1024
    v2 = v2/1024;
    y = (v1*v2*A2)/2048; // scaling with 2048
    y = v1*v1 + v2*v2 - y;

    v1 = 0;
    v2 = 0;

  }
  else                  // inner filter
  {
    v0 = A2*v1/128;     // scaling with 128
    v0 = adcval + v0 - v2;
    v2 = v1;
    v1 = v0;
    filtidx++;
  }
}


Die ganzen Divisionen/Multiplikationen mit Zweierpotenzen im Code 
bewirken nur eine Abbildung auf einen Integer-Wertebereich, wobei sie 
teilweise recht willkürlich gewählt sind. Ich habe schon ziemlich viel 
mit den Skalierfaktoren herumgespielt, an denen liegt es nicht, würde 
ich behaupten. Lasse mich aber gerne eines Besseren belehren, jegliche 
Ideen sind willkommen.

Hat jemand einen Tipp?

Danke,
Grüße
Raphael
Gast #1459543
schreib mal deine variablen definitionen mit dazu...welchen wert haben 
v1 und v2 initial? es gibt ein define von A,du verwendest aber A2...und 
man muss das bestimmt nicht alles in der ISR machen...
#1459741
Hi,

sorry, ich habe den Code etwas lesbarer gemacht und dabei Fehler 
reingebaut :( Natürlich liegts nicht an A bzw A2, im echten Code gibt es 
aber mehrere Ax.

Anfangs gilt v0 = v1 = v2 = filtidx = 0, das ist aber relativ egal, da 
die Variablen nach dem ersten Durchlauf eh Null gesetzt werden. Und 
grundsätzlich spuckt der Algorithmus ja erwartungsgemäß was aus, nur 
lässt sich die zu suchende Frequenz nicht über den Koeffizienten A 
einstellen. Edit: Hier noch die Variablendefinition:


uint16_t adcval;    // adc conversion result
int v0 = 0;         // goertzel filter variables
int v1 = 0;
int v2 = 0;
int filtidx = 0;    // current filter step
int y = 0;          // filter result (signal power)


Da es echt nur ein paar Berechnungen pro Durchlauf sind, spricht IMHO 
nichts gegen die Verwendung der Interruptroutine. Sollte aber auch 
nichts mit dem Fehler zu tun haben.

Hat noch jemand eine Idee?


Grüße&Danke
Raphael
#1459999
Hast du mathematisch untersucht, welchen Einfluss das Downscaling hier

    v1 = v1/1024;        // scaling with 1024
    v2 = v2/1024;
    y = (v1*v2*A2)/2048; // scaling with 2048

auf das Ergebnis hat. Effektiv werden dir da wohl nur ein paar von den 
höherwertigen Bits aus v1 und v2 übrig bleiben. Du wirfst du ziemlich 
viel weg.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.