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

Thread: ADC in free running on Teensy 3.6

  1. #1
    Junior Member
    Join Date
    Oct 2019
    Posts
    2

    ADC in free running on Teensy 3.6

    ADC in free running on Teensy 3.6

    Hello, I am trying to port a program I had on an Arduino Mega which takes samples of live music and runs FFT over them. I am hoping to replicate this functionality on the teensy exactly as it was on the Arduino, just much faster, and with more samples. Here is the program as it was on the Arduino:

    Code:
        void setup() {
    
            ADCSRA = 0b11100110;      // set ADC to free running mode and set pre-scalar to 32 (0xe5)
    
            ADMUX = 0b00000000;       // use pin A0 and external voltage reference
        }
    
    
        void loop() {
           // ++ Sampling
    
           for(int i=0; i<SAMPLES; i++)
            {
              while(!(ADCSRA & 0x10));        // wait for ADC to complete current conversion ie ADIF bit set
              ADCSRA = 0b11110101 ;               // clear ADIF bit so that ADC can do next operation (0xf5)
              int value = ADC - 512 ;                 // Read from ADC and subtract DC offset caused value
              vReal[i]= value/4;                      // Copy to bins after compressing
              vImag[i] = 0;                         
            }
            // -- Sampling
        }

    Can I use analogRead() to get the same effect? How can I port this code over to work the same way? I want to make sure it will still have ADC in free running mode, but the tutorial on this site for that didn't seem to compile for a Teensy 3.6 using Teensyduino. Thank you for any help you can give me!

  2. #2
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,905
    Is there any particular reason to not use the Teensy optimized audio library?
    https://www.pjrc.com/teensy/td_libs_Audio.html
    Which has an inbuilt FFT.
    If your application wants more specialization you probably want
    https://forum.pjrc.com/threads/25532...for-Teensy-3-1
    And us it in the mode where both ADCs are used on the same pin.

  3. #3
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,231
    The audio lib has some examples of FFT and analog input. Here is a slightly messy sketch that samples (44.1khz) mic input on Teensy A2 and runs fft1024 and displays FFT cells on tiny OLED (SPI or I2C version). The teensy audio lib manages ADC and FFT with double-buffered DMA @44.1KHz. The example does not require the PJRC audio adaptor board.
    Code:
    // Spectrum Analyzer using a Teensy 3.2 & OLED 128x32 mono
    //  Test microphone is connected to A2, I2C and pin 4 or SPI
    // https://forum.pjrc.com/threads/45418-FFT-analysis-using-teensy-3-2
    #include <SPI.h>
    #include <Wire.h>
    #include <Audio.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    
    #define HT 31
    #define WD 128
    
    // define 1 for I2C  else 0 will do SPI
    #define DOI2C  0
    
    #if DOI2C
    #define OLED_RESET 4
    Adafruit_SSD1306 display(OLED_RESET);
    #else
    #define OLED_DC     6
    #define OLED_CS     7
    #define OLED_RESET  8
    Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
    #endif
    
    #define MIC_GAIN  2  // multiplier for the specific mic
    
    //Set-up the audio library functions
    AudioInputAnalog         adc1(A2);             //default for adc1 is A2
    AudioAnalyzeFFT1024      fft1024_1;
    AudioConnection          patchCord1(adc1, fft1024_1);
    
    // An array to hold the 16 frequency bands
    float level[16];
    
    void setup() {
      Serial.begin(9600);
      //  while (!Serial);
    
    #if DOI2C
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
    #else
      display.begin(SSD1306_SWITCHCAPVCC);
    #endif
      display.display();   // splash screen
      delay(2000);
    
    #if DOI2C
      //  TWBR = 12;   // I2C @400khz  really 333khz
      I2C0_F = 0x1a;    // I2C analyzer shows 395khz
    #endif
    
    #if 0
      // benchmark
      for (int i = 0; i < 10; i++) {
        uint32_t t = micros();
        display.display();
        t = micros() - t;
        Serial.println(t);
        delay(1000);
      }
    #endif
    
    
      // Audio connections require memory to work.
      AudioMemory(12);
    
      // Configure the window algorithm to use
      fft1024_1.windowFunction(AudioWindowHanning1024);
    
    }
    
    
    void spectrum() {
      uint32_t  t2;
    
      if (fft1024_1.available()) {
        // each time new FFT data is available, bin it into 16 channels, octaves
        // Note- response doesn't seem flat so each is normalized <experimenting!
        // Note- these calculations go very fast!
    
        level[0] =  fft1024_1.read(0) * 1.21 * MIC_GAIN;
        level[1] =  fft1024_1.read(1) * 1.18 * MIC_GAIN;
        level[2] =  fft1024_1.read(2, 3) * 1.15 * MIC_GAIN;
        level[3] =  fft1024_1.read(4, 6) * 1.12 * MIC_GAIN;
        level[4] =  fft1024_1.read(7, 10) * 1.09 * MIC_GAIN;
        level[5] =  fft1024_1.read(11, 15) * 1.06 * MIC_GAIN;
        level[6] =  fft1024_1.read(16, 22) * 1.03 * MIC_GAIN;
        level[7] =  fft1024_1.read(23, 32) * 1.00 * MIC_GAIN;
        level[8] =  fft1024_1.read(33, 46) * 0.96 * MIC_GAIN;
        level[9] =  fft1024_1.read(47, 66) * 0.93 * MIC_GAIN;
        level[10] = fft1024_1.read(67, 93) * 0.90 * MIC_GAIN;
        level[11] = fft1024_1.read(94, 131) * 0.87 * MIC_GAIN;
        level[12] = fft1024_1.read(132, 184) * 0.84 * MIC_GAIN;
        level[13] = fft1024_1.read(185, 257) * 0.81 * MIC_GAIN;
        level[14] = fft1024_1.read(258, 359) * 0.78 * MIC_GAIN;
        level[15] = fft1024_1.read(360, 511) * 0.75 * MIC_GAIN;
    
        //***** LCD OUTPUT
        t2 = micros();
        display.clearDisplay();
    
        for (int i = 0; i < 16; i++) {
          int line1 = level[i] * HT;
          if (line1 > HT) {
            line1 = HT;
          }
          display.fillRect(i * 8,  HT - line1, 6, line1 + 1, 1); // insure a base line of 1
        }
        display.display();
        t2 = micros() - t2;
    #if 0
        Serial.println(t2);
    #endif
      }
    }
    
    void spectrum_bins() {
      // just linear FFT data first 128 bins
      int h, i;
      uint32_t t2;
    
      if (fft1024_1.available()) {
        t2 = micros();
        display.clearDisplay();
        for (i = 0; i < WD; i++) {
          h = 5 * HT * fft1024_1.read(i); // need * MICGAIN ?
          // display.drawLine(i, HT - h, i, HT, WHITE);
          display.drawFastVLine(i, HT - h, h, WHITE);
        }
        display.display();
        t2 = micros() - t2;
    #if 0
        Serial.println(t2);
    #endif
      }
    }
    
    void print_fft() {
      float n;
      int i;
    
      if (fft1024_1.available()) {
        // each time new FFT data is available
        // print it all to the Arduino Serial Monitor
        int printed = 0;
        //  Serial.print("FFT: ");
        for (i = 0; i < 40; i++) {
          n = fft1024_1.read(i);
          if (n >= 0.04) {
            printed = 1;
            Serial.print(i); Serial.print(":");
            Serial.print(n);
            Serial.print(" ");
          } else {
            //Serial.print("  -  "); // don't print "0.00"
          }
        }
        if (printed)Serial.println();
      }
    }
    
    void loop() {
      // pick one
      //spectrum();  //octaves
      spectrum_bins();
      // print_fft();
    
    }
    I don't think the mic I was using is available any longer.

    OLEDs:
    https://www.adafruit.com/product/931
    https://www.adafruit.com/product/661

Tags for this Thread

Posting Permissions

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