# Issues in getting FFT to work on Arduino using my own code

**URL:** <https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746>\
**Category:** Programming\
**Created:** [April 1, 2024, 10:55pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746 "2024-04-01T22:55:06Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![hawk453](https://avatars.discourse-cdn.com/v4/letter/h/439d5e/32.png) [@hawk453](https://forum.arduino.cc/u/hawk453)\
**Post date:** [April 1, 2024, 10:55pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/1 "2024-04-01T22:55:06Z")

</div>

Hi,

I'm working on a project which requires the use of FFT to analyze incoming frequency from the analog-read microphone. I want the magnitude of a specific frequency from a bunch of different frequencies that three 50ohm speakers are emitting, namely 1Khz, 3Khz and 5Khz. I tried using the arduinoFFT library but it gives me major peak and not the frequency of interest. Below is the code I came up with. Could you tell what mistake I'm making here? Thanks.

When I run this code, I run into one major issue, namely, the FFT just doesn't work, forget about getting the magnitude. I'm a DSP engineer. I think the math is right but if you could also cross check it, I would be thankful.

```arduino

#define SAMPLES 128
#define SAMPLING_FREQUENCY 1000

unsigned int sampling_period_us;
unsigned long microseconds;

struct cmpx {
    float real;
    float imag;
};
typedef struct cmpx COMPLEX;

COMPLEX v[SAMPLES];
COMPLEX w[SAMPLES];

float frequency_of_interest = 1000.0;

void setup() {
  Serial.begin(9600);
  sampling_period_us = round(1000000*(1.0/SAMPLING_FREQUENCY));

  for(int i = 0; i < SAMPLES; i++) {
    float angle = -2 * PI * i / SAMPLES;
    w[i].real = cos(angle);
    w[i].imag = sin(angle);
  }
}

void loop() {
  for(int i=0; i<SAMPLES; i++) {
    microseconds = micros();
   
    v[i].real = analogRead(A0);
    v[i].imag = 0;

    //Serial.print("Analog read: "); // Check analog read value
    //Serial.println(v[i].real);

    while(micros() < (microseconds + sampling_period_us)){}
  }

  fft(v, SAMPLES, w);

  for(int i=0; i<SAMPLES; i++) { // Check FFT output
    Serial.print("FFT output: ");
    Serial.println(sqrt(pow(v[i].real, 2) + pow(v[i].imag, 2)));
  }

  int index = round(frequency_of_interest * SAMPLES / SAMPLING_FREQUENCY);
  float magnitude = sqrt(pow(v[index].real, 2) + pow(v[index].imag, 2));

  Serial.print("Magnitude of frequency of interest: "); // Print magnitude of frequency of interest
  Serial.println(magnitude);

  delay(1000);
}

void fft(COMPLEX *Y, int M, COMPLEX *w) {
  COMPLEX temp1,temp2; //temporary storage variables
  int i,j,k; //loop counter variables
  int upper_leg, lower_leg; //index of upper/lower butterfly leg
  int leg_diff; //difference between upper/lower leg
  int num_stages=0; //number of FFT stages, or iterations
  int index, step; //index and step between twiddle factor
  i=1; //log(base 2) of # of points = # of stages
  do
  {
    num_stages+=1;
    i=i*2;
  } while (i!=M);

  leg_diff=M/2; //starting difference between upper & lower legs
  step=2; //step between values in twiddle.h              
  for (i=0;i<num_stages;i++) //for M-point FFT                 
  {
    index=0;
    for (j=0;j<leg_diff;j++)
    {
      for (upper_leg=j;upper_leg<M;upper_leg+=(2*leg_diff))
      {
        lower_leg=upper_leg+leg_diff;
        temp1.real=(Y[upper_leg]).real + (Y[lower_leg]).real;
        temp1.imag=(Y[upper_leg]).imag + (Y[lower_leg]).imag;
        temp2.real=(Y[upper_leg]).real - (Y[lower_leg]).real;
        temp2.imag=(Y[upper_leg]).imag - (Y[lower_leg]).imag;
        (Y[lower_leg]).real=temp2.real*(w[index]).real-temp2.imag*(w[index]).imag;
        (Y[lower_leg]).imag=temp2.real*(w[index]).imag+temp2.imag*(w[index]).real;
        (Y[upper_leg]).real=temp1.real;
        (Y[upper_leg]).imag=temp1.imag;
      }
      index+=step;
    }
    leg_diff=leg_diff/2;
    step*=2;
  }
  j=0;
  for (i=1;i<(M-1);i++) //bit reversal for resequencing data*/
  {
    k=M/2;
    while (k<=j)
    {
      j=j-k;
      k=k/2;
    }
    j=j+k;
    if (i<j)
    {
      temp1.real=(Y[j]).real;
      temp1.imag=(Y[j]).imag;
      (Y[j]).real=(Y[i]).real;
      (Y[j]).imag=(Y[i]).imag;
      (Y[i]).real=temp1.real;
      (Y[i]).imag=temp1.imag;
    }
  }
  return;
}

```

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [April 1, 2024, 11:54pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/2 "2024-04-01T23:54:41Z")

</div>

No need to guess whether the math is right. Feed the FFT with a data array containing a calculated sine wave and check whether the power spectrum is what you expect.

Note: this is not the correct way to time your samples, as it does not correctly handle counter overflow (after about 70 minutes of run time):

```arduino
   while(micros() < (microseconds + sampling_period_us)){}

```

This does:

```arduino
   while(micros() - microseconds < sampling_period_us){}

```

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [April 2, 2024, 12:48am UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/3 "2024-04-02T00:48:53Z")

</div>

You can also cross check using the FFT from Matlab or similar tool.

---

<div class="post-metadata">

**Author:** ![b707](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/b707/32/854321_2.png) [@b707](https://forum.arduino.cc/u/b707)\
**Post date:** [April 2, 2024, 5:44am UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/4 "2024-04-02T05:44:08Z")

</div>

> [@hawk453](#):
>
> Below is the code I came up with. Could you tell what mistake I'm making here? Thanks.

What is your arduino board?

---

<div class="post-metadata">

**Author:** ![hawk453](https://avatars.discourse-cdn.com/v4/letter/h/439d5e/32.png) [@hawk453](https://forum.arduino.cc/u/hawk453)\
**Post date:** [April 2, 2024, 1:25pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/6 "2024-04-02T13:25:41Z")

</div>

Arduino Mega 2560

---

<div class="post-metadata">

**Author:** ![hawk453](https://avatars.discourse-cdn.com/v4/letter/h/439d5e/32.png) [@hawk453](https://forum.arduino.cc/u/hawk453)\
**Post date:** [April 2, 2024, 1:29pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/7 "2024-04-02T13:29:45Z")

</div>

I did that using a sine wave lookup table, it matches the theoretical data. It just doesn't run on the Arduino correctly.

I'll make the changes. Thanks.

---

<div class="post-metadata">

**Author:** ![b707](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/b707/32/854321_2.png) [@b707](https://forum.arduino.cc/u/b707)\
**Post date:** [April 2, 2024, 2:02pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/8 "2024-04-02T14:02:01Z")

</div>

> [@hawk453](#):
>
> `float frequency_of_interest = 1000.0;`

> [@hawk453](#):
>
> `#define SAMPLING_FREQUENCY 1000`

According to Nyquist theorem, the sampling frequency must be at least a two times more than frequency\_of\_interest.  
With your 1000 Hz sampling the maximum freq you could measure is 500 Hz.  
For 3Khz and 5Khz you need a sampling with 6 and 10kHz respectively

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [April 2, 2024, 2:10pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/9 "2024-04-02T14:10:23Z")

</div>

> [@hawk453](#):
>
> It just doesn't run on the Arduino correctly.

Please explain what that means, and give an example.

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [April 2, 2024, 2:33pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/10 "2024-04-02T14:33:32Z")

</div>

Never mind. I ran this on an Uno, after reducing the array dimensions to fit, and the result is clearly nonsense. I suspect that the math coding is not correct.

The [ArduinoFFT library](https://www.arduino.cc/reference/en/libraries/arduinofft/) works as expected.

```arduino
#define SAMPLES 64
#define SAMPLING_FREQUENCY 1000

unsigned int sampling_period_us;
unsigned long microseconds;

struct cmpx {
    float real;
    float imag;
};
typedef struct cmpx COMPLEX;

COMPLEX v[SAMPLES];
COMPLEX w[SAMPLES];

float frequency_of_interest = 1000.0;

void setup() {
  Serial.begin(115200);
  sampling_period_us = round(1000000*(1.0/SAMPLING_FREQUENCY));

  for(int i = 0; i < SAMPLES; i++) {
    float angle = -2 * PI * i / SAMPLES;
    w[i].real = cos(angle);
    w[i].imag = sin(angle);
  }
}

void loop() {
  for(int i=0; i<SAMPLES; i++) {
// microseconds = micros();
   
    v[i].real = 100.0*sin(2*PI*i*15./SAMPLES); //15 Hz
    v[i].imag = 0;

    Serial.print("Analog read: "); // Check analog read value
    Serial.println(v[i].real);

// while(micros() < (microseconds + sampling_period_us)){}
  }

  fft(v, SAMPLES, w);

  for(int i=0; i<SAMPLES; i++) { // Check FFT output
    Serial.print("FFT output: ");
    Serial.println(sqrt(pow(v[i].real, 2) + pow(v[i].imag, 2)));
  }

  int index = round(frequency_of_interest * SAMPLES / SAMPLING_FREQUENCY);
  float magnitude = sqrt(pow(v[index].real, 2) + pow(v[index].imag, 2));

  Serial.print("Magnitude of frequency of interest: "); // Print magnitude of frequency of interest
  Serial.println(magnitude);

  while(1);
}

void fft(COMPLEX *Y, int M, COMPLEX *w) {
  COMPLEX temp1,temp2; //temporary storage variables
  int i,j,k; //loop counter variables
  int upper_leg, lower_leg; //index of upper/lower butterfly leg
  int leg_diff; //difference between upper/lower leg
  int num_stages=0; //number of FFT stages, or iterations
  int index, step; //index and step between twiddle factor
  i=1; //log(base 2) of # of points = # of stages
  do
  {
    num_stages+=1;
    i=i*2;
  } while (i!=M);

  leg_diff=M/2; //starting difference between upper & lower legs
  step=2; //step between values in twiddle.h              
  for (i=0;i<num_stages;i++) //for M-point FFT                 
  {
    index=0;
    for (j=0;j<leg_diff;j++)
    {
      for (upper_leg=j;upper_leg<M;upper_leg+=(2*leg_diff))
      {
        lower_leg=upper_leg+leg_diff;
        temp1.real=(Y[upper_leg]).real + (Y[lower_leg]).real;
        temp1.imag=(Y[upper_leg]).imag + (Y[lower_leg]).imag;
        temp2.real=(Y[upper_leg]).real - (Y[lower_leg]).real;
        temp2.imag=(Y[upper_leg]).imag - (Y[lower_leg]).imag;
        (Y[lower_leg]).real=temp2.real*(w[index]).real-temp2.imag*(w[index]).imag;
        (Y[lower_leg]).imag=temp2.real*(w[index]).imag+temp2.imag*(w[index]).real;
        (Y[upper_leg]).real=temp1.real;
        (Y[upper_leg]).imag=temp1.imag;
      }
      index+=step;
    }
    leg_diff=leg_diff/2;
    step*=2;
  }
  j=0;
  for (i=1;i<(M-1);i++) //bit reversal for resequencing data*/
  {
    k=M/2;
    while (k<=j)
    {
      j=j-k;
      k=k/2;
    }
    j=j+k;
    if (i<j)
    {
      temp1.real=(Y[j]).real;
      temp1.imag=(Y[j]).imag;
      (Y[j]).real=(Y[i]).real;
      (Y[j]).imag=(Y[i]).imag;
      (Y[i]).real=temp1.real;
      (Y[i]).imag=temp1.imag;
    }
  }
  return;
}

```

---

<div class="post-metadata">

**Author:** ![hawk453](https://avatars.discourse-cdn.com/v4/letter/h/439d5e/32.png) [@hawk453](https://forum.arduino.cc/u/hawk453)\
**Post date:** [April 2, 2024, 2:49pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/11 "2024-04-02T14:49:19Z")

</div>

Thanks, I'll look into the math.

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [September 29, 2024, 2:49pm UTC](https://forum.arduino.cc/t/issues-in-getting-fft-to-work-on-arduino-using-my-own-code/1242746/12 "2024-09-29T14:49:42Z")

</div>

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
