Pages: [1]   Go Down
Author Topic: DUE's more advanced FFT capabilities  (Read 5345 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm looking for the most efficient way to get the Arduino DUE to preform a FFT. Since I'm only interested in preforming FFTs of real signals, a symmetric transformer like the Hartley Transform would be best.

I know there are a few libraries floating around, but all the ones I can find have been made for the UNO (don't compile in the 1.5 IDE). Are there and FFT libraries for the DUE?
In the directories of IDE 1.5, I saw a few c files in ...\arduino\sam\system\CMSIS\CMSIS\DSP_Lib\Source\TransformFunctions\
like arm_cfft_radix4_f32.c for example

These are excellent implementations intended for the Ardunio DUE's ARM4 core, but I cant seem to get them to compile (compiler error: cant find ARMCM4.h   ... and when I add  ARMCM4.h as a library, the compiler complains that it is an invalid library)

Any ideas? What other powerful libraries are there for the DUE that haven't been publicized?

Thanks!
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 21
Posts: 1670
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   The Due, ARM3 not ARM4 so it does not have the DSP extension, my guess is that thats is why its complaining about the invalid library.

Duane B

rcarduino.blogspot.com
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oops, your absolutely right. The DUE  has an ARM M3 and not M4 core. Still, its very strange to me why the Arduino 1.5 IDE comes with ARM M4 c and s files.

Anyways, any thoughts about a FFT library which will take advantage of the ARM M3's float operation capabilities (for example...) would be much appreciated.

I did find one which does compile:
http://www.librow.com/articles/article-10
It uses "double" for all of its data types. Does the ARM M3 process doubles as efficiently as floats? Or is it emulated and therefore take a much longer time to process?

Thanks again!
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 21
Posts: 1670
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry to disappoint, but as far as I am aware there is no floating point co processor either so no hardware support for float or double.

Duane B
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yikes! well back to the drawing board...
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 21
Posts: 1670
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am sure there are good 32 bit fixed point libraries, have a look and let us know.

Duane B
Logged


Tacoma, WA
Offline Offline
Full Member
***
Karma: 4
Posts: 192
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

There's always the Teensy 3.0, which has the DSP extensions in it's core.
Logged

Brian from Tacoma, WA
Arduino evangelist - since Dec, 2010.

0
Offline Offline
Full Member
***
Karma: 2
Posts: 109
ArduiYES!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

lots of explaining can be found in hardware/arduino/sam/system/CMSIS/CMSIS/Documentation/DSP_Lib/html/index.html

as far as I can see now it is suposed to work , only not with hardware support (like in the M4).
it is even supposed to work on the M0 !

exciting !

... but on second thought, be aware that this stuff is covered by a licence.

I got the sketch to pass the errors mentioned above, but it seems to need to link with an .a file.
does anybody know how I should build these CMSIS files into a library and add that to the Arduino IDE ?

my sketch until now (based on one of the examples, but duly botched while trying to get it to compile) :
Code:
#define ARM_MATH_CM3 // this selects right environment for arm_math.h on DUE
#include <arm_math.h>

#define TEST_LENGTH_SAMPLES 2048
 
static q31_t testOutput[TEST_LENGTH_SAMPLES/2]; // all types changed from f32 to q31 just to see if it mattered
 
uint32_t M = 0;
 
/* ------------------------------------------------------------------
* Global variables for FFT Bin Example
* ------------------------------------------------------------------- */
uint32_t fftSize = 1024;
uint32_t ifftFlag = 0;
uint32_t doBitReverse = 1;
 
/* Reference index at which max energy of bin ocuurs */
uint32_t refIndex = 213, testIndex = 0;
 
/* ----------------------------------------------------------------------
Test Input signal contains 10KHz signal + Uniformly distributed white noise
** ------------------------------------------------------------------- */

q31_t testInput_f32_10khz[TEST_LENGTH_SAMPLES] =
{  
-0.865129623056441, 0.000000000000000, -2.655020678073846, 0.000000000000000, 0.600664612949661, 0.000000000000000, 0.080378093886515, 0.000000000000000,
-2.899160484012034, 0.000000000000000, 2.563004262857762, 0.000000000000000, 3.078328403304206, 0.000000000000000, 0.105906778385130, 0.000000000000000,
-1.620990298572947, 0.000000000000000, -1.085103073196045, 0.000000000000000, 0.738606361195386, 0.000000000000000,
-2.097831202853255, 0.000000000000000, 2.711952282071310, 0.000000000000000, 1.498539238246888, 0.000000000000000, 1.317457282535915, 0.000000000000000,
-0.302765938349717, 0.000000000000000, -0.044623707947201, 0.000000000000000, 2.337405215062395, 0.000000000000000, -3.980689173859100, 0.000000000000000,

};

void setup() {
  Serial.begin(19200);
}

void loop() {
      
    
       /** \example arm_fft_bin_example_f32.c
  */  

arm_status status;
arm_cfft_radix4_instance_q31 S;
q31_t maxValue;

status = ARM_MATH_SUCCESS;

/* Initialize the CFFT/CIFFT module */  
status = arm_cfft_radix4_init_q31(&S, fftSize, ifftFlag, doBitReverse);

/* Process the data through the CFFT/CIFFT module */
arm_cfft_radix4_q31(&S, testInput_f32_10khz);


/* Process the data through the Complex Magnitude Module for  
calculating the magnitude at each bin */
arm_cmplx_mag_q31(testInput_f32_10khz, testOutput, fftSize);  

/* Calculates maxValue and returns corresponding BIN value */
arm_max_q31(testOutput, fftSize, &maxValue, &testIndex);

if(testIndex !=  refIndex)
{
status = ARM_MATH_TEST_FAILURE;
}

/* ----------------------------------------------------------------------
** Loop here if the signals fail the PASS check.
** This denotes a test failure
** ------------------------------------------------------------------- */

if( status != ARM_MATH_SUCCESS)
{
while(1);
}

    while(1);                             /* main function does not return */
    
}
« Last Edit: December 31, 2012, 02:01:03 pm by raalst » Logged

0
Offline Offline
Full Member
***
Karma: 2
Posts: 109
ArduiYES!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I got this library to work on the DUE.
see http://arduino.cc/forum/index.php/topic,140107.0.html
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

lots of explaining can be found in hardware/arduino/sam/system/CMSIS/CMSIS/Documentation/DSP_Lib/html/index.html

as far as I can see now it is suposed to work , only not with hardware support (like in the M4).
it is even supposed to work on the M0 !

exciting !

... but on second thought, be aware that this stuff is covered by a licence.

I got the sketch to pass the errors mentioned above, but it seems to need to link with an .a file.
does anybody know how I should build these CMSIS files into a library and add that to the Arduino IDE ?

my sketch until now (based on one of the examples, but duly botched while trying to get it to compile) :
Code:
#define ARM_MATH_CM3 // this selects right environment for arm_math.h on DUE
#include <arm_math.h>

#define TEST_LENGTH_SAMPLES 2048
 
static q31_t testOutput[TEST_LENGTH_SAMPLES/2]; // all types changed from f32 to q31 just to see if it mattered
 
uint32_t M = 0;
 
/* ------------------------------------------------------------------
* Global variables for FFT Bin Example
* ------------------------------------------------------------------- */
uint32_t fftSize = 1024;
uint32_t ifftFlag = 0;
uint32_t doBitReverse = 1;
 
/* Reference index at which max energy of bin ocuurs */
uint32_t refIndex = 213, testIndex = 0;
 
/* ----------------------------------------------------------------------
Test Input signal contains 10KHz signal + Uniformly distributed white noise
** ------------------------------------------------------------------- */

q31_t testInput_f32_10khz[TEST_LENGTH_SAMPLES] =
{  
-0.865129623056441, 0.000000000000000, -2.655020678073846, 0.000000000000000, 0.600664612949661, 0.000000000000000, 0.080378093886515, 0.000000000000000,
-2.899160484012034, 0.000000000000000, 2.563004262857762, 0.000000000000000, 3.078328403304206, 0.000000000000000, 0.105906778385130, 0.000000000000000,
-1.620990298572947, 0.000000000000000, -1.085103073196045, 0.000000000000000, 0.738606361195386, 0.000000000000000,
-2.097831202853255, 0.000000000000000, 2.711952282071310, 0.000000000000000, 1.498539238246888, 0.000000000000000, 1.317457282535915, 0.000000000000000,
-0.302765938349717, 0.000000000000000, -0.044623707947201, 0.000000000000000, 2.337405215062395, 0.000000000000000, -3.980689173859100, 0.000000000000000,

};

void setup() {
  Serial.begin(19200);
}

void loop() {
      
    
       /** \example arm_fft_bin_example_f32.c
  */  

arm_status status;
arm_cfft_radix4_instance_q31 S;
q31_t maxValue;

status = ARM_MATH_SUCCESS;

/* Initialize the CFFT/CIFFT module */  
status = arm_cfft_radix4_init_q31(&S, fftSize, ifftFlag, doBitReverse);

/* Process the data through the CFFT/CIFFT module */
arm_cfft_radix4_q31(&S, testInput_f32_10khz);


/* Process the data through the Complex Magnitude Module for  
calculating the magnitude at each bin */
arm_cmplx_mag_q31(testInput_f32_10khz, testOutput, fftSize);  

/* Calculates maxValue and returns corresponding BIN value */
arm_max_q31(testOutput, fftSize, &maxValue, &testIndex);

if(testIndex !=  refIndex)
{
status = ARM_MATH_TEST_FAILURE;
}

/* ----------------------------------------------------------------------
** Loop here if the signals fail the PASS check.
** This denotes a test failure
** ------------------------------------------------------------------- */

if( status != ARM_MATH_SUCCESS)
{
while(1);
}

    while(1);                             /* main function does not return */
    
}


Could you finally get this library working under Q31? I can in Q15 and f32, but not under Q31!!!
Thank you
Logged

0
Offline Offline
Full Member
***
Karma: 2
Posts: 109
ArduiYES!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nope, I was happy with whatever I could get to work, since I'm still at the
"thinking about it" phase of my project.
I have not really made an effort specifically for the Q31.
It might be hard, it could be simple ....
 

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nope, I was happy with whatever I could get to work, since I'm still at the
"thinking about it" phase of my project.
I have not really made an effort specifically for the Q31.
It might be hard, it could be simple ....
 



It is not hard, I have it for Q15, the problem is, if I use any Q31 array, arduino just freezes!!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How can I implement this code to do an FFT from an AnalogRead

I attempted to ad the following code in place of the specified test signal "float32_t testInput_f32_10khz[2048]"
Code:

for (int x=0;x<2048;x++){
   float32_t voltage = analogRead(A0) * (5 / 1023.0);
   testInput_f32_10khz[x]=voltage;
   x++;
   testInput_f32_10khz[x]=0.000000000000000;
  }
But it always replies with a 0 value for the testIndex
Logged

US
Offline Offline
Full Member
***
Karma: 4
Posts: 182
Electronics are the new Legos
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

try:  voltage = (float) analogRead(0) * 5.0 / 1023.0; to ensure you do not get the 5/1023 being an int which would be zero.  Also, maybe instead of 5.0 use 3.3 as Due is a 3.3 volt system?
Logged

Pages: [1]   Go Up
Jump to: