I2S -> FFT stream is producing random numbers at most #1657
-
I tried to get I2S hooked up to FFT on an Arduino Nano ESP32-S3 all day yesterday, using a capture card very similar to the one described under "External ADC": Only mine allows configuring some more options - I can switch between 16 and 24 bit samples and would have an option to switch between "LS", "RJ" and "I2S", which I suppose is the bit alignment. "I2S" is default, so presumably Top view: https://m.media-amazon.com/images/I/71dZx+7XiyL._SL1500_.jpg Unfortunately, there's no documentation available, but I tried all permutations I could think of / figure out:
For slave mode, I think the capture frequency is set by the master clock because it only lists The problem is that I'm not even sure which part of the system is not working. Soldering joints are straightforward and shouldn't be the issue, but even just the In the end, what I want to do is perform FFT on a preamplified (mono) microphone input after applying simplistic AGC (which I take would be possible with This is one iteration of my code, for reference - maybe someone will notice something obvious, because I really have no idea what else to do here. Is there maybe any more granular, targeted way to trace things down inside the library? It's extremely abstract and requires lots of domain-specific knowledge it seems, and this is my first Arduino project so I'm a bit stuck. #include "adc.h"
#include <Arduino.h>
#include <cmath>
#include "AudioLibs/AudioRealFFT.h"
#include "AudioLibs/FFTDisplay.h"
#include "AudioTools.h"
#include "common.h"
#define AUDIO_SAMPLE_RATE 48000
#define AUDIO_BITS_PER_SAMPLE 16
#define FFT_BANDS 8
#define FFT_LENGTH 512
#define USE_I2S
#define ADC_PIN_DIRECT GPIO_NUM_5
#define ADC_I2S_PIN_MCK GPIO_NUM_44
#define ADC_I2S_PIN_BCK GPIO_NUM_17
#define ADC_I2S_PIN_DATA GPIO_NUM_18
#define ADC_I2S_PIN_WS GPIO_NUM_19
#define FFT_MAX_MAGNITUDE (FFT_LENGTH * (1 << AUDIO_BITS_PER_SAMPLE))
using namespace std;
AudioInfo info(AUDIO_SAMPLE_RATE, 2, AUDIO_BITS_PER_SAMPLE);
I2SStream i2sStream;
AudioRealFFT fft;
FFTDisplay fftDis(fft);
StreamCopy copier(fft, i2sStream);
uint8_t fftBands[FFT_BANDS] = {
5, // 156 Hz
8, // 250 Hz
16, // 500 Hz
32, // 1 kHz
64, // 2 kHz
92, // 3 kHz
128, // 4 kHz
FFT_LENGTH / 2 - 1, // 8 kHz
};
auto setup() -> bool {
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
auto cfg = i2sStream.defaultConfig(RX_MODE);
cfg.copyFrom(info);
cfg.i2s_format = I2S_STD_FORMAT;
cfg.channels = 2;
cfg.is_master = false;
cfg.use_apll = false;
cfg.pin_ws = ADC_I2S_PIN_WS;
cfg.pin_bck = ADC_I2S_PIN_BCK;
cfg.pin_data = ADC_I2S_PIN_DATA;
// cfg.pin_mck = ADC_I2S_PIN_MCK;
if (!i2sStream.begin(cfg)) {
slog("I2S initialization failed");
return false;
}
slog("I2S initialization success");
auto tcfg = fft.defaultConfig();
tcfg.copyFrom(info);
tcfg.length = FFT_LENGTH;
tcfg.callback = &audio_tools::FFTDisplay::fftCallback;
tcfg.window_function = new BufferedWindow(new Hamming());
if (!fft.begin(tcfg)) {
slog("FFT initialization failed");
return false;
}
slog("FFT initialization success");
fftDis.fft_group_bin = 16;
fftDis.fft_start_bin = 0;
fftDis.fft_max_magnitude = 40000;
fftDis.begin();
return true;
}
void loop() {
for (;;) {
copier.copy();
for (int i = 0; i < FFT_BANDS; i++) {
auto magnitude =
static_cast<uint32_t>(round(fftDis.getMagnitude(i)));
auto scaledMagnitude = static_cast<uint16_t>(round(
255.0F * magnitude / static_cast<float>(FFT_MAX_MAGNITUDE)));
Serial.printf("%10d (%3d)", magnitude, scaledMagnitude);
}
Serial.println();
}
} Device is jumpered to 48k, master, 16bit, I2S while running this. Sample output:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
You are not supposed to display the result in the loop, but only when it is ready (as in this example)! With such a high sample rate you might need to double check that your display is fast enough and not messing up the result because it is too slow.... |
Beta Was this translation helpful? Give feedback.
You are not supposed to display the result in the loop, but only when it is ready (as in this example)!
With such a high sample rate you might need to double check that your display is fast enough and not messing up the result because it is too slow....