FFT function, need to output 3 arrays of Frequency, Real and Imaginary values

Hi guys,
I have been looking/trying to find a solution to my problem which is that I need to get 3 arrays from my function, Frequency[i], Real[i] and Imaginary[i] as a result of my FFT function. I am new to this and have seen suggestions about using malloc but I have no idea how to do this. The board I am currently using is the Arduino Uno but will transition to the Teensy 4.0 due to its higher RAM capabilities. Could someone please help me out?


int data[]={14, 30, 35, 34, 69, 40, 46, 45, 30, 4,  -26,  -28,  -55,  -49,  -48,
-28,  -37,  -30,  -13,  32,  32, 34, 65, 57, 38, 17, 1,  -6, -20,  -19,  -34, 
-51,  -61,  -69,  -35,  -7, 18, 60, 35, 34, 35, 50, 46, 43, 26, -2, -25,  -50,
-69,  -47,  -35,  -27,  -24,  -21,  -10,  11, 37, 58, 34, 25, 34, 13, -1, -7};

/*
int MouthPressure[64]={14, 30, 35, 34, 69, 40, 46, 45, 30, 4,  -26,  -28,  -55,  -49,  -48,
-28,  -37,  -30,  -13,  32,  32, 34, 65, 57, 38, 17, 1,  -6, -20,  -19,  -34, 
-51,  -61,  -69,  -35,  -7, 18, 60, 35, 34, 35, 50, 46, 43, 26, -2, -25,  -50,
-69,  -47,  -35,  -27,  -24,  -21,  -10,  11, 37, 58, 34, 25, 34, 13, -1, -7};
*/                                            
byte sine_data [91]=
 {
0,  
4,    9,    13,   18,   22,   27,   31,   35,   40,   44, 
49,   53,   57,   62,   66,   70,   75,   79,   83,   87, 
91,   96,   100,  104,  108,  112,  116,  120,  124,  127,  
131,  135,  139,  143,  146,  150,  153,  157,  160,  164,  
167,  171,  174,  177,  180,  183,  186,  189,  192,  195,       //Paste this at top of program
198,  201,  204,  206,  209,  211,  214,  216,  219,  221,  
223,  225,  227,  229,  231,  233,  235,  236,  238,  240,  
241,  243,  244,  245,  246,  247,  248,  249,  250,  251,  
252,  253,  253,  254,  254,  254,  255,  255,  255,  255
  };

//float Freq_MP[5], Real_MP[5], Imag_MP[5];
float Freq_Flow[5], Real_Flow[5], Imag_Flow[5];

void setup() {

Serial.begin(9600);

FFT(data, 64, 60, Freq_Flow, Real_Flow, Imag_Flow);
//FFT(MouthPressure, 64, 100, Freq_MP, Real_MP, Imag_MP);


 for(int i = 0; i < 5; i++)
{
  Serial.println(Freq_Flow[i]);
  delay(1000);
 /* Serial.println(Real_Flow[i]);
  delay(1000);
  Serial.println(Imag_Flow[i]);
  delay(1000);
  */ 
}


delay(10000000);

}

void loop() {
  // put your main code here, to run repeatedly:
}

float FFT(int in[],int N,float Frequency, float freq[], float reali[], float imagi[])
{
/*
Term:
1. in[]     : Data array, 
2. N        : Number of sample (recommended sample size 2,4,8,16,32,64,128...)
3. Frequency: sampling frequency required as input (Hz)
*/

unsigned int data[13]={1,2,4,8,16,32,64,128,256,512,1024,2048};
int a,c1,f,o,x;
a=N;  
                                 
      for(int i=0;i<12;i++)                 //calculating the levels
         { if(data[i]<=a){o=i;} }
      
int in_ps[data[o]]={};     //input for sequencing
float out_r[data[o]]={};   //real part of transform
float out_im[data[o]]={};  //imaginory part of transform
float out_f[data[o]]={};  //frequency of transform


           
x=0;  
      for(int b=0;b<o;b++)                     // bit reversal
         {
          c1=data[b];
          f=data[o]/(c1+c1);
                for(int j=0;j<c1;j++)
                    { 
                     x=x+1;
                     in_ps[x]=in_ps[j]+f;
                    }
         }

 
      for(int i=0;i<data[o];i++)            // update input array as per bit reverse order
         {
          if(in_ps[i]<a)
          {out_r[i]=in[in_ps[i]];}
          if(in_ps[i]>a)
          {out_r[i]=in[in_ps[i]-a];}      
         }


int i10,i11,n1;
float e,c,s,tr,ti;

    for(int i=0;i<o;i++)                                    //fft
    {
     i10=data[i];              // overall values of sine/cosine  :
     i11=data[o]/data[i+1];    // loop with similar sine cosine:
     e=360/data[i+1];
     e=0-e;
     n1=0;

          for(int j=0;j<i10;j++)
          {
          c=cosine(e*j);
          s=sine(e*j);    
          n1=j;
          
                for(int k=0;k<i11;k++)
                 {
                 tr=c*out_r[i10+n1]-s*out_im[i10+n1];
                 ti=s*out_r[i10+n1]+c*out_im[i10+n1];
          
                 out_r[n1+i10]=out_r[n1]-tr;
                 out_r[n1]=out_r[n1]+tr;
          
                 out_im[n1+i10]=out_im[n1]-ti;
                 out_im[n1]=out_im[n1]+ti;          
          
                 n1=n1+i10+i10;
                  }       
             }
     }


for(int i=0;i<data[o];i++)
{

out_f[i]=i*Frequency/N;                                    // Frequency
if (out_f[i] > 5 && out_f[i] < 25 ){
  /*
Serial.println(out_f[i]);
delay(1000);
Serial.println(out_r[i]);
delay(1000);
Serial.println(out_im[i]);
delay(1000);
*/
freq [i] = out_f[i]; 
reali[i] = out_r[i];                                            //Array of Real values and their corresponding
imagi[i] = out_im[i];                                           //imaginary values from the FFT

}
}}
//-----------------------------------------------------------------------------------------------------------------

float complex_division_Imag(float realA, float realB, float imagA, float imagB) {
  float divide     = (pow(realB, 2)) + (pow(imagB, 2));
  float Real       = (realA * realB);
  float imaginary  = (imagA *  imagB);
  float num2       = (imagA * realB) - (realA * imagB);                                 //Imaginary Value of Complex Ratio Function
  float out_imag   = num2 / divide;
  return (out_imag);
}

//--------------------------------------------------------------------------------------------------

float complex_division_Real(float realA, float realB, float imagA, float imagB) {
  float divide     = (pow(realB, 2)) + (pow(imagB, 2));
  float Real       = (realA * realB);
  float imaginary  = (imagA *  imagB); 
  float num1       = Real + imaginary;                                                 //Real Value of Complex Ratio Function
  float out_real   = num1 / divide;
  return (out_real);
}

//--------------------------------------------------------------------------------------------- 

float sine(int i)
{
  int j=i;
  float out;
  while(j<0){j=j+360;}
  while(j>360){j=j-360;}
  if(j>-1   && j<91){out= sine_data[j];}
  else if(j>90  && j<181){out= sine_data[180-j];}
  else if(j>180 && j<271){out= -sine_data[j-180];}
  else if(j>270 && j<361){out= -sine_data[360-j];}
  return (out/255);
}

float cosine(int i)
{
  int j=i;
  float out;
  while(j<0){j=j+360;}
  while(j>360){j=j-360;}
  if(j>-1   && j<91){out= sine_data[90-j];}
  else if(j>90  && j<181){out= -sine_data[j-90];}
  else if(j>180 && j<271){out= -sine_data[270-j];}
  else if(j>270 && j<361){out= sine_data[j-270];}
  return (out/255);

//-----------------------------------------------------------------------------------------------
}

Please post your code in code tags.
</>
You can find more about asking effective questions in this post:

Key point is that arrays are passed by reference. That is, there is no local copy created within the function. So, if you update in the function, it will be updated in the calling code.

Have a look at Arduino - Passing Arrays to Functions

Example:

char mainArray [3] = {'1','2','3'};
  
void setup()
{
  Serial.begin(9600);
  delay(500);

  for (uint8_t x = 0; x < 3; x++)
    Serial.print(mainArray[x]);

  myFunction(mainArray);

  for (uint8_t x = 0; x < 3; x++)
    Serial.print(mainArray[x]);
}

void loop(){}

void myFunction(char fnArray[])
{
  fnArray[0] = 'a';
  fnArray[1] = 'b';
  fnArray[2] = 'c';
}

Produces

`123abc`

Thank you red_car! This is the thing, I am passing 3 arrays in the calling of the function. Then inside the function I have written the final part of the code which I was hoping would update singular cells of the arrays used in the calling do the function. This code is very similar to the example you have given me but I am very confused why the values of the arrays are not updated? Thank you again

What were these printing out?

  /*
Serial.println(out_f[i]);
delay(1000);
Serial.println(out_r[i]);
delay(1000);
Serial.println(out_im[i]);
delay(1000);
*/

These were in fact printing out the correct, frequency, real and imaginary values. The problem is that they are on the serial monitor and I can’t access these arrays. In my program, there will be two readings, pressure and flow. Both of which I have to take the FFT of and then perform their complex ratio by doing flow divided by pressure with both parameters in the frequency domain. Hope this helps. This is a paper for basically the exact same project that I am doing. Very good background information.

(Portable forced oscillation device for point-of-care pulmonary function testing | IEEE Conference Publication | IEEE Xplore)

Ok... looks like it is falling over in your function...

This code...

  Serial.begin(9600);
  delay(500);
  Serial.println("Here1");

  FFT(data, 64, 60, Freq_Flow, Real_Flow, Imag_Flow);
  //FFT(MouthPressure, 64, 100, Freq_MP, Real_MP, Imag_MP);

  Serial.println("Here2");```



Returns...


Here1
Here1
Here1
...

I do not understand why this is happening :slightly_frowning_face:

Defined as having 5 entries...

float Freq_Flow[5], Real_Flow[5], Imag_Flow[5];

passed by reference to...

float FFT(int in[],int N,float Frequency, float freq[], float reali[], float imagi[])

...and updated in the for loop

freq [i] = out_f[i]; 
reali[i] = out_r[i];                                            //Array of Real values and their corresponding
imagi[i] = out_im[i];                                           //imaginary values from the FFT

However,

for(int i=0;i<data[o];i++)

i can be much larger than 5 ! so you are overwriting memory with anything > 5.

I will runt the code to see how many frequencies there are and then set the corresponding arrays to this value. Does the value of the array have to match exactly and also shouldn’t serial.print of the array in the void setup{} print at least 5 values still? The reason I’ve set it to 5 is just so that I see the any 5 values being outputted.

When I ran your code there were 64 entries required.

Be careful - if you increase all your arrays to this size you may run our out memory - you might need to re organise your program. You don't really need the temporary arrays in the function.