This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Goertzel Algorithm for DTMF decoding on LAUNCHPAD

Other Parts Discussed in Thread: MSP430G2553

I have been trying to apply Goertzel's algorithm to DTMF decoding on my launchpad. I have applied the algorithm successfully in octave to see that it works. However, when I try the same in my launchpad (MSP430G2553) - I do not get the expected results.

Is the problem because of the sampling rate? I have set the sampling rate to near 7kHz. Or am I doing something wrong in multiplication and division of floating point numbers.

I have attached my code below. For simplicity, I have attached the code for only one frequency signal - which also doesn't work.

My OCTAVE Code:

y = wavread("one.wav"); //DTMF signal for 1 Sampling rate - 8000Hz

i=1000; //Starting from the 1000th sample
Q2=0;
Q1=0;

while i<1206 //Applying goertzel's algorithm for 205 samples
Q0 =ceil( y(i) + 1.708*Q1 - Q2) //1.708 is the coeff. for 697Hz signal
Q2 = Q1
Q1 = Q0
i++
endwhile

mag1 = Q2*Q2 + Q1*Q1 - 1.7077*Q1*Q2 //If mag1 is above a threshold - 697Hz frequency is present in the signal

//Similarly applying Goertzel's algorithm for few other frequencies
i=1000
Q2=0
Q1=0

while i<1206
Q0 =ceil( y(i) + 1.646*Q1 - Q2)//
Q2 = Q1
Q1 = Q0
i++
endwhile

mag2 = Q2*Q2 + Q1*Q1 - 1.646*Q1*Q2

i=1000
Q2=0
Q1=0
while i<1206
Q0 =ceil( y(i) + 1.569*Q1 - Q2)
Q2 = Q1
Q1 = Q0
i++
endwhile
mag3 = Q2*Q2 + Q1*Q1 - 1.569*Q1*Q2

i=1000
Q2=0
Q1=0
while i<1206
Q0 = ceil(y(i) + 1.479*Q1 - Q2)
Q2 = Q1
Q1 = Q0
i++
endwhile
mag4 = Q2*Q2 + Q1*Q1 - 1.479*Q1*Q2

My LAUNCHPAD code:

#include "msp430g2553.h"

#define threshold 1000
void main ( void )
{
double Q2, Q1, Q0, mag, temp,coeff;
int i,j;

WDTCTL = WDTPW | WDTHOLD ; // Stop watchdog

P1DIR = BIT0 + BIT6; // both leds in output mode
P1SEL |= BIT1; // P1.1 in ADC channel mode

P1OUT = 0x00;
coeff = 1.56;

ADC10CTL0 = SREF_0 | ADC10SHT_3 | ADC10ON ;
// VCC and VSS refs , sample for 64 cycs , int ref off , ADC on , no ints

ADC10CTL1 = INCH_1 | SHS_0 | ADC10DIV_1 | ADC10SSEL_3 | CONSEQ_0 ;
// Input channel 1 , trigger using ADC10SC bit , clock division by 2,
//internal ADC clock , single channel single conversions
ADC10AE0 = BIT1 ; // Enable analog input on channel 1

ADC10CTL0|=ENC; // Enable conversions

for (;;) // Loop forever taking measurements
{
Q2 = 0;
Q1 = 0;

for(i=0; i<206; i++)
{
ADC10CTL0|=ADC10SC; // Trigger new conversion

while ( ADC10CTL1 & ADC10BUSY) { nop(); } // Loop while conversion takes place
temp = ADC10MEM;
Q0 = ((temp*3.3)/200) + (coeff*Q1) - Q2;
Q2 = Q1;
Q1 = Q0;
}
mag = Q2*Q2 + Q1*Q1 - (coeff*Q1*Q2);
if (mag>=threshold)
{
P1OUT |= BIT0;
for(j=0;j<30000;j++){nop();}
P1OUT &= ~BIT0;


}

else
{
P1OUT |= BIT6;
for(j=0;j<30000;j++){nop();}
P1OUT &= ~BIT6;
}
}
}

When the octave code is run for DTMF signal '1' - it gives 500 times more value for mag1 than other magnitudes (mag2, mag3 and mag4) - showing the presence of 697Hz signal.

My launchpad code doesn't seem to work that way.
Any help would be welcome.

  • Rajeev Ranjan Jha said:
    I have applied the algorithm successfully in octave

    You mean this: http://www.gnu.org/software/octave/ ?

     GNU Octave is a high-level interpreted language, primarily intended for numerical computations. It provides capabilities for the numerical solution of linear and nonlinear problems, and for performing other numerical experiments.

    So it's intended to run on high-performance PC CPUs?

    The MSP430 is not a high-performance CPU! Therefore you need to cut your cloth accordingly!

    In particular, the MSP430 does not have any hardware floating point support; so it all has to be emulated in software - which gives a significant performance hit! (remember: it wasn't a high-performance CPU to start with!)

    However, plenty of people have successfully used the Goertzel algorithm on small microcontrollers - so I would suggest that you study how they did it...

     

  • Yeah I tested the algorithm on octave to be sure it works..........

    I am not sure how to perform a floating point multiplication with microcontrollers. I am not sure how the compiler deals with it. This seems to be the problem.

    I will try to read how others did it.................

  • Rajeev Ranjan Jha said:
    I am not sure how to perform a floating point multiplication with microcontrollers

    The compiler just generates the necessary code, and includes the necessary libraries - there's no problem with that part!

    The problem is that it's a lot of code - so there is a significant performance hit. Whether that is a problem to your particular application is a matter that you need to consider carefully - but you can't just chuck it in & assume that it'll "just work".

    This is one of the major differences between PC programming and embedded microcontroller programming!

    The issues with floating-point can generally be avoided by using integer maths instead; or, perhaps, fixed-point.

     

     

     

  • DTMF detection does not require floating pint calculations. In web you can find discrete goertzel source examples for sure. BTW TI have FSK modem appnote which talks about frequency detection either.

  • I will make an attempt in substituting the multiplication of floating point numbers with shift operators and see how it works out.

  • I could finally implement the Goertzel algorithm in my Launchpad to detect different frequencies. The floating point multiplication was indeed the problem. The time taken to perform floating point multiplication was huge (30s) in my code and it was affecting the sampling rate. I substituted the float multiplication by using integer maths (multiplying the floating number by 128 and shifting it by 7). This saved the time. I also started triggering the ADC by hardware (TimerA0) for more accurate sampling rate. 

  • As previously noted, this really is the big difference between programming something like a PC, and programming a small microcontroller:

    With a PC (or similar) you can usually get away with a "brute force" approach - you can't on a small microcontroller!

    With a small microcontroller you have to work smart - not hard!

**Attention** This is a public forum