periodic freeze with FastLED

Status
Not open for further replies.
I am working on a simple VU-meter with additional mic input (Karaoke).
The bare audio works fine, but when I use FastLED I get a periodic freeze. Roughly every 30 seconds the Teensy stops, emitting a beep for 2 seconds and then continues (most of the time). Any hints are highly appreciated. :)


This is my setup:
Teensy 4.1,
AudioShield for Teensy 4.0
i2s1 input: Audio from PC
i2s2 input: SPH0645 Microphone on pins 3, 4, 5
Vol pot A1
mic gain pot A17
66 APA102 LEDs on Data pin 16, Clock pin 17


CPU Speed: 150 MHz
Optimize: faster

Code:
#include <FastLED.h>
FASTLED_USING_NAMESPACE
#define DATA_PIN    16          // green
#define CLK_PIN     17          // yellow
#define LED_TYPE    APA102
//#define LED_TYPE    WS2812
#define COLOR_ORDER BGR
#define NUM_LEDS    66          
CRGB leds[NUM_LEDS];
#define BRIGHTNESS          16
uint8_t H = 0; 
uint8_t gHue = 0; // rotating "base color" used by many of the patterns


/*
xxxxxxxxxxxxxxxxxx|x|xxxxxxxxxxxxxxxxxx 
1               18   20              37 


xxxxxxxxxxxxxxxxxx|xx|xxxxxxxxxxxxxxxxxx 
1               32    35              66 


xxxxxxxxxxxxxxxxxx|xx|xxxxxxxxxxxxxxxxxx 
1               71    74             144 
*/


uint8_t startL  = NUM_LEDS/2 -1;          // automatic (if NUM_LEDs is an even number)
uint8_t middle1 = NUM_LEDS/2;
uint8_t middle2 = NUM_LEDS/2 +1;
uint8_t startR  = NUM_LEDS/2 +2;


/*
uint8_t startL  = 32;
uint8_t middle1 = 33;
uint8_t middle2 = 34;
uint8_t startR  = 35;
*/
/*
uint8_t startL  = 71;
uint8_t middle1 = 72;
uint8_t middle2 = 73;
uint8_t startR  = 74;
*/
/*
uint8_t startL  = 18;
uint8_t middle1 = 19;
uint8_t middle2 = 19;
uint8_t startR  = 20;
*/


#define ARRAY_SIZE 16        // we have 2x 7 bands and 2 peaks
uint8_t data[ARRAY_SIZE];    // read vector


#include <Audio.h>
//#include <Wire.h>
//#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>


const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;


// GUItool: begin automatically generated code
AudioInputI2S2           i2s2_Mic;         //xy=197,482
AudioInputI2S            audioInput;     //xy=218,276
AudioFilterStateVariable filter1;        //xy=329,486
AudioAnalyzePeak         peak_R;         //xy=397,394
AudioAnalyzePeak         peak_L;         //xy=402,179
AudioAnalyzeFFT256       myFFT_R;        //xy=445,350
AudioAnalyzeFFT256       myFFT_L;        //xy=457,225
AudioAmplifier           amp1;           //xy=478,451
AudioMixer4              mixerL;         //xy=699,255
AudioMixer4              mixerR;         //xy=701,343
AudioAnalyzeFFT256       mic_fft;        //xy=842,553
AudioOutputI2S           audioOutput;    //xy=909,305
AudioConnection          patchCord1(i2s2_Mic, 0, filter1, 0);
AudioConnection          patchCord2(audioInput, 0, myFFT_L, 0);
AudioConnection          patchCord3(audioInput, 0, peak_L, 0);
AudioConnection          patchCord4(audioInput, 0, mixerL, 0);
AudioConnection          patchCord5(audioInput, 1, myFFT_R, 0);
AudioConnection          patchCord6(audioInput, 1, peak_R, 0);
AudioConnection          patchCord7(audioInput, 1, mixerR, 0);
AudioConnection          patchCord8(filter1, 2, amp1, 0);         // (filter1, [0 1 2], 0); for Low- Band- and High Pass filter 
AudioConnection          patchCord9(amp1, mic_fft);
AudioConnection          patchCord10(amp1, 0, mixerL, 1);
AudioConnection          patchCord11(amp1, 0, mixerR, 1);
AudioConnection          patchCord12(mixerL, 0, audioOutput, 0);
AudioConnection          patchCord13(mixerR, 0, audioOutput, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=421,554
AudioControlSGTL5000     audioShield;    //xy=603,555
// GUItool: end automatically generated code


  float level_L[7], level_R[7], level_mic[7];
  uint8_t i;
  uint8_t pegel_L[7], pegel_R[7], pegel_mic[7];
  elapsedMillis fps =0;
  uint16_t Bass, Mid, Trem, Bass_L, Mid_L, Trem_L, Bass_R, Mid_R, Trem_R;
  uint8_t  leftPeak, rightPeak, micPeak;




void audioInputFFT() {
    if (myFFT_L.available() && myFFT_R.available()) {
    // 7 Bands @ 256 bins                      // one band is 172 Hz
    level_L[0] =  myFFT_L.read(0)*255;             // Bass  20 ..  150Hz = bin 0
    level_R[0] =  myFFT_R.read(0)*255;             
    level_L[1] =  myFFT_L.read(1, 2)*255;          // Mid  150 ..  2000Hz = bin 1..12
    level_R[1] =  myFFT_R.read(1, 2)*255;
    level_L[2] =  myFFT_L.read(3, 6)*255;
    level_R[2] =  myFFT_R.read(3, 6)*255;
    level_L[3] =  myFFT_L.read(7, 14)*255;
    level_R[3] =  myFFT_R.read(7, 14)*255;
    level_L[4] =  myFFT_L.read(15, 30)*255;        // Trem 2000 .. 20000Hz = bin 13 .. 122
    level_R[4] =  myFFT_R.read(15, 30)*255;
    level_L[5] =  myFFT_L.read(31, 61)*255;
    level_R[5] =  myFFT_R.read(21, 61)*255;
    level_L[6] =  myFFT_L.read(62, 122)*255;
    level_R[6] =  myFFT_R.read(62, 122)*255;
    
    for (i=0; i<7; i++) {
      pegel_L[i] = level_L[i];
      pegel_R[i] = level_R[i];
//      Serial.print("L "); Serial.print(pegel_L[i]); Serial.print("\t");
//      Serial.print("R "); Serial.print(pegel_R[i]); Serial.println("\t");
      } // end pegel
  } // end myFET
}   // end audioInputFFT


void micInputFFT() {
   if (mic_fft.available()) {
    level_mic[0] =  mic_fft.read(0)*255;                 
    level_mic[1] =  mic_fft.read(2, 3)*255;               // changed from (1, 3) to (2, 3)
    level_mic[2] =  mic_fft.read(4, 10)*255;
    level_mic[3] =  mic_fft.read(11, 28)*255;
    level_mic[4] =  mic_fft.read(29, 74)*255;
    level_mic[5] =  mic_fft.read(75, 195)*255;
    level_mic[6] =  mic_fft.read(196, 511)*255;   


      for (i=0; i<7; i++) {
      pegel_mic[i] = level_mic[i];
              }   
   }
}


void add_mic() {
// mic is mono, that's why we add the same value to L and R 
delay(2);  
  level_L[0] =  level_L[0];
  level_R[0] =  level_R[0];
  level_L[1] = (level_L[1] + level_mic[1]);
  level_R[1] = (level_R[1] + level_mic[1]);
  level_L[2] = (level_L[2] + level_mic[2]);
  level_R[2] = (level_R[2] + level_mic[2]); 
  level_L[3] = (level_L[3] + level_mic[3]);
  level_R[3] = (level_R[3] + level_mic[3]); 
  level_L[4] = (level_L[4] + level_mic[4]);
  level_R[4] = (level_R[4] + level_mic[4]); 
  level_L[5] = (level_L[5] + level_mic[5]);
  level_R[5] = (level_R[5] + level_mic[5]); 
  level_L[6] = (level_L[6] + level_mic[6]);
  level_R[6] = (level_R[6] + level_mic[6]); 


    for (i=0; i<7; i++) {
      pegel_L[i] = level_L[i];
      pegel_R[i] = level_R[i];
    }
//Serial.print(pegel_L[0]); Serial.print("  "); Serial.print(pegel_L[1]); Serial.print("  "); Serial.print(pegel_L[2]); Serial.print("  "); Serial.print(pegel_L[3]); Serial.print("  "); Serial.print(pegel_L[4]); Serial.print("  "); Serial.print(pegel_L[5]); Serial.print("  "); Serial.print(pegel_L[6]); Serial.println("  "); 
 }


void combine2data(){
data[0] = level_L[1];
data[1] = level_L[2];
data[2] = level_L[3];
data[3] = level_L[4];
data[4] = level_L[5];
data[5] = level_L[6];
data[6] = level_L[7];


data[7] = level_R[1];
data[8] = level_R[2];
data[9] = level_R[3];
data[10] = level_R[4];
data[11] = level_R[5];
data[12] = level_R[6];
data[13] = level_R[7];


data[14] = (data[0] + data[1] + data[2] +  data[3] +  data[4] +  data[5] +  data[6]) /8;
data[15] = (data[7] + data[8] + data[9] + data[10] + data[11] + data[12] + data[13]) /8;


// we have 66 LEDs in total, with 2 in the middle we have 32 on each side.
// data is 0..255, that's why we divide the 


//pegel_L = data[14];
//pegel_R = data[15];
//Serial.print(pegel_L); Serial.print("  "); Serial.println(pegel_L);


//Serial.print(data[14]); Serial.print("  "); Serial.print(-data[15]); Serial.print("  "); Serial.print(data[15]-data[14]); Serial.print("  "); Serial.println(0);  
//if ((data[14] > 250) || ((data[15]) > 250)) { Serial.print(data[14]); Serial.print("  "); Serial.print(-data[15]); Serial.println("  "); }
// it looks like it never exceeds 255


// we have 66 LEDs in total, with 2 in the middle we have 32 on each side.
// data is 0..255, that's why we divide the value with 8
uint8_t PEGEL_L = data[14];
uint8_t PEGEL_R = data[15];
//Serial.print(PEGEL_L); Serial.print("  "); Serial.print(-PEGEL_R); Serial.print("  "); Serial.println(0);
//Serial.println(PEGEL_R - PEGEL_L); 
}


void SerialPlotOnMonitor(){
// print data for serial plotter
Serial.print(data[14]);                   // extract certain values out of the 14 bytes (here peak L and R)
Serial.print(" ");
Serial.print(-data[15]);                  // we only have two values. Let's make the right channel negative
Serial.print(" ");       
Serial.print(data[14] - data[15]);       // print the delta (wow !!)
Serial.print(" ");
Serial.print("0");                         // print the middle line ;)
Serial.print(" ");
Serial.println(); 
}


void VU_solid(){
leds[middle1] = CRGB::White;                   // we do something with the intentional blank LED in the middle
leds[middle2] = CRGB::White;
for (uint8_t PEGEL_L = startL; PEGEL_L >= (startL - data[14]); PEGEL_L--) {     
  if (PEGEL_L <= 0) { PEGEL_L = 0; }
  leds[PEGEL_L] = CRGB::Blue;                 // left side is blue
}
for (uint8_t PEGEL_R = startR; PEGEL_R < (data[15] + startR); PEGEL_R++) {    //start with LEDno 20
  leds[PEGEL_R] = CRGB::Red;                  // right side is red
  FastLED.show();
  }
}


void colorCoolOff(){
  FastLED.delay(10);
  fadeToBlackBy( leds, NUM_LEDS, 20);        // higher values more hectic, lower values smoother
    FastLED.show();
}


void setup() {
  AudioMemory(15);        // determine value with AudioMemoryUsageMax(); 
  filter1.frequency(120); // filter out DC & extremely low frequencies  looks like we should use 90Hz as corner frequency @fft1024 and 120Hz @fft256
  amp1.gain(8.5);         // amplify sign to useful range


  audioShield.enable();
  audioShield.inputSelect(myInput);
//  audioShield.volume(0.5);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  
  // Configure the window algorithm to use
  myFFT_L.windowFunction(AudioWindowHanning256);
  myFFT_R.windowFunction(AudioWindowHanning256);
  mic_fft.windowFunction(AudioWindowHanning256);
  //myFFT.windowFunction(NULL);
  FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
//  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);  // set master brightness control
  FastLED.clear();
  FastLED.show();
}


void loop() {


// reading the pots must be in the loop. Subroutine does not work
    float vol = analogRead(A1);     // read the shield's volume pot
    vol = vol / 1024;               // orig. setting but VERY loud, however good for cell phone input
//    vol = vol / 1536;             // (1024 *3/2) is good for my headset
//    Serial.println(vol);
    sgtl5000_1.volume(vol);         // write it out


    int mic = analogRead(A17);      // read the external mic pot (A17 is right next to Gnd)
    mic = mic / 100;                // this is a range of 0..10
//  Serial.println(mic);
    amp1.gain(mic);                 // write it out


audioInputFFT();
micInputFFT();
add_mic();
combine2data();
SerialPlotOnMonitor();
VU_solid();
colorCoolOff();
delay(15);


}  // end loop
 
Probably a lack of power or of bulk decoupling on the LED supply - I make it 4A peak needed for 66 of
those RGB leds, so the supply and decoupling needs to be up to the heavy load they pose and the
rapid current fluctuation.
 
Status
Not open for further replies.
Back
Top