Other Parts Discussed in Thread: C2000WARE
I have successfully implemented 32 & 128 point Real FFTs using the VCU2 library. The 128 point RFFT was performed using 64 point CFFT. Now we need to increase the points to 256 so I am working on 128 points complex FFT. I have allocated an input and output buffer aligned to 256 in the RAM. The declarations are as below:
//Input buffer is allocated to 256 words aligned section in RAM #pragma DATA_SECTION(Vgrid_FFT_in_buf,"buffer1") int16_t Vgrid_FFT_in_buf[256]; //Output buffer is allocated to 256 words aligned section in RAM #pragma DATA_SECTION(Vgrid_FFT_out_buf,"buffer2") int16_t Vgrid_FFT_out_buf[256];
The sections are defined in the linker file as below:
/* Allocate twiddle factors area: */ twiddleFactors : > FLASHA_N, PAGE = 0 /*Allocate areas for 32 points RFFT input and output buffers*/ buffer1 : > RAMLS_PROG, ALIGN = 256, PAGE = 0 buffer2 : > RAMLS_PROG, ALIGN = 256, PAGE = 0
The FFT handler is initialized as below:
CFFT.pInBuffer = Vgrid_FFT_in_buf; CFFT.pOutBuffer = Vgrid_FFT_out_buf; CFFT.init = (void (*)(void*)) CFFT_init128Pt; CFFT.run = (void (*)(void*)) CFFT_run128Pt; // Step 2: Initialize the handle handleCFFT = &CFFT;
To test the code I have generated one complete cycle of the below signal with 256 points sampling.
x= 2000+ 1000*sin(t)+700*sin(2*t)+500*sin(3*t);
The sampled signal is stored in 256 length uint16_t array as shown below:
uint16_t matlab_sig[256] = { 2000, 2096, 2191, 2286, 2380, 2472, 2564, 2653, 2741, 2826, 2909, 2989, 3066, 3139, 3210, 3277, 3340, 3399, 3454, 3504, 3551, 3593, 3631, 3664, 3693, 3717, 3736, 3751, 3762, 3768, 3770, 3767, 3761, 3750, 3735, 3717, 3695, 3670, 3642, 3610, 3576, 3539, 3500, 3458, 3415, 3370, 3324, 3276, 3228, 3178, 3129, 3079, 3029, 2979, 2930, 2881, 2833, 2786, 2740, 2696, 2653, 2612, 2573, 2535, 2500, 2467, 2436, 2407, 2380, 2356, 2334, 2314, 2297, 2282, 2270, 2259, 2251, 2245, 2240, 2238, 2238, 2239, 2241, 2245, 2251, 2257, 2265, 2273, 2282, 2292, 2302, 2312, 2322, 2332, 2342, 2352, 2361, 2369, 2377, 2383, 2389, 2393, 2397, 2399, 2399, 2398, 2396, 2392, 2387, 2380, 2371, 2361, 2350, 2336, 2322, 2305, 2288, 2269, 2249, 2227, 2205, 2182, 2157, 2132, 2107, 2080, 2054, 2027, 2000, 1973, 1946, 1920, 1893, 1868, 1843, 1818, 1795, 1773, 1751, 1731, 1712, 1695, 1678, 1664, 1650, 1639, 1629, 1620, 1613, 1608, 1604, 1602, 1601, 1601, 1603, 1607, 1611, 1617, 1623, 1631, 1639, 1648, 1658, 1668, 1678, 1688, 1698, 1708, 1718, 1727, 1735, 1743, 1749, 1755, 1759, 1761, 1762, 1762, 1760, 1755, 1749, 1741, 1730, 1718, 1703, 1686, 1666, 1644, 1620, 1593, 1564, 1533, 1500, 1465, 1427, 1388, 1347, 1304, 1260, 1214, 1167, 1119, 1070, 1021, 971, 921, 871, 822, 772, 724, 676, 630, 585, 542, 500, 461, 424, 390, 358, 330, 305, 283, 265, 250, 239, 233, 230, 232, 238, 249, 264, 283, 307, 336, 369, 407, 449, 496, 546, 601, 660, 723, 790, 861, 934, 1011, 1091, 1174, 1259, 1347, 1436, 1528, 1620, 1714, 1809, 1904 };
So there is a dc component of 2000, first harmonic of 1000, 2nd of 700 and third of 500 Vpk.
Following is my function that performs the actual FFT.
static inline void calculate_THD(void) { uint16_t i, j; float32_t THD; //NOTE:Consider using memcpy for (i = 0; i < 256; i++) { Vgrid_FFT_in_buf[i] = matlab_sig[i]; } //running FFT on grid voltage samples CFFT.run(handleCFFT); //Unpacking is required as 128 point real FFT is performed using 64 points complex FFT. CFFT_unpack(handleCFFT); //Post processing FFT results magFFT[0] = CFFT.pOutBuffer[0] * 0.0313 * 5; //Calculating magnitude till 7th harmonic for (i = 1; i < 8; i++) { j = 2 * i; magFFT[i] = sqrtf(((float) CFFT.pOutBuffer[j] * (float) CFFT.pOutBuffer[j]) + ((float) CFFT.pOutBuffer[j + 1] * (float) CFFT.pOutBuffer[j + 1])); //scaling factor is (1/2^12)/Vgrid1_gain = 0.0313 //furthermore the library scales the ouput result by N where 2^N = # of samples. for 32 samples N=5. //since we are measuring a single phase so we scale by 2 to measure line to line voltages. magFFT[i] = magFFT[i] * 0.02901 * 5 * 2; //0.0313 prev gain } THD = 0.0f; for (i = 2; i < 8; i++) { THD = magFFT[i] * magFFT[i] + THD; } THD = sqrtf(THD); //Updating array of harmonics effective values //Shifting all values one left. Discrading the oldest value. for (i = 15; i > 0; i--) { harm_eff_values[i] = harm_eff_values[i - 1]; } harm_eff_values[0] = THD; //Updating array of fundamental values for (i = 5; i > 0; i--) { fundamental_values[i] = fundamental_values[i - 1]; } fundamental_values[0] = magFFT[1]; fft_updated = true; }
Now coming to the problem: First call to this function gives correct results but the next call gives wrong results and this continues for all successive call i.e a call giving correct results and the next call giving incorrect results.
Please find below the results captured from the watch window of debug:
Correct results:
Incorrect results:
Note that I am calling the function every 5 seconds so that the watch window has enough time to refresh. I have been trying to troubleshoot it my self but no success so far. I am using C2000Ware 4.0.2 and the compiler version is 22.6.0.LTS. Let me know if more information is needed.