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:
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!
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!