• AVR Freaks

Hot!dsPIC33FJ256GP710A FFT output not looking correct

Author
GreenDragonSA
New Member
  • Total Posts : 23
  • Reward points : 0
  • Joined: 2012/04/16 01:44:33
  • Location: 0
  • Status: offline
2019/09/18 07:13:34 (permalink)
0

dsPIC33FJ256GP710A FFT output not looking correct

Hello All.
 
Yip another FFT question. Looked at forum but struggling to find what I am seeing.
 
Used the CE018 FFT example and looks good except for:
1st (50Hz) Looks good.
5th (250Hz) <- My problem child is that this bar should be at least 50% of the 1st bar.
 
FFT_BLOCK_LENGTH 64 (Need the RAM on a load of other thinds :P)
LOG2_BLOCK_LENGTH 6
SAMPLING_RATE 3200
 
Attached is load that is being injected.
ADC reading as fraction Q1.15.
 
Then goes through C018 and I am just plotting the Q1.15 result as an integer.
 
      
      FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], &twiddleFactors[0], COEFFS_IN_DATA);
      BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]);
      SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real);

 
Would appreciate any help.
 

Attached Image(s)

#1

8 Replies Related Threads

    du00000001
    Just Some Member
    • Total Posts : 3076
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/18 09:39:43 (permalink)
    0
    GreenDragonSA
    FFT_BLOCK_LENGTH 64 (Need the RAM on a load of other thinds :P)

    • The block is somewhat short considering the lowest frequencies possible.
    • What's your signal that you're expecting a larger f5 but accept an f3 of 0 ?
    Overall: might have to do with the little data available.

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #2
    Nikolay_Po
    Super Member
    • Total Posts : 1897
    • Reward points : 0
    • Joined: 2012/04/01 13:49:27
    • Location: Russia, Novorossiysk
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/18 11:19:17 (permalink)
    0
    Frikkie, is your signal synchronized with sampling period? Is the spectrum the same very time? Why your array length is 65?
    #3
    davekw7x
    Entropy++
    • Total Posts : 1827
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Second star on the right, straight on till morning
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/19 12:52:31 (permalink)
    5 (2)
    frikkiemarais
    ...struggling...
    ...
    ADC reading as fraction Q1.15.

    Since I couldn't glean enough information from your post to see (or guess) why your results don't match your expectations, I'll make a couple of general observations and suggest a way that may get you a little further along.

    I did a fair amound of DSP work a few years ago (not with PIC devices and libraries), and I found four sticking points, which I will list in order of increasing probability (least likely first):
    • Library code is faulty.  Probably not, but it's always possible that OPC (Other People's Code) is buggy.
    • The library code is correct but I wasn't calling it correctly.  Maybe a documentation deficiency, but more probably my fault  It's always possible that even my code is buggy.  Really.  It could happen.
    • Results were correct but I interpreted them incorrectly.  Happened a lot, especially when I first studied DSP.  Way Back When the only bible was Oppenheim and Shafer and examples in FORTRAN were in a couple of hardback IEEE publications.
    • Input signals were incorrect.  Either incorrectly measured values or values not in the correct order in a properly sized array.  That's why I always started with mathematically correct values and made sure everything worked as expected before turning the program loose with real-world data.

    I'll start with the last one:
    Instead of trying to figure out what the heck is happening with input captured from an ADC,  why not just generate a specific set of input data and see if the results make sense?

    For example, I made a little python program to generate some time-domain sample values and create the code to put them into an array consistent with the way it is used in CE018.  I think this might be something close to what you are trying to test, but I can't really tell whether this is what you had in mind.


    // FFT_BLOCK_LENGTH = 64
    // Sample frequency = 3200 Hz
    // Frequency 1 =  50 Hz, Amplitude = 0.250
    // Frequency 2 = 250 Hz, Amplitude = 0.125
    //
    fractcomplex sigCmpx[FFT_BLOCK_LENGTH]
    __attribute__ ((section (".ydata, data, ymemory"), aligned (FFT_BLOCK_LENGTH * 2 *2))) =
    {
        {0x0000, 0}, {0x0AAE, 0}, {0x138C, 0}, {0x1936, 0},
        {0x1B07, 0}, {0x193C, 0}, {0x14E6, 0}, {0x0FA8, 0},
        {0x0B50, 0}, {0x096D, 0}, {0x0AEA, 0}, {0x0FDA, 0},
        {0x1771, 0}, {0x2031, 0}, {0x2846, 0}, {0x2DF5, 0},
        {0x3000, 0}, {0x2DF5, 0}, {0x2846, 0}, {0x2031, 0},
        {0x1771, 0}, {0x0FDA, 0}, {0x0AEA, 0}, {0x096D, 0},
        {0x0B50, 0}, {0x0FA8, 0}, {0x14E6, 0}, {0x193C, 0},
        {0x1B07, 0}, {0x1936, 0}, {0x138C, 0}, {0x0AAE, 0},
        {0x0000, 0}, {0xF552, 0}, {0xEC74, 0}, {0xE6CA, 0},
        {0xE4F9, 0}, {0xE6C4, 0}, {0xEB1A, 0}, {0xF058, 0},
        {0xF4B0, 0}, {0xF693, 0}, {0xF516, 0}, {0xF026, 0},
        {0xE88F, 0}, {0xDFCF, 0}, {0xD7BA, 0}, {0xD20B, 0},
        {0xD000, 0}, {0xD20B, 0}, {0xD7BA, 0}, {0xDFCF, 0},
        {0xE88F, 0}, {0xF026, 0}, {0xF516, 0}, {0xF693, 0},
        {0xF4B0, 0}, {0xF058, 0}, {0xEB1A, 0}, {0xE6C4, 0},
        {0xE4F9, 0}, {0xE6CA, 0}, {0xEC74, 0}, {0xF552, 0}
    };


    The attachment shows a plot of the 64 real-valued samples that were used to generate the Q15.1 Q1.15 entries in the above table.

    Bottom line: What happens when you try this in your program?

    If this doesn't help, then how about showing what is in your sigCmpx array before and after the call to the FFT function?  What is in the array after you do the Bit Reverse?

    Note that I simply never depend on the IDE to show me what is in an array (or any bloomin' thing else) for my test/evaluation programs.  I just print out the values.  That way I can save the results for my notes and I can share the results with others who might be interested.


    Regards,

    Dave
    post edited by davekw7x - 2019/09/20 16:23:28

    Attached Image(s)


    Sometimes I just can't help myself...
    #4
    GreenDragonSA
    New Member
    • Total Posts : 23
    • Reward points : 0
    • Joined: 2012/04/16 01:44:33
    • Location: 0
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/20 10:50:57 (permalink)
    0
    Thanks for the all the responses.
     
     
    @du00000001  

     
    Was expecting f5 to be at least 50% of f1 amplitude.
     
    @nik
    Sample rate at 3200 Hz (312.5 uS) interval to sample with ADC with a timer interrupt.
    Will need to correct the 65 to 64 samples. Must have been a typo in my code.
     
    @Dave
    Will try a fix signal and see if I get the same result or different.
    But what I am expecting is f5 to be at least 50% the size of f1 as I am injecting 50% amplitude of f1.
     
    Will give feedback as soon as I feed the array the fix signal to see if I see a difference.
     
    Will also redo the signal and do a compare between actual (From injection set) and simulated signal (From the array that you provided).
     
    Regards,
    Frikkie
    #5
    du00000001
    Just Some Member
    • Total Posts : 3076
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/20 11:04:38 (permalink)
    0
    GreenDragonSA
    ... as I am injecting 50% amplitude of f1.

    Did you check (scope) that the input signal is ok?

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #6
    davekw7x
    Entropy++
    • Total Posts : 1827
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Second star on the right, straight on till morning
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/20 16:16:13 (permalink)
    5 (1)
    frikkiemarais
    @Dave
    ...
    But what I am expecting is f5 to be at least 50% the size of f1 as I am injecting 50% amplitude of f1.


    Then you need to study a little more and LOOK at and THINK about what the functions are doing.

    To recap:
    The input that I supplied in my previous post consists of the Q1.15 values of a 50 Hz sinusoid with amplitude 0.25 plus a 250 Hz sinusoid with amplitude 0.125.  This ensures that all samples correspond to real values  between -0.5 and +0.5, which, as mentioned in CD018, is required to make sure the transform function does not overflow.

    So, here's the deal:
    With a sample frequency of 3200 Hz, the 64 samples of this mathematically perfect waveform constitute a single period of 50 Hz (and, therefore five periods of the 250 Hz component).

    The frequency represented by each bin in the frequency domain is the sample frequency divided by the number of samples.

    The result from the FFT function has exactly two non-zero positive-frequency bins: bin number 1, corresponding to 50 Hz and bin number 5, corresponding to 250 Hz. [Edit] The complex complements of these appear in the "negative frequency"  bins 63 and 59.  I'll just concentrate on bins 1 and 5, since those are what you are asking about[/Edit]

    For test purposes, I converted the Q1.15 values to  real values (using _itofQ15()) and I got an absolute value of 0.125 for bin 1 and 0.0625 for bin 5.
    Yep, bin 5's value is half that of bin 1.  That's what I expected

    Now You indicated that you ran it though the SquareMagnitudeCplx() function, as CE018 did, and from that I get a value of 0.015625 for bin 1 (that's 0.125 squared) and 0.0039625 (that's 0.0625 squared) for bin 5.  So, the number in bin 5 represents one fourth the power captured in bin 1.  That's what I expected.

    I asked you what you got at each step.  I printed out affected array values at each step so that I could see exactly was going on..

    The attachment shows outputs at various steps.  I print the complex-valued Q1.15 values in the array, followed by a print of the real valued equivalents.  This is the output from a test program on my dsPIC33FJ256GP710A test circuit. [Edit]I have replaced the attachment with output that shows outputs for all 64 bins. Because of symmetry it's not really necessary to look at all of the bins in the frequency domain, and for some of the steps I only showed half of the array. For purposes of illustration I guess I should have shown all of them.  That's why I changed it.[/Edit]

    Bottom line: For a mathematically perfect signal, PSD (Power Spectral Density) is accurately represented by the  results of the FFT and following functions.  See Footnote.

    Regards,

    Dave

    Footnote:
    An estimate of the PSD of an actual, real-world signal requires a lot more work than a single FFT.  I'll leave the details up to your study.  My intent here is to show that the FFT function can give reasonable results if you treat it properly.
    post edited by davekw7x - 2019/09/20 19:06:59

    Sometimes I just can't help myself...
    #7
    Nikolay_Po
    Super Member
    • Total Posts : 1897
    • Reward points : 0
    • Joined: 2012/04/01 13:49:27
    • Location: Russia, Novorossiysk
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/21 01:40:44 (permalink)
    0
    Dave, please, explain what you have used as a source for your "After IFFT" result? What source data and what function exactly?
    #8
    davekw7x
    Entropy++
    • Total Posts : 1827
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Second star on the right, straight on till morning
    • Status: offline
    Re: dsPIC33FJ256GP710A FFT output not looking correct 2019/09/21 06:30:37 (permalink)
    0
    Nikolay_Po
    ..."After IFFT" result? What source data and what function exactly?




        // Do FFTComplexIP and BitReverseComplex for in-place calculations
        // of the original data in sigCmpx, then do the following

        // Note that the code in CE018 overwrites values in the first
        // 64 words of sigCmpx, but I want to use sigCmpx later
        // for the IFFT, so for test purposes I write square magnitude
        // values somewhere else

        fractional sqm[FFT_BLOCK_LENGTH];
        SquareMagnitudeCplx(FFT_BLOCK_LENGTH, sigCmpx, sqm);
        printf("After SquareMagnitudeCplx:");
        print_frac_array(sqm, FFT_BLOCK_LENGTH);
        for (i = 0; i < FFT_BLOCK_LENGTH; i++) {
            if (i % 4 == 0) {
                printf("\r\n ");
            }
            printf("%e ", _itofQ15(sqm[i]));
        }
        printf("\r\n");
        printf("First: %e\r\n", _itofQ15(sqm[1]));
        printf("Fifth: %e\r\n", _itofQ15(sqm[5]));
        printf("\r\n");

        // Now do IFFTComplex to write the inverse values back into
        // sigCmpx

        IFFTComplexIP(LOG2_BLOCK_LENGTH, sigCmpx], (fractcomplex *) __builtin_psvoffset(invtwiddleFactors), (int) __builtin_psvpage(invtwiddleFactors));

        printf("After IFFT:");
        print_fc_array(sigCmpx, FFT_BLOCK_LENGTH);

        uint16_t scale = FFT_BLOCK_LENGTH;
        for (i = 0; i < FFT_BLOCK_LENGTH; i++) {
            sigCmpx[i].real *= scale;
            sigCmpx[i].imag *= scale;
        }

        printf("\r\nAfter scaling:");
        print_fc_array(sigCmpx, FFT_BLOCK_LENGTH);
        print_fcreal_array(sigCmpx, FFT_BLOCK_LENGTH);


    Where

    void print_fc_array(fractcomplex *x, uint16_t len)
    {
        uint16_t i;
        for (i = 0; i < len; i++) {
            if (i % 4 == 0) {
                printf("\r\n ");
            }
            printf(" {0x%04X, 0x%04X}", x[i].real, x[i].imag);
        }
        printf("\r\n");
    }


    And

    void print_fcreal_array(fractcomplex *x, uint16_t len)
    {
        int i;
        for (i = 0; i < FFT_BLOCK_LENGTH; i++) {
            double dp = _itofQ15(x[i].real);
            double di = _itofQ15(x[i].imag);
            if (i % 4 == 0) {
                printf("\r\n");
            }
            printf(" (%7.4f, %7.4f)", dp, di);
        }
        printf("\r\n");
    }


    _itofQ15() is in libq-dsp-elf.a and its prototype is in "libq.h"
    Other functions are in libdsp-elf.a and prototypes are in "dsp.h"


    Regards,

    Dave


    post edited by davekw7x - 2019/09/21 06:43:19

    Sometimes I just can't help myself...
    #9
    Jump to:
    © 2019 APG vNext Commercial Version 4.5