I need help with FFT and i2s. I'm making an application where I need to find frequencies between 50Hz and 300Hz. I made this code for FFT and it is not working, could someone help me?
I'm using an INMP441 microphone and ESP32
#include <driver/i2s.h>
#define I2S_WS 15
#define I2S_SD 13
#define I2S_SCK 2
#define I2S_PORT I2S_NUM_0
#include "arduinoFFT.h"
#define SAMPLES 512 //Must be a power of 2
#define SAMPLING_FREQUENCY 2000 //Hz, must be less than 10000 due to ADC //Frequencia mais alta esperada dobrada
arduinoFFT FFT = arduinoFFT();
unsigned int sampling_period_us;
unsigned long microseconds;
double vReal[SAMPLES];
double vImag[SAMPLES];
void setup() {
Serial.begin(115200);
sampling_period_us = round(1000000*(1.0/SAMPLING_FREQUENCY));
i2s_install();
i2s_setpin();
i2s_start(I2S_PORT);
}
void loop() {
int32_t samples = 512;
int bytes = i2s_pop_sample(I2S_PORT, (char*)&samples, portMAX_DELAY);
/*SAMPLING*/
for(int i=0; i<SAMPLES; i++)
{
microseconds = micros(); //Overflows after around 70 minutes!
vReal[i] = bytes;
vImag[i] = 0;
while(micros() < (microseconds + sampling_period_us)){
}
}
/*FFT*/
FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);
/*PRINT RESULTS*/
Serial.print("xp - "); Serial.println(peak); //Print out what frequency is the most dominant.
delayMicroseconds(sampling_period_us);
}
void i2s_install(){
const i2s_config_t i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 44100,
.bits_per_sample = i2s_bits_per_sample_t(16),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0, // default interrupt priority
.dma_buf_count = 8,
.dma_buf_len = SAMPLES,
.use_apll = false
};
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}
void i2s_setpin(){
const i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = -1,
.data_in_num = I2S_SD
};
i2s_set_pin(I2S_PORT, &pin_config);
}
What do you mean?
Does the arduinoFFT library work on the ESP32?
A circuit diagram would also help?
What are you using for your test signal?
Do you have a scope?
I need the sound frequency picked up by this microphone to be returned. It just leaves a default value, I think it's a code problem. I did the separate microphone test and it's working..
I need the sound frequency picked up by this microphone to be returned. It just leaves a default value, I think it's a code problem. I did the separate microphone test and it's working
But you are not using the ADC. You have setup the I2C for
I am not sure if the way you put the I2S samples into the FFT buffer will work. So I would test this by sending the FFT buffer to the serial plotter to see if you are getting a waveform, before worrying about what the FFT produces.
As I mentioned in the first thread you made, do yourself a favour and use ArduinoSound library, it has FFTAnalyzer library with example ArduinoSound - Arduino Reference
I don't think you did.
Did you try outputting the buffer as a waveform?
There is no need to have a delay because the data is coming from the I2C, this is setting the sample rate not any delay.