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

Thread: Teensy 4 audio ticking with audio board and Neopixels

  1. #1
    Junior Member
    Join Date
    May 2020
    Posts
    6

    Teensy 4 audio ticking with audio board and Neopixels

    Hello-
    First post here. I have a problem with rapid ticking on top of a WAV being played, listening with earbuds through the audio plug of a Teensy soundboard. Equipment: Teensy 4, Audio Board Rev. D, I2C OLED screen, Neopixel 8x5 matrix (with 74AHCT125 level shifter). The Teensy is powered by USB from a dock, Neopixels are powered by an Adafruit 5V power supply. Grounds are tied together.

    The project is a light board like at the end of Close Encounters. The Teensy reads a WAV off the micro-SD, plays the audio through the earphone jack on the audio board, calculates the FFT of the sound, displays the FFT on a 1.3" OLED monitor, and maps the FFT onto the Neopixel matrix. Though I'm pretty new with Arduinos and brand new with Teensy, the code works, with one little problem.

    When I was building the code, up through computing and displaying the FFT on the OLED, the sound through the earphones was perfect. However, a problem with the audio showed up when I introduced the Neopixels. When I'm using the Neopixels, there's a rapid ticking that I think is connected to the Neopixel updating; putting in a delay after the updating (delaying the next run through the loop that assigns brightnesses and updates the OLED) results in a change to the ticking frequency (greater delay means more time between ticks). Ticking is there with a small powered speaker as well, so it's not just the earphones.

    I'd like to be able to get rid of the ticking. Not sure what I'm doing wrong, if the problem is in the code or if I'm missing some component in the circuit. I don't have any resistors or capacitors in the circuit (except for one in the power supply line) and maybe I need to put some somewhere, but I don't know where to start on that.

    Thank you for whatever ideas you have.

    Code:
    // 
    //Based mainly on:
    // Advanced Microcontroller-based Audio Workshop
    //
    // http://www.pjrc.com/store/audio_tutorial_kit.html
    // https://hackaday.io/project/8292-microcontroller-audio-workshop-had-supercon-2015
    // 
    //
    
    
    #include <Adafruit_NeoPixel.h>  //For the Neopixels
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // OLED routines here
    #include <Adafruit_GFX.h>                             // graphics library for display
    #include <Adafruit_SSD1306.h>                         // SSD1306 OLED display library
    #define OLED_RESET 5                                  // OLED library likes to see this but it isn't used here with I2C, changed to deconflict with sound board
    #define OLED_ADDR 0x3D                                // OLED I2C address
    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);                 // create instance of OLED display
    byte ylim = 60;                                       //sets vertical pixel limit of histogram
    
    //below, do Neopixel setup, to CE3K light board colors
    #define PIN 6  // Which pin on the Arduino is connected to the NeoPixels?
    #define NUMPIXELS 40  //There are 40 Neopixels on the board
    Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
    //set up color mapping for the Neopixels
    int redc[] ={255,255,175,50,0,96,168,218,255,255,150,25,0,128,178,228,255,255,125,0,0,138,288,238,255,230,100,0,32,148,198,248,255,200,75,0,64,158,208,255};
    int greenc[]={128,218,255,255,102,0,0,0,146,236,255,255,51,0,0,0,164,255,255,255,0,0,0,0,182,255,255,204,0,0,0,0,200,255,255,153,0,0,0,0};
    int bluec[]={0,0,0,0,153,255,155,55,0,0,0,0,202,255,135,35,0,0,0,0,255,235,115,15,0,0,0,51,255,205,95,0,0,0,0,102,255,185,75,0};
    int MAXBRIGHT=10;
    //for storing the Neopixel brightnesses
    int reds[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int greens[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int blues[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    //
    
    //next code initializes many things, taken from the graphical audio configurator
    AudioPlaySdWav           playWav1;
    AudioMixer4              mixer1;
    AudioOutputI2S           audioOutput; //plays through 3.5mm jack
    AudioControlSGTL5000     sgtl5000_1;
    AudioAnalyzeFFT1024      fft1024_1;      //xy=562,298
    AudioConnection          patchCord1(playWav1, 0, audioOutput, 0);
    AudioConnection          patchCord2(playWav1, 1, audioOutput, 1);
    AudioConnection          patchCord3(playWav1, 0, mixer1, 0);
    AudioConnection          patchCord4(playWav1, 1, mixer1, 1);
    AudioConnection          patchCord5(mixer1, fft1024_1);
    
    // Use these with the Teensy Audio Shield
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  7  //changing these from their defaults to deconflict with the I2C display
    #define SDCARD_SCK_PIN   14 //changing these from their defaults to deconflict with the I2C display
    
    
    void setup() {
    
      //OLED setup information
      display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);     // initialize OLED display
      display.clearDisplay();                             // blank the display
      display.setTextSize(1);                             // configure text properties
      display.setTextColor(WHITE);
    
      //Neopixel setup information
      pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
      pixels.clear(); // Set all pixel colors to 'off'
      
      Serial.begin(9600);
      AudioMemory(100);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.2);
      SPI.setMOSI(SDCARD_MOSI_PIN);
      SPI.setSCK(SDCARD_SCK_PIN);
        if (!(SD.begin(SDCARD_CS_PIN))) {
         while (1) {
          Serial.println("Unable to access the SD card");
          delay(500);
          }
        }
     
      mixer1.gain(0, 2.0);
      mixer1.gain(1, 2.0);
      mixer1.gain(2, 0.0);
      mixer1.gain(3, 0.0);
      // Uncomment one these to try other window functions
      fft1024_1.windowFunction(AudioWindowHanning1024);
      // fft1024_1.windowFunction(NULL);
      // fft1024_1.windowFunction(AudioWindowBartlett1024);
      // fft1024_1.windowFunction(AudioWindowFlattop1024);
      delay(1000);
    //  playWav1.play("DIALOGUE.WAV");
      Serial.print("Finishing setup");
      Serial.println();
      
    }
    
    
    
    void loop() {                                              // begin the master loop
      pixels.clear(); // Set all Neopixels to 'off'
      playWav1.play("DIALOGUE.WAV");                           // "Play the five tones..."
      display.clearDisplay();                                  // clear the OLED display
      display.display();                                       // send the data to the OLED display
      delay(10);                                               // give time for the music to start
      while (playWav1.isPlaying()) {  //while the music is playing, compute and display the FFT
        // uncomment these lines if you audio shield
        // has the optional volume pot soldered
        //float vol = analogRead(15);
        //vol = vol / 1024;
        // sgtl5000_1.volume(vol)
        
      
        // print Fourier Transform data to the Arduino Serial Monitor and OLED
        if (fft1024_1.available()) {
           display.clearDisplay();                             // clear the OLED display
           display.setCursor(0, 0);                            // set cursor to top left corner of the display
           display.print("Audio Spectrum");                    // print a header on the top row of the display
        
     //      Serial.print("FFT: ");
           for (int i=0; i<40; i++) {  // 0-60  -->  DC to 23409 Hz at 39 Hz/bin
           float n = fft1024_1.read(i);
     //      printNumber((n));
           display.drawLine(i*2, ylim, i*2, ylim - (512*n), WHITE);
           // calculate the brightnesses of the pixels
              reds[i]=redc[i]*((512*n)/64)*MAXBRIGHT/255;
              greens[i]=greenc[i]*((512*n)/64)*MAXBRIGHT/255;
              blues[i]=bluec[i]*((512*n)/64)*MAXBRIGHT/255;
              //below are sanity checks for LED brightness
              if(reds[i]>=250) {
                  reds[i]=250;
                 }
                        if(greens[i]>=250) {
                  greens[i]=250;
                 }
                        if(blues[i]>=250) {
                  blues[i]=250;
                 }
              pixels.setPixelColor(i, pixels.Color(reds[i], greens[i], blues[i]));
              }
              
           }
    //    Serial.println();
        display.display();      //send the FFT data to the OLED display
        pixels.show();          // Send the updated pixel colors to the Neopixels
    
       
      
     } //This loop finishes when the music stops; then the master loop repeats, restarting the music
    
    }
    
    void printNumber(float n) {                               //this function sets up the format for printing output to the serial line
      
      if (n >= 0.003) {
        Serial.print(n, 3);
        Serial.print(" ");
      } else {
        Serial.print("   -  "); // don't print "0.00"
      }
     
    }

  2. #2
    Member
    Join Date
    Jan 2020
    Location
    Italy
    Posts
    88
    It is the neopixels block the interrupt.
    I know the timing of signal in the neopixels is critical, so there are interrups blocked.
    https://learn.adafruit.com/adafruit-...dvanced-coding
    FastLED could help.
    https://github.com/FastLED/FastLED/w...rrupt-problems

    Or use Paul's WS2812Serial
    https://forum.pjrc.com/threads/51143...and-brightness

    https://github.com/PaulStoffregen/WS2812Serial

  3. #3
    Junior Member
    Join Date
    May 2020
    Posts
    6
    Thank you! I'll take a look.

  4. #4
    Junior Member
    Join Date
    May 2020
    Posts
    6
    I was able to change the code to use the FastLED library, and everything basically works, but I still have the ticking. I tried adding in #define FASTLED_ALLOW_INTERRUPTS 0 before #include <FastLED.h> and the code refused to compile. If I replace that interrupt line with #define FASTLED_INTERRUPT_RETRY_COUNT 1, the code works (with ticking noise), but it's not very stable, there are LED and audio glitches.

    Any other ideas? If I have to live with it as-is, it's good enough for the immediate purpose, but I would like to figure out the ticking at some point.

    Thanks again.

  5. #5
    Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    86
    try
    #include <OctoWS2811.h>
    #define USE_OCTOWS2811
    #include <FastLED.h>

    in that order

  6. #6
    Member
    Join Date
    Jan 2020
    Location
    Italy
    Posts
    88
    Maybe this WS2812Serial is better with T4, if you can work with the higher use of RAM.

  7. #7
    Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    86
    I'm fairly sure the neopixels are ws2811s (rather than ws2812s)

    The OctoWS2811.h lib is another of Paul's non-blocking libs that you can use with FastLED as in #5

  8. #8
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,690
    Quote Originally Posted by houtson View Post
    I'm fairly sure the neopixels are ws2811s (rather than ws2812s)

    The OctoWS2811.h lib is another of Paul's non-blocking libs that you can use with FastLED as in #5
    I believe the original Adafruit neopixels used the WS2812's, then moved to the WS2812B's, and now they generally use SK6812's.

    Here are two pages that I've seen that compare them:


    IIRC, the WS2812B's were the ones that needed at least 4.5v power, and needed the high speed level shifting to go from a 3.3v data signal to 5v. I've run SK6812's on lipo batteries (i.e. 3.7v) and even off of 3.3v from the Teensy (providing I'm careful not to exceed the 250ma power for the Teensy + LEDs).

  9. #9
    Junior Member
    Join Date
    May 2020
    Posts
    6
    I added the Octo lines, and there was no ticking, but no LEDs, and the code hung up first run through.

  10. #10
    Junior Member
    Join Date
    May 2020
    Posts
    6
    Maybe I’m doing this the hard way... Could I get a 3.5 mm male to 2x (L/R) RCA cord, strip the RCA ends and solder them to the line-in on the audio board? And plug the 3.5mm plug into any old source for the audio input, rather than reading/playing a WAV from the SD card? I can use a splitter to send the audio to a portable speaker at the same time. Then the Teensy won’t have to play the sound, just “listen.”

    Should that work? No capacitors or whatever needed?

  11. #11
    Senior Member
    Join Date
    Feb 2016
    Location
    Australia
    Posts
    254
    Quote Originally Posted by jgoldader View Post
    M...Could I get a 3.5 mm male to 2x (L/R) RCA cord, strip the RCA ends and solder them to the line-in on the audio board? And plug the 3.5mm plug into any old source for the audio input, rather than reading/playing a WAV from the SD card? I can use a splitter to send the audio to a portable speaker at the same time. Then the Teensy won’t have to play the sound, just “listen.” ...
    Yes you could do that.
    You could use your audio board as the splitter if you setup the mixers.
    I know thats what I did rather than looking into an issues I was having with sdcard playback octows2811 code.
    It's something else to help you diagnose your issue anyway.

  12. #12
    Junior Member
    Join Date
    May 2020
    Posts
    6
    Well, this was an adventure, but it ended well!

    I got the line in to work, no trouble at all. FastLED worked well in "demo" mode, just to set the pixel colors. However, it absolutely refused to address more than about 26 of the Neopixels in the array, no matter what I did, when it was "active". (EDIT: I think it was a timing error.) So, I resurrected the version I wrote using the Neopixel library, modifying it to work with the line in. I'm very happy with the end result.

    I'm grateful for the suggestions! Here's the code, in case someone else wants to try this project.

    Code:
    // 
    //Based mainly on:
    // Advanced Microcontroller-based Audio Workshop
    //
    // http://www.pjrc.com/store/audio_tutorial_kit.html
    // https://hackaday.io/project/8292-microcontroller-audio-workshop-had-supercon-2015
    //  OLED display routines from learnelectronics:      https://www.youtube.com/watch?v=5RmQJtE61zE
    // 
    //
    
    
    #include <Adafruit_NeoPixel.h>  //For the Neopixels
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // OLED routines here
    #include <Adafruit_GFX.h>                             // graphics library for display
    #include <Adafruit_SSD1306.h>                         // SSD1306 OLED display library
    #define OLED_RESET 5                                  // OLED library likes to see this but it isn't used here with I2C, changed to deconflict with sound board
    #define OLED_ADDR 0x3D                                // OLED I2C address
    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);                 // create instance of OLED display
    byte ylim = 60;                                       //sets vertical pixel limit of histogram
    
    //below, do Neopixel setup, to CE3K light board colors
    #define PIN 1  // Which pin on the Arduino is connected to the NeoPixels?
    #define NUMPIXELS 40  //There are 40 Neopixels on the board
    Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
    //set up color mapping for the Neopixels
    int redc[] ={255,255,175,50,0,96,168,218,255,255,150,25,0,128,178,228,255,255,125,0,0,138,288,238,255,230,100,0,32,148,198,248,255,200,75,0,64,158,208,255};
    int greenc[]={128,218,255,255,102,0,0,0,146,236,255,255,51,0,0,0,164,255,255,255,0,0,0,0,182,255,255,204,0,0,0,0,200,255,255,153,0,0,0,0};
    int bluec[]={0,0,0,0,153,255,155,55,0,0,0,0,202,255,135,35,0,0,0,0,255,235,115,15,0,0,0,51,255,205,95,0,0,0,0,102,255,185,75,0};
    int MAXBRIGHT=25;
    //for storing the Neopixel brightnesses
    int reds[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int greens[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int blues[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    float scalfac[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    //
    
    //next code initializes many things, taken from the graphical audio configurator
    AudioInputI2S            i2s1;           //xy=180,280
    AudioMixer4              mixer1;         //xy=392,202
    AudioAnalyzeFFT1024      fft1024_1;      //xy=570,196
    AudioConnection          patchCord1(i2s1, 0, mixer1, 0);
    AudioConnection          patchCord3(i2s1, 1, mixer1, 1);
    AudioConnection          patchCord5(mixer1, fft1024_1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=302,184
    
    const int myInput = AUDIO_INPUT_LINEIN;
    
    // Use these with the Teensy Audio Shield
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  7  //changing these from their defaults to deconflict with the I2C display
    #define SDCARD_SCK_PIN   14 //changing these from their defaults to deconflict with the I2C display
    
    
    void setup() {
    
      //OLED setup information
      display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);     // initialize OLED display
      display.clearDisplay();                             // blank the display
      display.setTextSize(1);                             // configure text properties
      display.setTextColor(WHITE);
    
      //Neopixel setup information
      pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
      pixels.clear(); // Set all pixel colors to 'off'
      
      for(int i=0;i<40;i++) {
        scalfac[i]=3./39.*(float(i))+1; //scaling factor qualitatively accounts for the fact that higher frequencies sound louder
    
      }
      
      // Enable the audio shield, select input, and enable output
      sgtl5000_1.enable();
      sgtl5000_1.inputSelect(myInput);
      sgtl5000_1.volume(0.5);
      //  
      Serial.begin(9600);
      AudioMemory(100);
    
     
      mixer1.gain(0, 4);
      mixer1.gain(1, 4);
      mixer1.gain(2, 0.0);
      mixer1.gain(3, 0.0);
    
      fft1024_1.windowFunction(AudioWindowHanning1024);
      
    } //end Setup
    
    
    
    void loop() {               // begin the master loop
      
      pixels.clear();           // Set all Neopixels to 'off'
      display.clearDisplay();   // clear the OLED display
    
      
        // in the loop below, take, scale, and print Fourier Transform data to the Neopixels and OLED
        
        if (fft1024_1.available()) {
           display.clearDisplay();                             // clear the OLED display
           display.setCursor(0, 0);                            // set cursor to top left corner of the display
           display.print("Audio Spectrum");                    // print a header on the top row of the display
        
    
           for (int i=0; i<40; i++) {  // 0-39 there are 40 pixels in the array, and 43 Hz per bin
    //Decided to add 3 consecutive bins together; squeezing FFT to cover up to 5220 Hz
              float n=scalfac[i]*((fft1024_1.read(3*i)+fft1024_1.read(3*i+1)+fft1024_1.read(3*i+2))/3.0);
                    
              if((i<1)) {  //low-frequency noise suppression in the first couple of bins
                 if(n>=0.05){
                  n=n-0.05;
                 }
              }
              
           // draw the line for this bin on the OLED; the 512 was found from experimentation
           display.drawLine(i*2, ylim, i*2, ylim - (512*n), WHITE);
           
           // calculate the brightnesses of the pixels; coefficient 32 found from experimentation
    
              reds[i]=redc[i]*(n/32)*MAXBRIGHT;
              greens[i]=greenc[i]*(n/32)*MAXBRIGHT;
              blues[i]=bluec[i]*(n/32)*MAXBRIGHT;
    
              //below are sanity checks for LED brightness, keep them below 250 no matter what
              //
              if(reds[i]>=250) {
                  reds[i]=250;
                 }
              if(greens[i]>=250) {
                  greens[i]=250;
                 }
              if(blues[i]>=250) {
                  blues[i]=250;
                 }
    
              pixels.setPixelColor(i, pixels.Color(reds[i], greens[i], blues[i])); //build the Neopixel data array
              } //finish the pixel-by-pixel calculations
              
           }  //finish the FFT analysis loop
    
        display.display();      // send the FFT data to the OLED display
        pixels.show();          // send the updated pixel data to the Neopixels
    
    }
    
    void printNumber(float n) {     //this function sets up the format for printing output to the serial line, for debugging
      
      if (n >= 0.003) {
        Serial.print(n, 3);
        Serial.print(" ");
      } else {
        Serial.print("   -  "); // don't print "0.00"
      }
     
    }
    Last edited by jgoldader; 05-17-2020 at 07:55 PM.

Posting Permissions

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