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