Forum: Mikrocontroller und Digitale Elektronik Goertzel auf ATMega1280: Seltsames Problem


von Raphael (Gast)


Lesenswert?

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

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Weil Du in Code A2 und nicht A verwendest?

von mui (Gast)


Lesenswert?

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...

von Raphael S. (rs073)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Raphael S. (rs073)


Lesenswert?

Jetzt funktionierts, es lag tatsächlich an den Skalierfaktoren, ich 
hatte die Wirkung von A zu stark unterdrückt, wie schon vermutet

Manchmal brauchts ne Weile, auch wenns so einfach ist...

Grüße und Danke
Raphael

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.