Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 1 of 1

Thread: Teensy 3.2 to 4.1 broke FFT from analog microphone MAX9814

  1. #1
    Junior Member
    Join Date
    Feb 2023
    Posts
    1

    Teensy 3.2 to 4.1 broke FFT from analog microphone MAX9814

    Hello friends! About 7 years ago, I built an LED art project using the Teensy 3.2, OctoWS2811, and an Adafruit dev board for the MAX9814. MAX9814 is an amplifier with auto gain. It is analog out, not I2S.

    Because of supply chain issues resulting in Teensy 3.2 not being available, I upgraded to the Teensy 4.1. Everything related to the LEDs and other features seems to be working perfectly, but the audio portion of the project is broken.

    I designed my project around the example in File > Examples > OctoWS2811 > SpectrumAnalyzer. The code for this example is pasted below (even though everyone has it with Teensyduino). When I originally made this art piece, I leaned hard on this spectrum analyzer example right down to the hardware pin suggested for the analog input: A3.

    I read up on a similar issue someone was having in this PJRC forum thread here. In that thread, Paul suggests a possible fix, but he notes:
    Here is a program which will run on Teensy 4.0 using 1.52-beta4 and gives you FFT of an audio signal on analog pin A2. 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.
    (Note: I am aware Paul's workaround here suggests analog into A2 instead of A3 where my audio input is going to).

    So, back to what I am doing. When I upgraded to Teensy 4.1, the OctoWS2811 > SpectrumAnalyzer example no longer works. I think what's going on is that OctoWS2811 uses DMA channels 1, 2 , and 3. But and the fix that Paul suggested uses AudioOutputI2S, which also uses DMA channel 1 and 2.

    Given all of this, does anyone know of a workaround that will allow me to continue using my Teensy 4.1, OctoWS2811B, and MAX9814 with audio going to pin A3? I already have PCBs printed and assembled for this project, so changing pins or hardware at this point would be a major bummer.

    Code:
    // LED Audio Spectrum Analyzer Display
    // 
    // Creates an impressive LED light show to music input
    //   using Teensy 3.1 with the OctoWS2811 adaptor board
    //   http://www.pjrc.com/store/teensy31.html
    //   http://www.pjrc.com/store/octo28_adaptor.html
    //
    // Line Level Audio Input connects to analog pin A3
    //   Recommended input circuit:
    //   http://www.pjrc.com/teensy/gui/?info=AudioInputAnalog
    //
    // This example code is in the public domain.
    
    
    #include <OctoWS2811.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SD.h>
    #include <SPI.h>
    
    // The display size and color to use
    const unsigned int matrix_width = 60;
    const unsigned int matrix_height = 32;
    const unsigned int myColor = 0x400020;
    
    // These parameters adjust the vertical thresholds
    const float maxLevel = 0.5;      // 1.0 = max, lower is more "sensitive"
    const float dynamicRange = 40.0; // total range to display, in decibels
    const float linearBlend = 0.3;   // useful range is 0 to 0.7
    
    // OctoWS2811 objects
    const int ledsPerPin = matrix_width * matrix_height / 8;
    DMAMEM int displayMemory[ledsPerPin*6];
    int drawingMemory[ledsPerPin*6];
    const int config = WS2811_GRB | WS2811_800kHz;
    OctoWS2811 leds(ledsPerPin, displayMemory, drawingMemory, config);
    
    // Audio library objects
    AudioInputAnalog         adc1(A3);       //xy=99,55
    AudioAnalyzeFFT1024      fft;            //xy=265,75
    AudioConnection          patchCord1(adc1, fft);
    
    
    // This array holds the volume level (0 to 1.0) for each
    // vertical pixel to turn on.  Computed in setup() using
    // the 3 parameters above.
    float thresholdVertical[matrix_height];
    
    // This array specifies how many of the FFT frequency bin
    // to use for each horizontal pixel.  Because humans hear
    // in octaves and FFT bins are linear, the low frequencies
    // use a small number of bins, higher frequencies use more.
    int frequencyBinsHorizontal[matrix_width] = {
       1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
       2,  2,  2,  2,  2,  2,  2,  2,  2,  3,
       3,  3,  3,  3,  4,  4,  4,  4,  4,  5,
       5,  5,  6,  6,  6,  7,  7,  7,  8,  8,
       9,  9, 10, 10, 11, 12, 12, 13, 14, 15,
      15, 16, 17, 18, 19, 20, 22, 23, 24, 25
    };
    
    
    
    // Run setup once
    void setup() {
      // the audio library needs to be given memory to start working
      AudioMemory(12);
    
      // compute the vertical thresholds before starting
      computeVerticalLevels();
    
      // turn on the display
      leds.begin();
      leds.show();
    }
    
    // A simple xy() function to turn display matrix coordinates
    // into the index numbers OctoWS2811 requires.  If your LEDs
    // are arranged differently, edit this code...
    unsigned int xy(unsigned int x, unsigned int y) {
      if ((y & 1) == 0) {
        // even numbered rows (0, 2, 4...) are left to right
        return y * matrix_width + x;
      } else {
        // odd numbered rows (1, 3, 5...) are right to left
        return y * matrix_width + matrix_width - 1 - x;
      }
    }
    
    // Run repetitively
    void loop() {
      unsigned int x, y, freqBin;
      float level;
    
      if (fft.available()) {
        // freqBin counts which FFT frequency data has been used,
        // starting at low frequency
        freqBin = 0;
    
        for (x=0; x < matrix_width; x++) {
          // get the volume for each horizontal pixel position
          level = fft.read(freqBin, freqBin + frequencyBinsHorizontal[x] - 1);
    
          // uncomment to see the spectrum in Arduino's Serial Monitor
          // Serial.print(level);
          // Serial.print("  ");
    
          for (y=0; y < matrix_height; y++) {
            // for each vertical pixel, check if above the threshold
            // and turn the LED on or off
            if (level >= thresholdVertical[y]) {
              leds.setPixel(xy(x, y), myColor);
            } else {
              leds.setPixel(xy(x, y), 0x000000);
            }
          }
          // increment the frequency bin count, so we display
          // low to higher frequency from left to right
          freqBin = freqBin + frequencyBinsHorizontal[x];
        }
        // after all pixels set, show them all at the same instant
        leds.show();
        // Serial.println();
      }
    }
    
    
    // Run once from setup, the compute the vertical levels
    void computeVerticalLevels() {
      unsigned int y;
      float n, logLevel, linearLevel;
    
      for (y=0; y < matrix_height; y++) {
        n = (float)y / (float)(matrix_height - 1);
        logLevel = pow10f(n * -1.0 * (dynamicRange / 20.0));
        linearLevel = 1.0 - n;
        linearLevel = linearLevel * linearBlend;
        logLevel = logLevel * (1.0 - linearBlend);
        thresholdVertical[y] = (logLevel + linearLevel) * maxLevel;
      }
    }
    Last edited by daterdots; 02-19-2023 at 05:37 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •