FHT audio spectrum analyzer and fastled Color Palette(help)

Yup! It's me asking question again
I've follow a instruction to make spectrum analyzer using FHT arduino library and it worked just fine
and of course Color Palette worked with my setup too
I want to put them together and use serial command just to switch between 2 modes (spectrum and color palette effects)

Commands are received by the board and with mode 1, color palette just freeze at 1st effect (rainbow)
and with mode 2, spectrum analyzer worked as normal
but I was unable to use terminal command after switch to mode 2, just stuck at mode 2 forever

I think there was a problem with interrupt but I dont know how to fix it
please view my code and help me out
thanks

122.ino (10.1 KB)

Post the code properly in code tags. Most mobile devices can’t use a .ino file.

As a pure guess then:-
You need to write your led code as a state machine so you can interleave access to the FFT and access to the LED patterns.

yup, that's what I want here is my code.

/*
Written by FischiMc and SupaStefe

This sketch uses a 10x10 RGB LED-Matrix as a spectrum analyzer
It uses a FTT Library to analyze an audio signal connected to the
pin A7 of an Arduino nano. Everytime a column gets higher than
10 pixels the color of each column changes.
*/

#define LOG_OUT 0         //set output of FFT library to linear not logarithmical
#define LIN_OUT 1
#define FHT_N 256     
#define UPDATES_PER_SECOND 100//set to 256 point fft

#include <FHT.h>
#include <FastLED.h>      //include the FastLED Library
#include <math.h>         //include library for mathematic funcions
#define DATA_PIN 6        //DATA PIN WHERE YOUR LEDS ARE CONNECTED
#define NUM_LEDS 42      //amount of LEDs in your matrix
CRGB leds[NUM_LEDS];
float faktoren[7] = {1.75, 1.55, 1.45, 1.25, 1.45, 1.55,1.75};       //factors to increase the height of each column
unsigned char hs[7] = {8, 8, 8, 8,8,8,8};                        //height of each column
float hue;       
int previousMillis;
int paletteCounter;
int previousMillis2= 0;
int currentMillis2;

int currentMillis;
CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;


void setBalken(unsigned char column, unsigned char height){                   //calculation of the height of each column
    unsigned char h = (unsigned char)map(height, 0, 255, 0, 7);
    h = (unsigned char)(h * faktoren[column]);
    if (h < hs[column]){
        hs[column]--;
    }
    else if (h > hs[column]){
        hs[column] = h;
    }
   if (height > 250){
      hue+=2;                     //CHANGE THIS VALUE IF YOU WANT THE DIFFERENCE BETWEEN THE COLORS TO BE BIGGER
      if(hue > 25) hue=0;
   }

    for(unsigned char y = 0; y < 8; y++){                          //set colors of pixels according to column and hue
       if(hs[column] > y){ 
        leds[y+(column*6)] = CHSV((hue*10)+(column*6), 255, 180);
        
        
       } else {
        leds[y+(column*6)] = CRGB::Black;
       }
    }
}

unsigned char grenzen[8] = {0,3,5,7,9,11,13,16};          //borders of the frequency areas

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB> (leds, NUM_LEDS);
  Serial.begin(115200);                                             //use the serial port
                                                //turn off timer0 for lower jitter
  ADCSRA = 0xe5;                                                    //set the adc to free running mode
  ADMUX = 0b01000111;                                               //use pin A7
  DIDR0 = 0x01;                                                     //turn off the digital input for 
  analogReference(EXTERNAL);                                        //set aref to external
paletteCounter=1;
currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
}
  
void loop() {
  
 
  paletteCounter = Serial.parseInt();
           if (paletteCounter==1){
  Serial.print("ZoE");
 
currentMillis2 = millis();
   if (currentMillis2 - previousMillis2 >=10) {
    
    ChangePalettePeriodically();


    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */

    FillLEDsFromPaletteColors( startIndex);
    // check if "interval" time has passed (1000 milliseconds)


    FastLED.show();
    previousMillis2 = millis();

    


  }
 }
 if (paletteCounter==2){
  while(1) {                                                        //reduces jitter
    cli();                                                          //UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 256 ; i+=1) {                            //save 256 samples
      while(!(ADCSRA & 0x10));                                      //wait for adc to be ready
      ADCSRA = 0xf5;                                                //restart adc
      byte m = ADCL;                                                //fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m;                                         //form into an int
      k -= 0x0200;                                                  //form into a signed int
      k <<= 6;                                                      //form into a 16b signed int
      fht_input[i] = k;                                             //put real data into even bins
    }

    fht_window();                                                   // window the data for better frequency response
    fht_reorder();                                                  // reorder the data before doing the fft
    fht_run();                                                      // process the data in the fft
    fht_mag_lin();                                                  // take the output of the fft
    sei();

    fht_lin_out[0] = 0;
    fht_lin_out[1] = 0;

    for(unsigned char i = 0; i <= 6; i++){
      unsigned char maxW = 0;
        for(unsigned char x = grenzen[i]; x < grenzen[i+1];x++){
 
           if((unsigned char)fht_lin_out[x] > maxW){
            maxW = (unsigned char)fht_lin_out[x];
           }
        }

currentMillis=millis;
if (currentMillis-previousMillis>=1){
  hue++;
  previousMillis=millis;
  
}

      setBalken(i, maxW);
      Serial.print(maxW);
      Serial.print(" ");
      Serial.println("");
 
    FastLED.show();
    
    }
    
  }
}
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
    uint8_t brightness = 255;
    
    for( int i = 0; i < NUM_LEDS; i++) {
        leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
        colorIndex += 3;
    }
}

Hi kaitoukid93, can you procvide a link to the instruction to make spectrum analyzer using FHT arduino library? Thanks

lesept:
Hi kaitoukid93, can you procvide a link to the instruction to make spectrum analyzer using FHT arduino library? Thanks

yeah
here my friend

Thanks.
I was thinking of making an Arduino-based oscilloscope, I can add spectrum analyser then.

It uses a FTT Library to analyze an audio signal

What FFT libiary, there are a few and it is non of the ones I have.

Oh no not another crappy instructiables project. These things are written by idiots.
I did put a comment on this one 4 months ago telling him of some of his mistakes but these have been ignored.

All time variables must be an unsigned long and not the int type this clod uses.

I think there was a problem with interrupt but I dont know how to fix it

No problem with the interrupt it is the code.
Read up on how the serial input works.

Grumpy_Mike:
What FFT libiary, there are a few and it is non of the ones I have.

Oh no not another crappy instructiables project. These things are written by idiots.
I did put a comment on this one 4 months ago telling him of some of his mistakes but these have been ignored.

All time variables must be an unsigned long and not the int type this clod uses.
No problem with the interrupt it is the code.
Read up on how the serial input works.

Yah that project is full of mistake. I corrected it and put some comments, and use Open music lab's FHT library instead
the problem is when I tried to input character from serial monitor, ADC and FHT keeps running and would not take any command to switch back to Fastled patterns , when I tried to put Serial.parseInt() inside the while(1) loop, (right after "sei();"), I was able to input command from serial but after input, both Audio visualizer and Fastled pattern stop working

OK I dont know how but after tried everything I can, finally it works as I expected

first thing I do: remove the While(1) loop

after that, check serial every cycle and if (paletteCounter!=0) then: do palette paterns

else: do FHT setup and fastled visualizer, at the end of FHT code, reset paletteCounter=0

/*
Written by FischiMc and SupaStefe

This sketch uses a 10x10 RGB LED-Matrix as a spectrum analyzer
It uses a FTT Library to analyze an audio signal connected to the
pin A7 of an Arduino nano. Everytime a column gets higher than
10 pixels the color of each column changes.
*/

#define LOG_OUT 0         //set output of FFT library to linear not logarithmical
#define LIN_OUT 1
#define FHT_N 256     
#define UPDATES_PER_SECOND 100//set to 256 point fft

#include <FHT.h>
#include <FastLED.h>      //include the FastLED Library
#include <math.h>         //include library for mathematic funcions
#define DATA_PIN 6        //DATA PIN WHERE YOUR LEDS ARE CONNECTED
#define NUM_LEDS 42      //amount of LEDs in your matrix
CRGB leds[NUM_LEDS];
float faktoren[7] = {1.75, 1.55, 1.45, 1.25, 1.45, 1.55,1.75};       //factors to increase the height of each column
unsigned char hs[7] = {8, 8, 8, 8,8,8,8};                        //height of each column
float hue;       
int previousMillis;
int paletteCounter;
int previousMillis2= 0;
int currentMillis2;

int currentMillis;
CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;


void setBalken(unsigned char column, unsigned char height){                   //calculation of the height of each column
    unsigned char h = (unsigned char)map(height, 0, 255, 0, 7);
    h = (unsigned char)(h * faktoren[column]);
    if (h < hs[column]){
        hs[column]--;
    }
    else if (h > hs[column]){
        hs[column] = h;
    }
   if (height > 250){
      hue+=2;                     //CHANGE THIS VALUE IF YOU WANT THE DIFFERENCE BETWEEN THE COLORS TO BE BIGGER
      if(hue > 25) hue=0;
   }

    for(unsigned char y = 0; y < 8; y++){                          //set colors of pixels according to column and hue
       if(hs[column] > y){ 
        leds[y+(column*6)] = CHSV((hue*10)+(column*6), 255, 180);
        
        
       } else {
        leds[y+(column*6)] = CRGB::Black;
       }
    }
}

unsigned char grenzen[8] = {0,3,5,7,9,11,13,16};          //borders of the frequency areas

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB> (leds, NUM_LEDS);
  Serial.begin(115200);                                             //use the serial port
                                                //turn off timer0 for lower jitter
  ADCSRA = 0xe5;                                                    //set the adc to free running mode
  ADMUX = 0b01000111;                                               //use pin A7
  DIDR0 = 0x01;                                                     //turn off the digital input for 
  analogReference(EXTERNAL);                                        //set aref to external
paletteCounter=1;
currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
}
void serialInterrupt()
{
 detachInterrupt(0);
 interrupts();
 
  paletteCounter = Serial.parseInt();


 Serial.print("Zoe");

 attachInterrupt(0, serialInterrupt, CHANGE);
}
  
void loop() {
  
 if(Serial.read() >= 0){
  paletteCounter = Serial.parseInt();
  delay(100);
 }
 
 
           if (paletteCounter!=0){
  
 
currentMillis2 = millis();
   if (currentMillis2 - previousMillis2 >=10) {
    
    ChangePalettePeriodically();


    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */

    FillLEDsFromPaletteColors( startIndex);
    // check if "interval" time has passed (1000 milliseconds)


    FastLED.show();
    previousMillis2 = millis();

    


  }
 }
 
 else {
   
                                                     //reduces jitter
    cli();                                                          //UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 256 ; i+=1) {                            //save 256 samples
      while(!(ADCSRA & 0x10));                                      //wait for adc to be ready
      ADCSRA = 0xf5;                                                //restart adc
      byte m = ADCL;                                                //fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m;                                         //form into an int
      k -= 0x0200;                                                  //form into a signed int
      k <<= 6;                                                      //form into a 16b signed int
      fht_input[i] = k;                                             //put real data into even bins
    }

    fht_window();                                                   // window the data for better frequency response
    fht_reorder();                                                  // reorder the data before doing the fft
    fht_run();                                                      // process the data in the fft
    fht_mag_lin();                                                  // take the output of the fft
    sei();


    fht_lin_out[0] = 0;
    fht_lin_out[1] = 0;

    for(unsigned char i = 0; i <= 6; i++){
      unsigned char maxW = 0;
        for(unsigned char x = grenzen[i]; x < grenzen[i+1];x++){
 
           if((unsigned char)fht_lin_out[x] > maxW){
            maxW = (unsigned char)fht_lin_out[x];
           }
        }

currentMillis=millis;
if (currentMillis-previousMillis>=1){
  hue++;
  previousMillis=millis;
  
}

      setBalken(i, maxW);
      Serial.print(maxW);
      Serial.print(" ");
      Serial.println("");
 
    FastLED.show();
    paletteCounter==0;
    
    }
    
    
  }

}

there's 1 more weird thing: If I input value in range (0-10), mode visualizer active, I have to input value greater than 10 if I want pallet pattern ( if (paletteCounter!=0) then: do palette paterns?????)

Still got this:-

int previousMillis;
int paletteCounter;
int previousMillis2= 0;
int currentMillis2;

int currentMillis;

replace with

unsigned long previousMillis;
int paletteCounter;
unsigned long previousMillis2= 0;
unsigned long currentMillis2;
unsigned long currentMillis;

Or it can stop working correctly after a short time.

Your serialInterrupt function looks wrong, use serialEvent, like it tells you here.

Grumpy
I've been use that with another code and a week passed. still functioning, I will replace all with your suggestion
thanks
I've edit the code and now perfectly working, I think the "paletteCounter" value have been messed up somehow
I separate it as below and now I can chose different pattern with terminal number commands
about that interrupt, It was not the problem so I dont use it anymore
I also add EEPROM to remember which pattern or mode was playing last time before unpluge
thanks again Grumpy

#include <EEPROM.h>




/*
Written by FischiMc and SupaStefe

This sketch uses a 10x10 RGB LED-Matrix as a spectrum analyzer
It uses a FTT Library to analyze an audio signal connected to the
pin A7 of an Arduino nano. Everytime a column gets higher than
10 pixels the color of each column changes.
*/

#define LOG_OUT 0         //set output of FFT library to linear not logarithmical
#define LIN_OUT 1
#define FHT_N 256     
#define UPDATES_PER_SECOND 100//set to 256 point fft

#include <FHT.h>
#include <FastLED.h>      //include the FastLED Library
#include <math.h>         //include library for mathematic funcions
#define DATA_PIN 6        //DATA PIN WHERE YOUR LEDS ARE CONNECTED
#define NUM_LEDS 42      //amount of LEDs in your matrix
CRGB leds[NUM_LEDS];
float faktoren[7] = {1.75, 1.55, 1.45, 1.25, 1.45, 1.55,1.75};       //factors to increase the height of each column
unsigned char hs[7] = {8, 8, 8, 8,8,8,8};                        //height of each column
float hue;       
int previousMillis;
int paletteCounter;
int paletteCounter2;
int previousMillis2= 0;
int currentMillis2;
int eepaddress = 0;

int currentMillis;
CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;


void setBalken(unsigned char column, unsigned char height){                   //calculation of the height of each column
    unsigned char h = (unsigned char)map(height, 0, 255, 0, 7);
    h = (unsigned char)(h * faktoren[column]);
    if (h < hs[column]){
        hs[column]--;
    }
    else if (h > hs[column]){
        hs[column] = h;
    }
   if (height > 250){
      hue+=2;                     //CHANGE THIS VALUE IF YOU WANT THE DIFFERENCE BETWEEN THE COLORS TO BE BIGGER
      if(hue > 25) hue=0;
   }

    for(unsigned char y = 0; y < 8; y++){                          //set colors of pixels according to column and hue
       if(hs[column] > y){ 
        leds[y+(column*6)] = CHSV((hue*10)+(column*6), 255, 180);
        
        
       } else {
        leds[y+(column*6)] = CRGB::Black;
       }
    }
}

unsigned char grenzen[8] = {0,3,5,7,9,11,13,16};          //borders of the frequency areas

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB> (leds, NUM_LEDS);
  Serial.begin(115200);                                             //use the serial port
                                                //turn off timer0 for lower jitter
  ADCSRA = 0xe5;                                                    //set the adc to free running mode
  ADMUX = 0b01000111;                                               //use pin A7
  DIDR0 = 0x01;                                                     //turn off the digital input for 
  analogReference(EXTERNAL);                                        //set aref to external
currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
    paletteCounter =EEPROM.read(eepaddress);
  paletteCounter2=EEPROM.read(eepaddress);
}

  
void loop() {
  
 if(Serial.read() >= 0){
  paletteCounter = Serial.parseInt();
  delay(100);
  
 }
 
 
           if (paletteCounter==22){

  
  
 currentPalette =adt_velocity_gp;
    currentBlending = LINEARBLEND;
    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */
    FillLEDsFromPaletteColors( startIndex);
    // check if "interval" time has passed (1000 milliseconds)

    FastLED.show();
    FastLED.delay(10);
    
 }
 

 if (paletteCounter==24){
currentMillis2 = millis();
   if (currentMillis2 - previousMillis2 >=10) {
  
    currentPalette = RainbowStripeColors_p;
    currentBlending = LINEARBLEND;
    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */
    FillLEDsFromPaletteColors( startIndex);
    // check if "interval" time has passed (1000 milliseconds)

    FastLED.show();
    previousMillis2 = millis(); }
 }
 if (paletteCounter==0)
   {
                                                     //reduces jitter
    cli();                                                          //UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 256 ; i+=1) {                            //save 256 samples
      while(!(ADCSRA & 0x10));                                      //wait for adc to be ready
      ADCSRA = 0xf5;                                                //restart adc
      byte m = ADCL;                                                //fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m;                                         //form into an int
      k -= 0x0200;                                                  //form into a signed int
      k <<= 6;                                                      //form into a 16b signed int
      fht_input[i] = k;                                             //put real data into even bins
    }

    fht_window();                                                   // window the data for better frequency response
    fht_reorder();                                                  // reorder the data before doing the fft
    fht_run();                                                      // process the data in the fft
    fht_mag_lin();                                                  // take the output of the fft
    sei();


    fht_lin_out[0] = 0;
    fht_lin_out[1] = 0;

    for(unsigned char i = 0; i <= 6; i++){
      unsigned char maxW = 0;
        for(unsigned char x = grenzen[i]; x < grenzen[i+1];x++){
 
           if((unsigned char)fht_lin_out[x] > maxW){
            maxW = (unsigned char)fht_lin_out[x];
           }
        }

currentMillis=millis;
if (currentMillis-previousMillis>=1){
  hue++;
  previousMillis=millis;
  
}

      setBalken(i, maxW);
      Serial.print(maxW);
      Serial.print(" ");
      Serial.println("");
 
    FastLED.show();
   
    
    }
    
    
  }
 if (paletteCounter!= paletteCounter2 ){
      EEPROM.write(eepaddress,paletteCounter);
      paletteCounter2=paletteCounter;
      }
}
    


void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
    uint8_t brightness = 255;
    
    for( int i = 0; i < NUM_LEDS; i++) {
        leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
        colorIndex += 3;
    }
}

.