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

Thread: Teensy 4.1 sketch freezes after adding any extra variable

  1. #1
    Junior Member
    Join Date
    Feb 2016
    Posts
    4

    Teensy 4.1 sketch freezes after adding any extra variable

    Hello all, I've come around to a weird problem.
    I have a program that computes a live FFT on an audio buffer and uses that to display that spectrum in an array of LEDs. There are 2 16x16 WS2812B LED matrixes connected to pin 11 and an amplified electret microphone connected to A0. A LDR is hooked to A1 for brightness control with ambient lighting. I am using a teensy 4.1 board.
    Here's the code and it runs without any problem:

    Code:
    #include <CircularBuffer.h>
    #include "arduinoFFT.h"
    #include <FastLED.h>
    
    
    #define kMatrixWidth  16
    #define kMatrixHeight 32
    const bool kMatrixSerpentineLayout = true;
    #define NUM_LEDS (kMatrixWidth * kMatrixHeight)
    #define DATA_PIN 11
    CRGB leds[NUM_LEDS];
    arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
    
    
    #define DEBUG_TIMING 0
    #define DEBUG_FFT_MAG 0
    #define DEBUG_LDR 0
    
    
    #define AUDIO_INPUT A0 // ADC channel
    #define BRIGHTNESS_INPUT A1// ADC channel
    
    
    double alpha=0.1,alpha_fft=0.25; //LPF for brightness input
    int brightness=0;
    const int LDR_MIN=200;
    const int LDR_MAX=700;
    const int MIN_BRIGHT=31;
    const int MAX_BRIGHT=255;
    const uint16_t samples = 256*16; //This value MUST ALWAYS be a power of 2
    const double samplingFrequency = 44000.0; //Hz, must be less than 10000 due to ADC
    const double fftFrequency = 25.0;//Hz
    
    
    CircularBuffer<int, samples> buffer;
    
    
    volatile unsigned long sampling_period_us,FFT_period_us;
    volatile unsigned long microseconds1,microseconds2;
    
    
    const uint16_t numbands=16;
    
    
    double vReal[samples];
    double vImag[samples];
    double freqV[samples>>1];
    double bandF[numbands+1];
    double bandMag[numbands];
    //from tests at 256 samples and 5 kHz sampling rate
    //double minscaleBands[numbands]={10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0};
    //double maxscaleBands[numbands]={5471.4,2999.49,3691.08,5952.2,4608.23,4428.21,4234.0,5254.41,4334.65,5718.69,5185.4,5938.3,6120.66,7552.29,5710.17};
    //from tests at 4096 samples and 44 kHz sampling rate
    //double minscaleBands[numbands]={10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0};
    //double maxscaleBands[numbands]={33306.2,39482.7,15209.3,9438.79,5834.15,3434.73,2651.32,1977.24,1352.12,949.501,1047.97,829.038,779.203,770.579,727.395,700.0};
    //from tests at 4096 samples and 44 kHz sampling rate and log bands
    double minscaleBands[numbands]={1000.0,1000.0,1000.0,1000.0,1000.0,1000.0,100.0,100.0,100.0,100.0,100.0,100.0,100.0,100.0,100.0,100.0};
    double maxscaleBands[numbands]={5000.0,5000.0,5000.0,15000.5,20000.5,22958.9,16103.6,31781.6,14431.2,20192.2,7876.23,9793.69,14957.8,5406.17,3446.98,3000.0};
    double scaling=1.5;
    double minfreqBand=60.0;
    double maxfreqBand=samplingFrequency/2.0;
    volatile int lvl=0;
    //double trololo;
    /*int singleBandIndex=4;
    int boolSingleBandMode=0;*/
    #define SCL_INDEX 0x00
    #define SCL_TIME 0x01
    #define SCL_FREQUENCY 0x02
    #define SCL_PLOT 0x03
    #if DEBUG_TIMING >0
    volatile long t0=0, t=0, t0_1=0, t_1=1;
    #endif
    void setup() {
            //Set ADC prescaler to 8
            Serial.begin(250000);
            sampling_period_us = round(1000000*(1.0/samplingFrequency));
            FFT_period_us = round(1000000*(1.0/fftFrequency));
            FastLED.addLeds<1,WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
            pinMode(AUDIO_INPUT, INPUT);
            pinMode(BRIGHTNESS_INPUT, INPUT);
            //populate freq vector for FFT
            for(uint16_t i=0; i<(samples>>1); i++)
            {
                    freqV[i] = ((i * 1.0 * samplingFrequency) / samples);
                    //Serial.println(freqV[i]);
            }
            //populate freq vector for bands
            for(uint16_t i=0; i<(numbands+1); i++)
            {
                    //bandF[i]=minfreqBand+((i * 1.0 * (maxfreqBand-minfreqBand)) / (double)(numbands+1));
                    bandF[i]=minfreqBand*pow(maxfreqBand/minfreqBand,((i * 1.0) / (double)(numbands+1)));
                    //Serial.println(bandF[i]);
            }
            for(uint16_t j=0; j<(kMatrixWidth*kMatrixHeight); j++)
            {
                    leds[j].r=255;
                    leds[j].g=0;
                    leds[j].b=0;
            }
            //FastLED.show();
            FastLED.delay(250);
            for(uint16_t j=0; j<(kMatrixWidth*kMatrixHeight); j++)
            {
                    leds[j].r=0;
                    leds[j].g=0;
                    leds[j].b=0;
            }
            //FastLED.show();
            FastLED.delay(250);
            //testMatrix();
            microseconds1 = micros();
            microseconds2 = millis();
            #if DEBUG_TIMING > 0
            t0=micros();
            t0_1=micros();
            #endif
    }
    void loop() {
    
    
            if((micros()-microseconds1)>=sampling_period_us)
            {       microseconds1 = micros();
                    int reading = analogRead(AUDIO_INPUT);
                    buffer.push(reading);
                    #if DEBUG_TIMING > 0
                    t=micros()-t0;
                    t0=micros();
                    #endif
            }
            if((micros()-microseconds2)>=FFT_period_us)
            {
                    microseconds2 = micros();
                    //Read brightness pot input and filter it
                    //Serial.println(analogRead(BRIGHTNESS_INPUT));
                    brightness=(1.0-alpha)*(float)constrain(map(analogRead(BRIGHTNESS_INPUT),LDR_MIN,LDR_MAX,MIN_BRIGHT,MAX_BRIGHT),MIN_BRIGHT,MAX_BRIGHT)+(alpha)*(float)brightness;
                    //Copy buffer data to vReal vect and clear vImag
                    for(uint16_t i=0; i<samples; i++)
                    {
                            vReal[i] = buffer[i];
                            vImag[i] = 0.0;
                    }
    
    
                    FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);         // Weigh data
                    FFT.DCRemoval();
                    FFT.Compute(vReal, vImag, samples, FFT_FORWARD);         // Compute FFT
                    FFT.ComplexToMagnitude(vReal, vImag, samples);         // Compute magnitudes
                    calculateBands(bandF,bandMag,freqV,vReal,numbands,samples>>1);
                    for(uint16_t j=0; j<(kMatrixWidth*kMatrixHeight); j++)
                    {
                            leds[j].r=0;
                            leds[j].g=0;
                            leds[j].b=0;
                    }
                    for(uint16_t j=0; j<kMatrixWidth; j++)
                    {
                            /*if(1>0)
                            {
                              band_j=bandMag[singleBandIndex];
                            }
                            else
                            {*/
                            //  band_j=bandMag[j];
                            //}
                            //Serial.println(band_j);
                            lvl=round((1.0-alpha_fft)*double(constrain(map(scaling*bandMag[j]*255.0,0,255,0,kMatrixHeight),0,kMatrixHeight))+alpha_fft*double(lvl));
                            //Serial.println(lvl);
                            for(uint16_t i=0; i<kMatrixHeight; i++)
                            {
    
    
                                    uint16_t k=XY(j,i);
                                    if(i<lvl)
                                    {
                                            if(i<26)
                                            {
                                                    leds[k].r=brightness;
                                                    leds[k].g=brightness-6;
                                                    leds[k].b=brightness-3;
                                            }
                                            else
                                            {
                                                    leds[k].r=0;
                                                    leds[k].g=0;
                                                    leds[k].b=constrain(brightness+10,0,255);
                                            }
                                    }
                                    else
                                    {
                                            leds[k].r= 0;
                                            leds[k].g= 0;
                                            leds[k].b= 0;
                                    }
    
    
                            }
                    }
                    FastLED.show(); //Outputs LEDs
    
    
                    #if DEBUG_FFT_MAG >0
                    Serial.println(F("Computed magnitudes:"));
                    PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
                    #endif
                    #if DEBUG_TIMING > 0
                    t_1=micros()-t0_1;
                    t0_1=micros();
                    #endif
                    #if DEBUG_TIMING > 0
                    Serial.print(F("ADC "));
                    Serial.print(1000000.0/(float)t);
                    Serial.print(F(" FFT "));
                    Serial.println(1000000.0/(float)t_1);
                    #endif
            }
            #if DEBUG_LDR > 0
            Serial.println(brightness);
            #endif
    }
    
    
    void PrintVector(double *vData, uint16_t bufferSize, uint8_t scaleType)
    {
            for (uint16_t i = 0; i < bufferSize; i++)
            {
                    double abscissa;
                    /* Print abscissa value */
                    switch (scaleType)
                    {
                    case SCL_INDEX:
                            abscissa = (i * 1.0);
                            break;
                    case SCL_TIME:
                            abscissa = ((i * 1.0) / samplingFrequency);
                            break;
                    case SCL_FREQUENCY:
                            abscissa = ((i * 1.0 * samplingFrequency) / samples);
                            break;
                    }
                    Serial.print(abscissa, 4);
                    if(scaleType==SCL_FREQUENCY)
                            Serial.print(F("Hz "));
    
    
                    Serial.println(vData[i], 4);
            }
            Serial.println();
    }
    
    
    
    
    void PrintBand(double *vData, uint8_t scaleType,uint16_t index)
    {
            double abscissa;
            /* Print abscissa value */
            switch (scaleType)
            {
            case SCL_INDEX:
                    abscissa = (index * 1.0);
                    break;
            case SCL_TIME:
                    abscissa = ((index * 1.0) / samplingFrequency);
                    break;
            case SCL_FREQUENCY:
                    abscissa = ((index * 1.0 * samplingFrequency) / samples);
                    break;
            }
    
    
            Serial.print(abscissa, 4);
            if(scaleType==SCL_FREQUENCY)
                    Serial.print(F("Hz "));
    
    
            Serial.println(vData[index], 4);
    }
    
    
    uint16_t XY( uint8_t x, uint8_t y)
    {
            uint16_t i;
            if( kMatrixSerpentineLayout == false) {
                    i = (y * kMatrixWidth) + x;
            }
            else {
                    if( y & 0x01) {
                            // Odd rows run backwards
                            uint8_t reverseX = (kMatrixWidth - 1) - x;
                            i = (y * kMatrixWidth) + reverseX;
                    } else {
                            // Even rows run forwards
                            i = (y * kMatrixWidth) + x;
                    }
            }
            return i;
    }
    
    
    void calculateBands(double*freqBand,double* magBand,double* freqV,double* magV,uint16_t n_bands,uint16_t n_freq)
    {
            static double minbands[numbands];
            static double maxbands[numbands];
            for(uint16_t i=0; i<(n_bands); i++)
            {
                    double min_bound=freqBand[i];
                    double max_bound=freqBand[i+1];
                    double partial=0.0,denominator=0.0;
                    for(uint16_t j=0; j<(n_freq); j++)
                    {
                            if((freqV[j]>=min_bound)&&(freqV[j+1]<max_bound))
                            {
                                    partial+=(freqV[j+1]-freqV[j])*(magV[j+1]+magV[j])/2.0;//Trapezoid integration
                                    denominator+=freqV[j+1]-freqV[j];
                            }
                    }
                    partial/=denominator;
                    if(partial<minbands[i])
                    {
                            minbands[i]=partial;
                    }
                    if(partial>maxbands[i])
                    {
                            maxbands[i]=partial;
                    }
                    //Base 1 magnitude
                    magBand[i]=(partial-minscaleBands[i])/(maxscaleBands[i]-minscaleBands[i]);
                    if(magBand[i]<0.0)
                    {
                            magBand[i]=0.0;
                    }
                    /*
                       char mystring[100];
                       sprintf(mystring,"Min: %g,max: %g,mag: %g \n",min_bound,max_bound,magBand[i]);
                       Serial.print(mystring);
                     */
    
    
                    /*char mystring[100];
                       sprintf(mystring,"%i f: %g Min: %g,max: %g,mag: %g \n",i,min_bound,minbands[i],maxbands[i],magBand[i]);
                       Serial.print(mystring);*/
    
    
                    //  Serial.println(magBand[i]);
            }
    }
    void testMatrix()
    {
            for(uint16_t j=0; j<(kMatrixWidth*kMatrixHeight); j++)
            {
                    leds[j].r=0;
                    leds[j].g=0;
                    leds[j].b=0;
            }
            for(uint16_t j=0; j<kMatrixWidth; j++)
            {
                    //  Serial.print(bandMag[j]);
                    //  Serial.print(" , ");
                    for(int l=0; l<32; l++)
                    {
                            //Serial.println(lvl);
                            for(uint16_t i=0; i<kMatrixHeight; i++)
                            {
    
    
                                    uint16_t k=XY(j,i);
                                    if(i<=l)
                                    {
                                            leds[k].r=31;
                                            leds[k].g=31;
                                            leds[k].b=31;
                                    }
                                    else
                                    {
                                            leds[k].r= 0;
                                            leds[k].g= 0;
                                            leds[k].b= 0;
                                    }
    
    
                            }
                            FastLED.show();
                            delay(100);
                    }
            }
    
    
    }

    Now, here's the catch.
    There's a test variable at line 55 deaclared as "double trololo;" (for obvious purposes); after I uncomment this line and compile the code again the sketch stops running as previously, although no changes have been performed.
    I've tried with any type of variable, making them volatile, static inside the loop function and constants as well with the same results. I have also tried changing the optimize setting and CPU frequency in the tools tab without any effects as well.
    Can anyone give a hint on what is going on? This issue is preventing me for further expanding the program. There also seems to be enough RAM left for the program to run.
    Thanks in advance to everyone,
    cheers!

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,108
    Quote Originally Posted by gertorro View Post
    Can anyone give a hint on what is going on?
    Usually these sorts of mysterious problems are due to a buffer overflow. Adding even an unused variable tends to cause the overwriting to corrupt something else (which is less critical and doesn't make your program crash).

    As a first easy step, try making each of those arrays just before the "trololo" variable much larger. If you find allocation 20X the size for any particular array magically cures this mysterious problem, then start looking all whatever code writes to that array.

  3. #3
    Junior Member
    Join Date
    Feb 2016
    Posts
    4
    Hi Paul, thanks for the hint, I was accessing element [length] of an array inadvertly.
    Thank you for pointing out that this was common behavior, consider it solved!

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,942
    Just a quick scan of the code, until this showed something like this could be going off the end of an array where for ( j=0 to limit (n_freq) ) - on the last valid entry it is referring and writing to j+1:
    Code:
                    for(uint16_t j=0; j<(n_freq); j++)
                    {
                            if((freqV[j]>=min_bound)&&(freqV[j+1]<max_bound))
                            {
                                    partial+=(freqV[j+1]-freqV[j])*(magV[j+1]+magV[j])/2.0;//Trapezoid integration
                                    denominator+=freqV[j+1]-freqV[j];
                            }
                    }
    That code is not valid on the last element

Posting Permissions

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