Background

We can combine waves at different frequencies and amplitudes to generate complicated waves.


A Fourier transform takes a complicated looking wave and spits out the individual frequencies that it contains.


Sampling

We can sample a wave with a freqency equal to half of our sampling rate. So,  if we are sampling at 10,000 Hz, we can sample wave of 5000 Hz.




Input Circuit


Sample Code


Size of bin = Sampling Rate/#Samples


#include <arduinoFFT.h>
#define AUDIO_IN_PIN    A0
#define SAMPLES         128
#define SAMPLING_FREQ   3200 
#define AMPLITUDE       100
#define NUM_BANDS       8 
#define NOISE           500           // Used as a crude noise filter, values below this are ignored

unsigned int sampling_period_us;

double vReal[SAMPLES];
double vImag[SAMPLES];
unsigned long newTime;

arduinoFFT FFT = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);


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

  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQ));
  sampleInput();
}

void loop() {
}

void sampleInput() {

  // Sample the audio pin
  for (int i = 0; i < SAMPLES; i++) {
    newTime = micros();
    vReal[i] = analogRead(AUDIO_IN_PIN); 
    vImag[i] = 0;
    while ((micros() - newTime) < sampling_period_us) { /* chill */ }
  }

  // Compute FFT
  FFT.DCRemoval();
  FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(FFT_FORWARD);
  FFT.ComplexToMagnitude();

  // binSize = SAMPLING_FREQ / SAMPLES
  // binsize = 3200/128 = 25Hz

  // Analyse FFT results
  int biggestFrequency = 0;
  int magnitude = 0;
  int binsize = SAMPLING_FREQ / SAMPLES;
  
  // Don't use sample 0 and only first SAMPLES/2 are usable. 
  // Each array element represents a frequency bin and its value the amplitude.
    
  for (int i = 1; i < (SAMPLES/2); i++){       
    if (vReal[i] > NOISE) {                    // Add a crude noise filter
      Serial.print(i);
      Serial.print("[");
      Serial.print((i)*binsize);
      Serial.print("]");
      Serial.print(": ");
      Serial.println((int)vReal[i]);
      if((int)vReal[i] > magnitude){
        biggestFrequency=(i)*binsize;
        magnitude=(int)vReal[i];
      }
    }
  }

  if(biggestFrequency>0){
    Serial.print("f=");
    Serial.print(biggestFrequency);
    Serial.print(" c=");
    Serial.println(magnitude);
  }
  
}


References

ReferenceURL
Arduino FFT Libraryhttps://github.com/kosme/arduinoFFT
ESP32 spectrum analyser VU meter using arduinoFFT and a FastLED matrixhttps://www.youtube.com/watch?v=Mgh2WblO5_c
ESP32_FFT_VU - Codehttps://github.com/s-marley/ESP32_FFT_VU
  • No labels