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.

Have a trouble with ADC-FFT.

Other Parts Discussed in Thread: TMS320F28377D, CONTROLSUITE

I'm using TMS320F28377D and it's docking station.

While doing ADC - FFT programming, I have a trouble.

The trouble is..

When I use 60Hz sine wave as input, my FFT magnitude plot has 120Hz pitched wave.

Also, when I use 120Hz, FFT mag has 240Hz pitch.

Is it a code problem or another problem such as function generator or something?

  • Hi,

    Are you using the FPU DSP library 1.50.00.00, RFFT_adc_f32()? Can you post the graph of the magnitude as well as the details of the FFT (size) - did you try the example in the library?

  • Dear Vishal

    I believe I use a example FFT code from TI.

    And, here is a mag-graph and a setting for graph. 

    Also, I have one more thing to ask. Even I pick 'Frequency Display Unit' as 'Hz', x-axis scale stayed in 'sample'. Is it program problem?

    If not, how can I chance x-axis scale to 'Hz'?

    Thank you for your reply.

    Sincerely

  • Ok if you refer to the example: C:\ti\controlSUITE\libs\dsp\FPU\v1_50_00_00\examples\fft\2837x_rfft_adc

    It calls RFFT_adc_f32 followed by RFFT_f32_mag(). I was hoping to see the graph (single time graph) of "RFFTmagBuff". It looks like you have used the CCS graph FFT property to plot the FFT of the raw input - am i wrong?

    Also, it looks like you are using a 512 point real FFT with sampling frequency of 2KHz in which case after you run the magnitude function you should see a peak in the (60*512)/2000 = 15.36 ~15th bin with some leakage in the surrounding bins.

  • Dear Vishal.

    This is single time plot for "RFFTmagBuff"

    I think it is the same plot with a case when I copy "RFFTmagBuff" array and plot it in Matlab.

    Also, I changed buffer size to 256, then, I should see peak value around 7th bin (60*256/2000). Is it right?

    Thank you.

    Sinverely

  • Hmm, i only see a DC peak. Something is wrong with the input - it looks like you are sampling DC

    kyungin nam said:
    Also, I changed buffer size to 256, then, I should see peak value around 7th bin (60*256/2000). Is it right?

    No the bin is determined by the sampling frequency and size of the FFT not buffer size. so bin = (60 Hz * FFT_SIZE)/F_s

    So it should still be the 15th bin. The RFFT routine only calculates the spectrum from DC to nyquist (F_s/2) because the spectrum of real data is conjugate symmetric about the nyquist point. So the magnitude give you 257 bins (0 to F_s/2) just half the spectrum

  • Dear Vishal

    Is it correct single time plot for "RFFTmagBuff"?

    If so, I had a mistake in a last post. Sorry.

    Can I find the reason why I have this problem in this plot?

  • No the plot is incorrect. I think there is a problem with the sampled input. What i suggest you do is plot the input after its sampled by the ADC and make sure you are seeing a 60Hz sinusoidal wave.

    You should only see a single large peak at the 15th bin and small peaks in the surrounding bins and then the noise floor everywhere else.
  • Dear Vishal.

    I solved a problem. Thank you.

    I have something to ask related code composer studio.

    As you know, I'm using 'RFFT_f32_mag' function for FFT In code composer studio.


    In result in 'RFFTmagBuff' float array form, I got 2 questions to ask you.

    1. There is a difference between each float values in 'RFFTmagBuff' array and a magnitude in FFT magnitude plot.
    Why there is a mismatch?


    2. In FFT magnitude plot, I choose 'Hz' for x-axis, however, x-axis in plot always stay in 'sample'. Is it a program problem?
    How can I change x-axis from 'sample' to 'Hz'? ]

  • Hy to all, my name is Paul and i'm new users of C2000 MCU.

    Sorry for my bad English, It's little low!

    I'm using F28377S delfino launchpad to perform FFT spectral measurement.

    Input signal is a square wave of 50 Hz, 50% duty, 2vpp, 1v average.

    Futhermore i'm using FPU library, in particular RFFT_f32();  and RFFT_f32_mag();  

    FFTSIZE = 2048, Fsample = 2560 --> Spectral resolution is 2560/2048 = 1,25 Hz.

    I don't understand why the magnitude of FFT is so high, the dc component is 925, and first armonic peack is 550..! What does mean? I see any correlation with input signal amplitude, maybe i am doing something incorrect.

    The code:

    do
    
           {
    
            //start ePWM
    
               EPwm1Regs.ETSEL.bit.SOCAEN = 1;  //enable SOCA
    
               EPwm1Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode
    
            //wait while ePWM causes ADC conversions, which then cause interrupts,
    
            //which fill the results buffer, eventually setting the bufferFull
    
            //flag
    
            while(!bufferFull);
    
            bufferFull = 0; //clear the buffer full flag
    
            //stop ePWM
    
               EPwm1Regs.ETSEL.bit.SOCAEN = 0;  //disable SOCA
    
               EPwm1Regs.TBCTL.bit.CTRMODE = 3; //freeze counter
    
                             //RFFT_f32_win(&RFFTin1Buff[0], (float *)&RFFTwindow, RFFT_SIZE);
    
                        RFFT_f32u(hnd_rfft);
    
                      RFFT_f32_mag(hnd_rfft);
    
      asm("   ESTOP0");
    
           }while(1);
    
    interrupt void adca1_isr(void)
    
    {
    
    RFFTin1Buff[resultsIndex++] =(AdcaResultRegs.ADCRESULT0)*((float)3/4096);
    
    if(RFFT_SIZE<=resultsIndex )
    
    {
    
    resultsIndex = 0;
    
    bufferFull = 1;
    
    }
    
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
    
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    
    }
    
    
    

    The value of samples in input to RFFT_f32() are correct, but is no correct the magnitude, i think it is necessary to appropriately scale the values ​​of magnitude , but the library does not say anything about it.

    Input samples

    FFT module (labview plotting after saving values in txt file from CCS)

    FFT module with windowing BLACKMAN2048 (labview plotting after saving values in txt file from CCS)

    The x scale is correct, effectively the fundamental is 50 Hz and i have all odd armonics up to Nyquist frequency, but i think no correct the module.

    Someone can help me to understand?

    Tanks to all
    Regards

    Paolo.

  • Ok, solved!
    The library computes only magnitude, but to having peak value FFT needs to scale magnitude buffer for FFTSize (in my case 2048) and multiply all magnitude buffer (but no DC bean) for 2.

    Tanks to all
    Paolo
  • So, is anybody there who can solve my problem?~

  • I cant tell if there is a mismatch or not. you can use the marker feature - i think its the 4th icon from the left (top row of the graph) to see what the actual value is at a given point.

    As for the x-axis showing the values in Hz - if its not working that would definitely be an issue with CCS. Make sure you select the display of Hz, but also provide the sampling frequency when you set up the graph.
  • Dear Vishal.

    1. there is still mismatch. I used a function which you taught me. In 1st array value is 218.568008. However, a y-value at first is 68.65. Is it a program issue?

    2. I set 'Hz' for FFT magnitude graph, but y-scale is stay to 'Sample". I think this can be an issue of CCS.

  • Ok it looks like you are doing a magnitude plot of the magnitude. Go to Tools->Graph->Single Time

  • Dear Vishal.

    I did it. However, what does that mean??

    And, it also doesn't match to values in "RFFTmagBuff" array.

  • Please give me a feedback.

    I'm looking forward to have your comment:)

    Thank you

  • Can you graph (using single time graph) just the buffered input data that you got from the ADC? so dont run the RFFT just buffer the data from the ADC and graph it.

  • Dear kyungin , can you use memory browser function for plotting acquired data. You can export data in floating point format, only you need insert address of RFFTmagBuff array.
    Once the samples stored in a file, you can use Matlab or Excel to view spectrum.
    You must create frequency -axis (Fsample/FFT_Size)*k where k go from 0 to (FFT_Size/2 - 1).

    Paolo.

    PS: Post your code if you want.
  • Dear Paolo.

    Thank you for your reply.

    Here is my code for ADC-FFT.

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    //*****************************************************************************
    // includes
    //*****************************************************************************
    #include "fpu_rfft.h"            //Main include file
    #include "math.h"
    #include "examples_setup.h"
    //*****************************************************************************
    // defines
    //*****************************************************************************
    #define RFFT_STAGES     9
    #define RFFT_SIZE       (1 << RFFT_STAGES)
    #define F_PER_SAMPLE    (ADC_SAMPLING_FREQ/(float)RFFT_SIZE)
    //#define EPSILON         2
    #define EPSILON         0.1
    //*****************************************************************************
    // globals
    //*****************************************************************************
    #pragma DATA_SECTION(RFFTin1Buff,"RFFTdata1")
    #pragma DATA_SECTION(RFFTmagBuff,"RFFTdata2")
    #pragma DATA_SECTION(RFFToutBuff,"RFFTdata3")
    #pragma DATA_SECTION(RFFTF32Coef,"RFFTdata4")
    //uint16_t RFFTin1Buff[2*RFFT_SIZE];
    uint16_t RFFTin1Buff[RFFT_SIZE];
    //float RFFTmagBuff[RFFT_SIZE];
    float RFFTmagBuff[RFFT_SIZE/2+1];
    //float RFFTmagBuff[RFFT_SIZE+1];
    float RFFToutBuff[RFFT_SIZE];
    float RFFTF32Coef[RFFT_SIZE];

    RFFT_ADC_F32_STRUCT rfft_adc;           //brief RFFT_ADC_F32_STRUCT object
    RFFT_ADC_F32_STRUCT_Handle hnd_rfft_adc = &rfft_adc; //brief Handle to the RFFT_ADC_F32_STRUCT object
    RFFT_F32_STRUCT rfft;                   //brief RFFT_F32_STRUCT object
    RFFT_F32_STRUCT_Handle hnd_rfft = &rfft;//brief Handle to the RFFT_F32_STRUCT object
    volatile uint16_t flagInputReady = 0;   //brief Flag to signal the ADC has finished sampling,
                                            //and storing, N points in the FFT input buffer
    volatile uint16_t sampleIndex = 0;      //brief Index into the FFT input buffer
    uint16_t pass = 0;
    uint16_t fail = 0;

    interrupt void adcaIsr();

    int16_t main(void)
    {
        uint16_t i, j;                          //Locals
        float freq = 0.0;
    #ifdef FLASH
        EALLOW;
        Flash0EccRegs.ECC_ENABLE.bit.ENABLE = 0;
        memcpy((uint32_t *)&RamfuncsRunStart, (uint32_t *)&RamfuncsLoadStart,
                (uint32_t)&RamfuncsLoadSize );
        FPU_initFlash();
    #endif                                      //FLASH
        FPU_initSystemClocks();
        FPU_initEpie();
        FPU_initADCA();                         //Setup ADC-A
        FPU_initEPWM();                         //Setup EPWM1A as the sampling clock, EPWM2A as the signal to be sampled
        EALLOW;                                 //Map ISR functions
        PieVectTable.ADCA1_INT = &adcaIsr;      //function for ADCA interrupt 1
        EDIS;                                   //Enable global Interrupts and higher priority real-time debug events:
        PieCtrlRegs.PIEIER1.bit.INTx1 = 1;      //Enable ADC1INT
        IER |= M_INT1;                          //Enable group 1 interrupts
        EINT;                                   //Enable Global interrupt INTM
        ERTM;                                   //Enable Global realtime interrupt DBGM
        FPU_startEPWM();                        //Start up the EPWMs
        hnd_rfft_adc->Tail = &(hnd_rfft->OutBuf);
        hnd_rfft->FFTSize   = RFFT_SIZE;        //FFT size
        hnd_rfft->FFTStages = RFFT_STAGES;      //FFT stages
        hnd_rfft_adc->InBuf = &RFFTin1Buff[0];  //Input buffer (12-bit ADC) input
        hnd_rfft->OutBuf    = &RFFToutBuff[0];  //Output buffer
        hnd_rfft->CosSinBuf = &RFFTF32Coef[0];  //Twiddle factor
        hnd_rfft->MagBuf    = &RFFTmagBuff[0];  //Magnitude output buffer

        RFFT_f32_sincostable(hnd_rfft);         //Calculate twiddle factor
        for (i=0; i < RFFT_SIZE; i++){
            RFFToutBuff[i] = 0;                 //Clean up output buffer
        }
        for (i=0; i < RFFT_SIZE; i++){          //  /2
            RFFTmagBuff[i] = 0;                 //Clean up magnitude buffer
        }
        while(1){
            while(flagInputReady == 0){};       //Wait on ADC ISR to set the flag before proceeding
            RFFT_adc_f32(hnd_rfft_adc);         //Calculate real FFT with 12-bit ADC input
            flagInputReady = 0;                 //Reset the flag
            RFFT_f32_mag(hnd_rfft);             //Calculate magnitude
            //RFFT_f32_mag_TMU0(hnd_rfft);
            j = 1;
            freq = RFFTmagBuff[1];
            for(i=2;i<RFFT_SIZE/2;i++){         //RFFT_SIZE/2
                                                //Looking for the maximum component of frequency spectrum
                if(RFFTmagBuff[i] > freq){
                    j = i;
                    freq = RFFTmagBuff[i];
                }
            }
            freq = F_PER_SAMPLE * (float)j;
        }
        return 1;
    }
    __interrupt void adcaIsr()
    {
        RFFTin1Buff[sampleIndex++] = AdcaResultRegs.ADCRESULT0;
        if(sampleIndex == (RFFT_SIZE - 1) ){
            sampleIndex = 0;
            flagInputReady = 1;
        }
        AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    Thank you!

  • Dear Paolo.

    I'm looking forward to get your reply.

    Thanks.

  • Hi Paolo,

    I'm a new user trying to implement FFT function out of F28377s. Can you give me some idea where to find the FPU library more exactly? And also, I'm wondering if the FFT function can catch both real and imaginary parts that shows phase.

    Thank you.

    Lang

  • Hello dear Lang,

    you can find all necessary in control Suite.

    Open controlSuite  and go in Libraries-->DSP Libraries-->Floating Point-->Documentation-->C28x FPU DSP Libraries User's Guide.

    You have all instrunction to install and use library.

    In your case you have two ways to  reach the goal:

    1)  catch only OutBuf ant then compute separately Magnitude and Phase applying formulas.

    2) catch Magnitude and Phase directly.

    I like 2) because library compute all for you ;)

    You can write someting like that:

    #include "fpu\_rfft.h"
    #define RFFT_STAGES 8 
    #define RFFT_SIZE (1 << RFFT_STAGES)
    
    #pragma DATA_SECTION(RFFTin1Buff,"RFFTdata1");
    float32 RFFTin1Buff[RFFT_SIZE];
    
    #pragma DATA_SECTION(RFFToutBuff,"RFFTdata2");
    float32 RFFToutBuff[RFFT_SIZE];
    
    #pragma DATA_SECTION(RFFTmagBuff,"RFFTdata3");
    float32 RFFTmagBuff[RFFT_SIZE/2+1];
    
    #pragma DATA_SECTION(RFFTF32Coef,"RFFTdata4");
    float32 RFFTF32Coef[RFFT_SIZE];
    
    #pragma DATA_SECTION(RFFTF32Coef,"RFFTdata4");
    float32 RFFTF32PhaseBuf[RFFT_SIZE/2];
    
    
    
    RFFT_F32_STRUCT rfft;
    RFFT_F32_STRUCT_Handle hnd_rfft = &rfft;
    
    main()
    {
    hnd_rfft->FFTSize = RFFT_SIZE;
    hnd_rfft->FFTStages = RFFT_STAGES;
    hnd_rfft->InBuf = &RFFTin1Buff[0]; //Input buffer
    hnd_rfft->OutBuf = &RFFToutBuff[0]; //Output buffer
    hnd_rfft->MagBuf = &RFFTmagBuff[0]; //Magnitude buffer
    hnd_rfft->PhaseBuf = &RFFTPhaseBuf[0]; //Phase buffer
    hnd_rfft->CosSinBuf = RFFT_f32_twiddleFactors; //Twiddle factor buffer
    
    RFFT_f32_sincostable(hnd_rfft); //Calculate twiddle factor
    RFFT_f32u(hnd_rfft); //Calculate real FFT
    }

    After RFFT_f32u(hnd_rfft) call, you should have FFT phase and magnitude in RFFTF32PhaseBuf and RFFTmagBuff array respectively.

    I hope help you.

    Bye

    Paolo.