cfftesp32esp-idfespressif-idf

ESP32 FFT I'm not getting the correct max frequency of the input signal


I'm working on a project on my ESP32s3, trying to correctly evaluate the maximum frequency of an input signal. I've performed my fft basing my code on the FFT dsp example on ESP-IDF. Actually I generate the signal inside my code, sampling it at a very high frequency. The signal i generate has his peak frequency at 5Hz, but the code I wrote gives back values way higher than this peak frequency. It might be important to mention that the Default fft size that i'm using is 4096.

This is the code that i use to generate the signal

double composite_signal(double t, SignalComponent *component) {
    double signal = 0;
    
    // Summing sine components
    for (int i = 0; i < component->num_sin_components; i++) {
        signal += component->sin_amplitudes[i] * sin(2 * M_PI * component->sin_frequencies[i] * t);
    }
    
    return signal;
}

SignalComponent component = {
    2, // Number of sine components
    {3,5}, // Sine frequencies in HZ
    {2,4} // Sine amplitudes
};

//AND IN THE MAIN
    for (int i = 0; i < NUM_SAMPLES; i++) {
        double t = (double)i / SAMPLING_RATE;
        wave[i] = composite_signal(t, &component);
        //ESP_LOGI(TAG, "FFT for %f ", wave[i]);
    }

Those are the rates i'm using


#define SAMPLING_RATE 1000 // Hz
#define DURATION 3 // seconds
#define NUM_SAMPLES (SAMPLING_RATE * DURATION)
#define TH 3 //threshold for magnitude, max frequency of the fft

Then I process the FFT as it is done in the dsp ESP IDF example

dsps_wind_hann_f32(wind, NUM_SAMPLES);
    // Generate input signal for x1 A=1 , F=0.1
    // dsps_tone_gen_f32(x1, N, 1.0, 0.1,  0);
    // for(int i=0; i<N;i++){
    //     ESP_LOGI(TAG, "Signal at index %i is %f", i, x1[i]);
    // }

    // Generate input signal for x2 A=0.1,F=0.2
    //dsps_tone_gen_f32(x2, N, 0.1, 0.2, 0);

    // Convert two input vectors to one complex vector
    for (int i = 0 ; i < NUM_SAMPLES ; i++) {
        y_cf[i * 2] = wave[i] * wind[i];
        y_cf[i * 2 + 1] = 0; // I don't have a second vector as in the example
    }
    // FFT
    unsigned int start_b = dsp_get_cpu_cycle_count();
    dsps_fft2r_fc32(y_cf, NUM_SAMPLES);
    unsigned int end_b = dsp_get_cpu_cycle_count();
    // Bit reverse
    dsps_bit_rev_fc32(y_cf, NUM_SAMPLES);
    // Convert one complex vector to two complex vectors
    dsps_cplx2reC_fc32(y_cf, NUM_SAMPLES);

    //RETRIEVE THE MAX FREQ OF THE SIGNAL
    int maxI = 0;
    double maxM = 0;
    for (int i = 0; i < NUM_SAMPLES; i++)
    {
        if(y_cf[i]>TH && y_cf[i]>maxM){
            maxI = i;
            maxM = y_cf[i];
        }
    }
    ESP_LOGI(TAG, "THE MAX Index is %i", maxI);
    float maxF = maxI;
    maxF *= SAMPLING_RATE / (float) NUM_SAMPLES; //max frequency retrival

Then the example code does some adjustment in order to display the signals correctly. Obviously here I'm expecting that the max frequency should be something around 5Hz. But in the output I'm getting: I (22594) main: THE MAX Index is 1838 I (22944) main: The maximum frequency of the signal is 612.666687, and the relative magnitude value is 564.219421.

I've been following various guides and I think that is the proper way to get the max frequency. Can somebody tell me what I'm doing wrong ?


Solution

  • I eventually found out that the FFT needs in input an array of a dimension that has to be expressible as a power of 2.