Analog Microphone

Hi everybody, I am running an analog microphone into Pin 36 on a wireless stick light. It tracks frequency well [using a new 50 until it gets down to 175Hz at which point the FFT jumps up so that at 170Hz it is reading about 480-500Hz as the peak frequency - I am guessing this is something to do with sampling rate at the pin - any suggestions would be very welcome.

This is the code I am using

/*
ADC read voltage via GPIO13 with 1% accuracy.

by Aaron.Lee from HelTec AutoMation, ChengDu, China
成都惠利特自动化科技有限公司
www.heltec.cn
*/
#include “arduinoFFT.h”
#include “Arduino.h”

#define SAMPLES 256 //SAMPLES-pt FFT. Must be a base 2 number. Max 128 for Arduino Uno.
#define SAMPLING_FREQUENCY 22050 //Ts = Based on Nyquist, must be 2 times the highest expected frequency.

//const int micPin = A0; //A0;

arduinoFFT FFT = arduinoFFT();

unsigned int samplingPeriod;
unsigned long microSeconds;

double vReal[SAMPLES]; //create vector of size SAMPLES to hold real values
double vImag[SAMPLES]; //create vector of size SAMPLES to hold imaginary values
double peakAverage[10];
double peakPrint = 0;
double peak = 0;
double oldPeak = 0;
int counter;
int averagingSteps=10;

void setup() {
Serial.begin(115200);

// adc_power_on( );
// adc1_config_width(ADC_WIDTH_12Bit);
// // ADC1 channel 0 is GPIO36 (ESP32), GPIO1 (ESP32-S2)
// adc1_config_channel_atten(ADC1_CHANNEL_0 , ADC_ATTEN_DB_11);
}

int readPin = micPin;

double ReadVoltage(byte pin){
double reading = analogRead(readPin); // Reference voltage is 3v3 so maximum reading is 3v3 = 4095 in range 0 to 4095
// if(reading < 1 || reading >= 4095){
// return 0;
return -0.000000000009824 * pow(reading,3) + 0.000000016557283 * pow(reading,2) + 0.000854596860691 * reading + 0.065440348345433;
// return (-0.000000000000016 * pow(reading,4) + 0.000000000118171 * pow(reading,3)- 0.000000301211691 * pow(reading,2)+ 0.001109019271794 * reading + 0.034143524634089);
// }

} // Added an improved polynomial, use either, comment out as required

long mil=millis();

void loop() {
//Serial.println(ReadVoltage(readPin),3);
// Serial.println(analogRead(readPin));

/*Sample SAMPLES times*/
for(int i=0; i<SAMPLES; i++)
{
    microSeconds = micros();    //Returns the number of microseconds since the Arduino board began running the current script. 
 
    //vReal[i] = ReadVoltage(readPin); //Reads the value from analog pin 0 (A0), quantize it and save it as a real term.
    vReal[i] = analogRead(36);
    vImag[i] = 0; //Makes imaginary term 0 always

//  
    /*remaining wait time between samples if necessary*/
    while(micros() < (microSeconds + samplingPeriod))
    {
      // Serial.print("Real: ");
      Serial.println(vReal[i]);
    }
}

/*Perform FFT on samples*/
FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

/*Find peak frequency and print peak*/
peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);

peakAverage[counter] = peak;

counter++;

if(counter > averagingSteps){
  counter = 0;
}

 for (int x = 0; x < averagingSteps; x++)
 {
   peakPrint = peakPrint+peakAverage[x];
 }
 
    Serial.println(peakPrint/averagingSteps);     //Print out the most dominant frequency.
peakPrint = 0;

}

//See more APIs about ADC here: https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series/blob/master/esp32/cores/esp32/esp32-hal-adc.h

/* ADC readings v voltage

  • y = -0.000000000009824x3 + 0.000000016557283x2 + 0.000854596860691x + 0.065440348345433
    // Polynomial curve match, based on raw data thus:
  • 464 0.5
  • 1088 1.0
  • 1707 1.5
  • 2331 2.0
  • 2951 2.5
  • 3775 3.0

*/