FFT Library for Arduino Due, SAM3X

Check this out:
https://cloud.mail.ru/public/FtFv/WorrYQnFB

There's a thread here for library listings, you might want to add that there.

Also what about a fast DCT next :wink:

Yes, I've seen one. Was hoping to get some feedback, before I post there . If someone tested it on win/mac?
I also noticed, that timing results vary between 69xx and 71xx usec, and I can't see a reason.

Does the chip have a cache - that's a common reason for timing variability.

I also noticed, that timing results vary between 69xx and 71xx usec, and I can't see a reason.

The number of cycles for math calcs may depend on the actual operands values..

Hi Magician, First of all thank you for FFT Library for Arduino Due, SAM3X CPU !

I was planing to use example Arduino sketch FFT_ovSerMon_0.1d to run FFT for Signal of 500kHz.Well known for Arduino due is that ADC sampling rate is 1MSPS.

Title Arduino Due II Arduino Due
MCK- Hz 84,000,000 II 84,000,000
Prescaler 2 II 1
ADC Clock 14,000,000 II 21,000,000
ADC Clock Cycle 20 II 20
Sample Speed-Hz 700,000 II 1,050,000
Freq. Range. Max- Hz 350,000 II 525,000
Pockets 2,048 II 2,048
FFT Pockets 1,024 II 1,024

After testing, results are OK if SMP_RATE is less than 600000UL ! My goal is to measure signal up to 500kHz. And for that I need to use prescaler 1 and #define SMP_RATE 1000000UL ! Please advice what changes are required to be done in example sketch? I have tried to change :
t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK5 | // use TCLK5 (prescale by 1, TIMER_CLOCK5 input is equivalent to Master Clock), but no success!

Don't change Timer's prescaler, ADC is using it's own separate prescaler, and this line in adc_setup() defines it:

  adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);

With ADC_FREQ_MAX prescaler sets to 6, that is the best integer divider of 84MHz to get close to 20MHz, according to data sheet max ADC clock. So ADC is running at 14MHz, and that's why you have ~600 ksps.
In order to get full speed, we have to violate data sheet prescription (slightly).
Change to:

  adc_init(ADC, SystemCoreClock, 21000000UL, ADC_STARTUP_FAST);

I'm using next integer divider, 4, and to do trick send 21000000UL directly.
In my experience, arduino ADC can't reach exact 1MSPS, about 960 - 980 ksps at max, so define this line:

#define  SMP_RATE         960000UL

no more, and only one input has to be active:

  adc_enable_channel(ADC, ADC_CHANNEL_7);      // AN0

In my last project
I have two inputs, with SPM_RATE 480000.

HI Magiciant , thanks for your help. For me all working fine when:

#define SMP_RATE 950000UL
adc_init(ADC, SystemCoreClock, 21000000UL, ADC_STARTUP_FAST);
adc_enable_channel(ADC, ADC_CHANNEL_7); // AN0

I can run FFT now up to 475kHz which is OK for me!

Thanks
Vaclav

Hi , i am kind of new with arduino and i would like to display in Processing software a graph of the fft of a signal (pre-amplified) that i am reading from a coil to my arduino, where i could show the different frequencies (from 500 Hz to 30 KHz).

Currently i am using Processing to show the signal and save the data in a file, then i open the file in MATLAB and then MATLAB process the FFT and graph the FFT and the signal.

Does someone know how i can calculate the FFT in my arduino DUE and display it in a Processing graph?

Hello Magiciant, your FFT Library for DUE is fantastic! I've spend the last 3 evenings to understand the FFT theme.
I'm following this forum since 2 years and learned a lot. But now I'm brave enough to ask something.

My frequency range to measure and to analyse is from 8kHz - 200kHz. I've taken your "FFT_SplitRRP_ovSerMon_1a.ino" example.
The only value I've altered was the sampling rate due to my frequency range.

#define SMP_RATE 4800000UL

I've sampled some sine waves (array size 2048) and it was great to see results coming up with amazing speed.

Just to be sure about what I understand so far:
How can I calculate the effective frequency range (max) = SMP_RATE / 2 = 240kHz ?
And how do I calculate the frequency scale factor corresponding to the magnitude array position?
frequency scale factor = frequency range / out1[MIRROR] = 240kHz / 1024 = 0.234375 kHz (?)

But his is not matching up with my measurement results, what do I wrong?

Thanks.
It's a pity C language doesn't allow thousands separator, how many typo errors it could fix.

#define SMP_RATE 4.800.000 UL

It's not what you expect?

Magiciant, thanks for your quick answer!
...and sorry for the typo, the right sample frequency is of course 480ks/s.

Meantime I've made some more tests and now everything fits perfectly.
A measured test sine of 20kHz is showing its magnitude peak at array position [86] and the corresponding calculation has a result of position [85].

This is pretty close, or do I have to ignore also position[0] while counting?

20.000 / 234.375= 85.33333 Your test freq. isn't the best choice, it doesn't fit well. Main peak must be at bin = 85, with noticeable magnitude in sidelobes 84/86 and likely in 83/87. Do you have hamming ? W/o you'd have wider splash on both sides from 85 . Post your results

I still wonder why people use an FFT when a DCT is all that's needed (faster, smaller)?

If you don't care about phase information, the DCT is the right choice, and factors of 2
or 4 in performance are really important on a microcontroller!

MarkT:
I still wonder why people use an FFT when a DCT is all that's needed (faster, smaller)?

If you don't care about phase information, the DCT is the right choice, and factors of 2
or 4 in performance are really important on a microcontroller!

In short, DCT has 2x lower freq. resolution.

In abstract, I find a similarity, between FFT and "perpetuum mobile". Millions of clever people (OMG, Leonardo da Vinci?) were absolutely sure, that their invention is flawlessly perfect engine. Till thermodynamics theory proofs ones and forever opposite.
I don't have a theory (yet -);), but non of DCT, Hartley, Wavelets etc, could ever outperformed FFT on a ratio :

R (effectiveness) = frequency resolution / calculation complexity.

All of derivatives reduce complexity,but nobody acknowledge that outputs result degrade as well, in most cases more significantly than claimed gain in calculation complexity.

On my blog page I stopped to respond and delete questions on this matter, well, until I (or someone) create a theory...
There is also a chance , that theory already developed, but patented and kept as a secret by US government.-);

Hey Magician,

sorry for my delayed answer, but I was two days on travel. First of all - you are completely right in the point that for our example 20kHz is not a suiting frequency.
I've taken now 15kHz (0.234375 kHz * 64).

And here are the results of out1:

	Magnitudes: 
	-1861	791	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	1	1	1	1	1	1	1	1	1	1	1	1	0	17	197	
	246	48	1	1	1	1	1	1	1	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	26	109	
	76	4	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	1	17	18	
	2	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	5	9	2	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	1	5	2	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	2	2	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	1	2	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	1	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	0	
	0	0	0	0	0	0	0	0	0	0	1	0	0	0	0	0

The results showing the 15kHz is having its peak at array position [65]. But it should be [64]. I will check my pc sine gen vs. an other device by tomorrow.
Just to verify the precision of the frequency. Or... may be, you see something in the magic numbers, what I didn't acknowledge.

By the way I've chosen your brilliant FFT solution exactly for the reason - not to struggle with the well known limitations of DFT excerpts.

Yes, I see two things. First of all you don't have DC offset, you shouldn't drive analog input with AC! Otherwise it 'd destroy your board. Bias input with 2 10k resistors, one to 3.3V rail and another to ground, and apply AC via cap, appropriate capacity.
Another, output show correct peak at [64], counting from[0] - DC, value 246, but your signal generator isn't perfect, it's off to left about 100 Hz, probably 14.9 kHz. You may use your PC sound card for testing, there are a lot free "generator" software available on-line.

Hi Magician, after changing the sine gen and the replacement of the air wiring with proper shielded connections - all results are absolute perfectly shown by the FFT analysis (out1) now.
Thank you very much for your great work and your useful quick help.

I like to use the results of a single measurement / FFT analysis for further calculations. Searching trough the out1[mirror] array to find the dominant value is no problem.
But so far I did understand your direct register settings, all other analog (and digital?) inputs are disabled.
How can I activate this inputs after this single measurement for other control and measurement purposes?

But so far I did understand your direct register settings, all other analog (and digital?) inputs are disabled.
How can I activate this inputs after this single measurement for other control and measurement purposes?

No, it's not true. There is only 1 analog-0 pin in use, all others are free, you can call any of them with regular arduino command - analogRead, digitalRead etc.