1
$\begingroup$

I am sampling an audio range signal with a bandwidth of 3100Hz and then applying a FFT using the DSP library example from Microchip to determine the most dominant frequency of the signal.

On the last step where I am supposed to get back the frequency with the highest energy, all I am getting are zeros.

The first step, which is sampling the analogue signal is working well as I have exported the array values into excel and plotted the graph.

The code is as follows:

void alarmFreq (void) //Detect the dominant frequency of the audio picked by the microphone
    {    
    int i = 0;
    fractional *p_real = &sigCmpx[0].real;
    fractcomplex *p_cmpx = &sigCmpx[0];
    readMic();
    for (ix_MicADCbuff=0;ix_MicADCbuff<FFT_BLOCK_LENGTH;ix_MicADCbuff++)
    {
        sigCmpx[ix_MicADCbuff].real = Float2Fract(micADCbuff[ix_MicADCbuff]);   // replace real part with ADC value
        sigCmpx[ix_MicADCbuff].imag = 0;                                        // set imaginary part with 0
    }
    /*for (ix_MicADCbuff=0;ix_MicADCbuff<FFT_BLOCK_LENGTH;ix_MicADCbuff++)
    {
        *p_real = micADCbuff[ix_MicADCbuff];   // replace real part with ADC value
        *p_real++;                                        
    }*/
    for ( i = 0; i < FFT_BLOCK_LENGTH; i++ )//The FFT function requires input data to be in the fractional fixed-point range [-0.5, +0.5]
        {                   
            *p_real = *p_real >>1 ;         //So, we shift all data samples by 1 bit to the right.
            *p_real++;                      //Should you desire to optimize this process, perform data scaling when first obtaining the time samples or within the BitReverseComplex function source code
        }                   
    p_real = &sigCmpx[(FFT_BLOCK_LENGTH/2)-1].real; //Set up pointers to convert real array to a complex array. The input array initially has all the real input samples followed by a series of zeros
    p_cmpx = &sigCmpx[FFT_BLOCK_LENGTH-1] ;                     
    for ( i = FFT_BLOCK_LENGTH; i > 0; i-- )        //Convert the Real input sample array to a Complex input sample array
        {                   
            (*p_cmpx).real = (*p_real--);   //We will simply zero out the imaginary part of each data sample
            (*p_cmpx--).imag = 0x0000;  
        }
    FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));// Perform FFT operation
    BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]);// Store output samples in bit-reversed order of their addresses   
    SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real);//Compute the square magnitude of the complex FFT output array so we have a Real output vector
    VectorMax(FFT_BLOCK_LENGTH/2, &sigCmpx[0].real, &peakFrequencyBin);//Find the frequency Bin ( = index into the SigCmpx[] array) that has the largest energy 
    peakFrequency = peakFrequencyBin*(AUDIO_FS/FFT_BLOCK_LENGTH); //Compute the frequency (in Hz) of the largest spectral component 
}

void readMic (void) //Sample microphone input
    {
    ADC1_ChannelSelectSet(ADC1_AI_MIC);
    ix_MicADCbuff=0;
    for(ix_MicADCbuff=0;ix_MicADCbuff<FFT_BLOCK_LENGTH;ix_MicADCbuff++)
        {
            //delay_ms(1);          //FS without waiting time 66790 Hz
            ADC1_SamplingStop();
            while(!ADC1_IsConversionComplete()){}
            micADCbuff[ix_MicADCbuff] = ADC1_Channel0ConversionResultGet();
        }
}

External variables

extern const fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2]    
__attribute__ ((space(auto_psv), aligned (FFT_BLOCK_LENGTH*2)));

fractcomplex sigCmpx[FFT_BLOCK_LENGTH] __attribute__ ((section (".ydata, data, ymemory"), 
    aligned (FFT_BLOCK_LENGTH * 2 *2))) ={0};

UPDATE:

I am now getting a value, 16640 Hz for dominant frequency.

When I export the data generated to dsPICWorks I get this:

enter image description here

Seems like the function is returning the correct value but the FFT is not working properly as I should get something else right?

UPDATE 2

So I got it working! It was a data type issue. What I did was to change the ADC output data type bits from decimal to fractional and I loaded the samples directly into the array that the FFT function uses. However, I am still having strange behaviours.

The frequency bins are 66790/512 = 130Hz

Sometimes, when I pass a signal which dominant frequency is not a multiple of 130Hz, I get as a result the dominant frequency multiplied times 3. So I have added a divide by 3 instruction in case the result is too high. Luckily I only have two expected frequencies which are 520Hz and 3100 Hz so I can truncate the results, however, I would like to know what the issue is here.

$\endgroup$
  • $\begingroup$ Hi! Can you upload the captured audio data of 3100 Hz bandwidth ? Also, what's the sampling rate and bit resolution of ADC? $\endgroup$ – Fat32 Oct 15 '18 at 0:10

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.