Teensy 4.1 sketch freezes after adding any extra variable

Status
Not open for further replies.

gertorro

New member
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!
 
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.
 
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!
 
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; [B]j<(n_freq)[/B]; j++)
                {
                        if((freqV[j]>=min_bound)&&(freqV[[B][U]j+1[/U][/B]]<max_bound))
                        {
                                partial+=(freqV[[B][U]j+1[/U][/B]]-freqV[j])*(magV[[B][U]j+1[/U][/B]]+magV[j])/2.0;//Trapezoid integration
                                denominator+=freqV[[B][U]j+1[/U][/B]]-freqV[j];
                        }
                }
That code is not valid on the last element
 
Status
Not open for further replies.
Back
Top