1

At the moment I am attempting to implement a program for finding 3 frequencies (xs = 30.1 kHz, ys = 28.3 kHz and zs = 25.9 kHz) through the use of the CMSIS pack on the STM32F411RE board. I cannot get the Complex FFT (CFFT) and complex magnitude working correctly.

In accordance with the freqeuncy bins I generate an array containing these frequencies, so that I can manually lookup which index bins the signals xs, ys and zs are on. I then use this index to look at the 3 fft outcomes (Xfft, Yfft, Zfft) to find the outcomes for these signals, but they dont match up.

I use the following order of functions:

DMA ADC Buffer: HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
Freqeuncy bins in binfreqs
Change ADC input to float Xfft
CFFT_F32: arm_cfft_f32(&arm_cfft_sR_f32_len1024, Xfft, 0, 0);
Complex Mag: arm_cmplx_mag_f32(Xfft, Xdsp, fftLen);

// ADC Stuff done via DMA, working correctly

int main(void)
{

    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_ADC1_Init();
    MX_USART2_UART_Init();
    HAL_ADC_Start_DMA(&hadc1, adc_buffer, bufferLen); // adc_buffer needs to be an uint32_t

   while (1)
    {

        /**
         * Generate the frequencies
         */
        for (int binfreqs = 0; binfreqs < fftLen; binfreqs++)   // Generates the frequency bins to relate the amplitude to an actual value, rather than a bin frequency value
        {
            fftFreq[binfreqs] = binfreqs * binSize;
        }

        /*
         * Find the amplitudes associated with the 3 emitter frequencies and store in an array for each axis. By default these arrays are generated with signal strength 0
         *  and with frequency index at 0: because of system limits these will indicate invalid values, as system range is from 10 - 60 kHz.
         */
        volatile int32_t X_mag[3][4] =  // x axis values: [index][frequency][signal_strength][phase]
        {
            {0, Xfreq, 0, 0},   // For x-freq index [0][0], frequency [0][1] associated with 1st biggest amplitude [0][2], phase [0][3]
            {0, Yfreq, 0, 0},   // Ditto for y-freq
            {0, Zfreq, 0, 0}    // Ditto for z-freq
        };


        /*
         * Finds the index in fftFreq corresponding to respectively X, Y and Z emitter frequencies
         */
        for(int binSearch = 0; binSearch < fftLen; binSearch++)
        {
            if(fftFreq[binSearch] == Xfreq) // Find index for X emitter frequency
            {
              X_mag[0][0] = binSearch;
            }

            if(fftFreq[binSearch] == Yfreq) // Find index for Y emitter frequency
            {
              X_mag[1][0] = binSearch;
            }

            if(fftFreq[binSearch] == Zfreq) // Find index for Z emitter frequency
            {
              X_mag[2][0] = binSearch;
            }
        }

Signal processing


        /* Signal processing algorithms --------------------------------------------------
         *
         * Only to be run once with fresh data from the buffer, [do not run continuous] or position / orientation data will be repeated.
         * So only run once when conversionPaused
         */
        if(conversionPaused)
        {

            /*
             * Convert signal to voltage (12-bit, 4096)
             */
            for (int floatVals = 0; floatVals < fftLen; floatVals++)
            {
                Xfft[floatVals] = (float) Xin[floatVals]; * 3.6 / 4096
            }

            /*
             * Fourier transform
             */
            arm_cfft_f32(&arm_cfft_sR_f32_len1024, Xfft, 0, 0); // Calculate complex fourier transform of x time signal, processing occurs in place

            for (int fix_fft = 0 ; fix_fft < half_fftLen ; fix_fft++)
            {
                Xfft[fix_fft] = 2 * Xfft[fix_fft] / fftLen;
                Xfft[fix_fft + half_fftLen] = 0;
            }

           /*
            * Amplitude calculation
            */
            arm_cmplx_mag_f32(Xfft, Xdsp, fftLen);  // Calculate the magnitude of the fourier transform for x axis

            /*
             *  Finds all signal strengths for allocated frequency indexes
             */
            for(int strength_index = 0; strength_index < 3; strength_index++) // Loops through xyz frequencies for all 3 magnetometer axis
            {
                int x_temp_index = X_mag[strength_index][0]; // temp int necessary to store the strength, otherwise infinite loop?
                X_mag[strength_index][2] = Xfft[x_temp_index]; // = Xfft[2*x_temp_index];

            }
            conversionPaused = 0;
          }
      } // While() end
} // Main() end

I do not know how I am to calculate the frequency bins for this combination of cfft and complex magnitude, as I would expect the even indexes of the array to hold the real values and the odd indexes of the array to hold the imaginary phase values. I reference some 1 2 3 examples but could not make out what I am doing wrong with my code.

However as per the images when applying an input signal of 30.1 kHz neither the 301 bin index or the 602 bin index holds the corresponding output expected?

301 bin index

602 bin index


EDIT:

I have since tried to implement the arm_cfft_f32 example given here. This latter example is completely broken as the external 10 kHz dataset is no longer included by default and trying to include it is not possible, as the program behaves poorly and keeps erroring about a return data type that is not even present in the first place. Thus I cannot use the example program given for this: it also appears to be 4 years out of date, so that is not surprising.

The arm_max_f32() function also proved not fruitful as it keeps homing in on the noise generated at bin 0 via using an analog generated signal. Manually setting this bin 0 to equal 0 then upsets the algorithm which starts pointing to random values that are not even the largest value present in the system.

Even when going manually through the CFFT data and magnitude it appears as if they are not working correctly. There are random noise values all over the spectrum parts, whilst the oscilloscope confirms that large outcomes should only be present at 0 Hz and the selected signal generator frequency (thus corresponding to a frequency bin).

Using CMSIS is extremely frustrating for me because of the little documentation and examples available, which is then further reduced by most of it simply not working (without major modification).

Nanne118
  • 125
  • 1
  • 13

0 Answers0