Arduino FFT Example Issue

I am testing out the Example 5 from the ArduinoFFT library by kosme, shown below.

/*

	Example of use of the FFT libray
        Copyright (C) 2014 Enrique Condes

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

/*
  In this example, the Arduino simulates the sampling of a sinusoidal 1000 Hz
  signal with an amplitude of 100, sampled at 5000 Hz. Samples are stored
  inside the vReal array. The samples are windowed according to Hamming
  function. The FFT is computed using the windowed samples. Then the magnitudes
  of each of the frequencies that compose the signal are calculated. Finally,
  the frequency with the highest peak is obtained, being that the main frequency
  present in the signal. This frequency is printed, along with the magnitude of
  the peak.
*/

#include "arduinoFFT.h"

arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
/*
These values can be changed in order to evaluate the functions
*/
const uint16_t samples = 64; //This value MUST ALWAYS be a power of 2
const double signalFrequency = 1000;
const double samplingFrequency = 5000;
const uint8_t amplitude = 100;
/*
These are the input and output vectors
Input vectors receive computed results from FFT
*/
double vReal[samples];
double vImag[samples];

#define SCL_INDEX 0x00
#define SCL_TIME 0x01
#define SCL_FREQUENCY 0x02
#define SCL_PLOT 0x03

void setup()
{
  Serial.begin(115200);
  Serial.println("Ready");
}

void loop()
{
  /* Build raw data */
  double cycles = (((samples-1) * signalFrequency) / samplingFrequency); //Number of signal cycles that the sampling will read
  for (uint16_t i = 0; i < samples; i++)
  {
    vReal[i] = int8_t((amplitude * (sin((i * (twoPi * cycles)) / samples))) / 2.0);/* Build data with positive and negative values*/
    //vReal[i] = uint8_t((amplitude * (sin((i * (twoPi * cycles)) / samples) + 1.0)) / 2.0);/* Build data displaced on the Y axis to include only positive values*/
    vImag[i] = 0.0; //Imaginary part must be zeroed in case of looping to avoid wrong calculations and overflows
  }
  /* Print the results of the simulated sampling according to time */
  Serial.println("Data:");
  PrintVector(vReal, samples, SCL_TIME);
  FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);	/* Weigh data */
  Serial.println("Weighed data:");
  PrintVector(vReal, samples, SCL_TIME);
  FFT.Compute(vReal, vImag, samples, FFT_FORWARD); /* Compute FFT */
  Serial.println("Computed Real values:");
  PrintVector(vReal, samples, SCL_INDEX);
  Serial.println("Computed Imaginary values:");
  PrintVector(vImag, samples, SCL_INDEX);
  FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */
  Serial.println("Computed magnitudes:");
  PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
  double x;
  double v;
  FFT.MajorPeak(vReal, samples, samplingFrequency, &x, &v);
  Serial.print(x, 6);
  Serial.print(", ");
  Serial.println(v, 6);
  while(1); /* Run Once */
  // delay(2000); /* Repeat after delay */
}

void PrintVector(double *vData, uint16_t bufferSize, uint8_t scaleType)
{
  for (uint16_t i = 0; i < bufferSize; i++)
  {
    double abscissa;
    /* Print abscissa value */
    switch (scaleType)
    {
      case SCL_INDEX:
        abscissa = (i * 1.0);
	break;
      case SCL_TIME:
        abscissa = ((i * 1.0) / samplingFrequency);
	break;
      case SCL_FREQUENCY:
        abscissa = ((i * 1.0 * samplingFrequency) / samples);
	break;
    }
    Serial.print(abscissa, 6);
    if(scaleType==SCL_FREQUENCY)
      Serial.print("Hz");
    Serial.print(" ");
    Serial.println(vData[i], 4);
  }
  Serial.println();
}

I connected the Arduino Uno board to my computer and ran the exact example from the library, which yielded the attached graph.

The beginning looks pretty normal, but then everything seems to go wrong.

  1. I’m assuming the blue line is the FFT, but what does the red line represent?
  2. Why is there an extra red peak at the beginning of the graph?
  3. Shouldn’t there be only one peak at 1000 on the x-axis if it is simulating a sinusoidal signal?
  4. Why is the amplitude so high, if I set it to 100?

Instructions for posting images can be found in the first threads of the forum.

If you don't know what the plot represents, don't bother with it and look at the printed results.

There are several problems with the example you chose and so it is not recommended. For one, when transforming N (64) real values, only the first N/2 (32) elements of the two output arrays are unique and interesting.

Start with example #1 instead, which performs the same calculation but just prints the results.

There are several different conventions to scaling the output of the FFT algorithm, so for the moment, don't worry about the fact that the amplitude does not appear to be correct. Also, the windowing algorithm you choose will affect the amplitude, and the spread of the output peak.

The output amplitudes will be proportional to the input amplitudes, which you can verify by changing that value.

This is the interesting bit of the output from example 1, after reducing the precision of the output to 1 decimal place. The last number is the estimated center frequency of the major peak.

Computed magnitudes:
0.0Hz 6.8
78.1Hz 7.0
156.3Hz 5.6
234.4Hz 5.3
312.5Hz 7.6
390.6Hz 6.3
468.7Hz 6.9
546.9Hz 8.2
625.0Hz 7.0
703.1Hz 7.6
781.2Hz 3.0
859.4Hz 66.4
937.5Hz 631.4
1015.6Hz 738.7
1093.8Hz 145.7
1171.9Hz 2.0
1250.0Hz 3.4
1328.1Hz 6.4
1406.3Hz 2.3
1484.4Hz 5.8
1562.5Hz 3.5
1640.6Hz 2.6
1718.8Hz 4.4
1796.9Hz 2.9
1875.0Hz 4.0
1953.1Hz 2.2
2031.3Hz 2.0
2109.4Hz 4.0
2187.5Hz 3.0
2265.6Hz 4.4
2343.8Hz 0.9
2421.9Hz 2.6

1004.2

With Example 1, vary the amplitude and frequency of the input sample, and try adding an additional sine or cosine term to the input, change the window function, etc., look at the printed output and make sure you understand what happens and why.