Teensy 4.0 ADC FFT - Current State

Status
Not open for further replies.

MSO

Active member
Hello! I have been working through a number of microphones to get FFT working from the Teensy 4.0. All of the code worked great with the i2s microphone, but then I found out it spoiled the timing for writing to WS2813 LEDs. Then I decided to make the modification to an Adafruit MAX4466 microphone to use it for FFT. However, according to this thread (comment 15) Paul Stoffregen replied:

"This will work without the audio shield present, but I2S output (or any other I/O object that causes the library to update) is currently required. Future versions will remove this requirement."

So the ADC need some type of external timing regulation. However, when I fire up a basic FFT program I get the following results.

1. analogRead(A7): .6V biased signal that responds to audio
2. ADC -> FFT without i2s: no data.
3. ADC -> FFT with i2s: data that does not respond to sound unchanging.jpg

So in this case, the i2s makes the FFT return data, just not useful data. As I mentioned earlier, i2s breaks the LEDs anyway, so another "I/O object that causes the library to update" would be preferable.

The sketch I have been using is this: View attachment analog_erad.ino.

I would really appreciate hearing what may be done to get ADC -> FFT working on the 4.0. Thanks a lot for any help you are able to provide on this one.

edit: Looks like having "AudioInputI2S i2s1; " in the sketch garbles the analogread() output. Goes from solid .6V to a random low value.
 
Last edited:
1. analogRead(A7): .6V biased signal that responds to audio
2. ADC -> FFT without i2s: no data.
3. ADC -> FFT with i2s: data that does not respond to sound View attachment 21374
You failed to call init(A7) on the adc object, so its defaulting to A2.

Using code tags to post code is the way to go, make it easy for people...
 
Thanks for taking a look I'll add the code with tags. I tried every pin for the ADC using adc1(A0-A7), I just moved it to A2 to more easily test different audio library configs.
 
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1(A6);           //xy=263.00000762939453,49.00000476837158
//AudioSynthWaveformSine   sine1;          //xy=294,142.00000476837158
AudioMixer4              mixer1;         //xy=458.7826232910156,58
AudioAnalyzeFFT1024      fft1024;      //xy=554,124
AudioConnection          patchCord1(adc1, 0, mixer1, 0);
//AudioConnection          patchCord2(sine1, 0, mixer1, 1);
AudioConnection          patchCord3(mixer1, fft1024);
// GUItool: end automatically generated code

const int EQbins = 14;
float EQbuff[EQbins];

void setup() {
  AudioMemory(24);
  Serial.begin(115200);
  //mixer1.gain(0, 1);
  //mixer1.gain(1, 0);
  //mixer1.gain(2, 1);
  sine1.amplitude(1);
  sine1.frequency(330);
  //sine1.Set the frequency, from 0 to 22000. Very low values may be used to create a LFO (Low Frequency Oscillator) for objects with modulation signal inputs.
  sine1.phase(0);
}

void loop() {
  //delay(1);
  //readfft();
  logread();
  //finefft();
  
}

void logread(){
  Serial.print(0);  // To freeze the lower limit
  Serial.print(" ");
  Serial.print(1.2*10);  // To freeze the upper limit
  Serial.print(" ");
  float printle = analogRead(A6)*3.3/1024*10;
  Serial.println(printle);
}

void readfft(){
  if (fft1024.available()) {
    Serial.println(fft1024.read(0, 1024));
  }
}
void finefft(){
  if (fft1024.available()) {
    EQbuff[0] =  fft1024.read(0);
    EQbuff[1] =  fft1024.read(1);
    EQbuff[2] =  fft1024.read(2, 3);
    EQbuff[3] =  fft1024.read(4, 6);
    EQbuff[4] =  fft1024.read(7, 11);
    EQbuff[5] =  fft1024.read(12, 18);
    EQbuff[6] =  fft1024.read(19, 29);
    EQbuff[7] =  fft1024.read(30, 45);
    EQbuff[8] =  fft1024.read(46, 68);
    EQbuff[9] =  fft1024.read(69, 103);
    EQbuff[10] = fft1024.read(104, 154);
    EQbuff[11] = fft1024.read(155, 131);
    EQbuff[12] = fft1024.read(132, 184);
    EQbuff[13] = fft1024.read(344, 511);

    for(int i = 0; i < EQbins; i++){
      Serial.print(EQbuff[i]);
      Serial.print(" ");
    }
    Serial.println(" ");
  }
}
 
I had another look at this, and added an AudioOutputI2S to this sketch and then it triggers updates and you can see
signals on ADC pins. The relevant TODO in input_adc.cpp
Code:
    // TODO: configure I2S1 to interrupt every 128 audio samples
Is what Paul was refering to in "This will work without the audio shield present, but I2S output (or any other I/O object that causes the library to update) is currently required. Future versions will remove this requirement."

The way the Audio lib works is that there needs to be at least one AudioStream component that can drive updates, and on the T4 currently
the AudioInputAnalog is not one of them until this gets fixed/written.
 
Status
Not open for further replies.
Back
Top