FFT, SNR und LED Matrix

Liebes Forum, :slight_smile:

Ich versuche schon seit einer Weile eine FFT von einem Stereo Line Eingang auf einer RGB LED Matrix (Adafruit 16x32) anzzeugen.

Dabei gibt es 2 Probleme:

  1. Es gibt einen konstanten tieffrequenten Anteil, den ich nicht aus dem Signal bekomme.

  2. Außerdem zeigt meine Matrix nicht die volle Amplitude des Signals an.

Das Bild FFT1.jpg zeigt die Matrix ohne Input. FFT2.jpg zeigt die Matrix mit einem 10 kHZ Sinus bei voller Lautstärke. Es sollte eigentlich in 8b (max 256) ausgegeben werden
Ich habe auch meinen Schaltplan hinzugefügt.

In der .txt Datei ist info zur FFT Bibliothek.

Code auf dem Arduino:

/*
  fft_adc.pde
  guest openmusiclabs.com 8.18.12
  example sketch for testing the fft library.
  it takes in data on ADC0 (Analog0) and processes them
  with the fft. the data is sent out over the serial
  port at 115.2kb.  there is a pure data patch for
  visualizing the data.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 64 // set to 64 point fft

#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library
#include <FFT.h> // include the library

#define CLK 8  // MUST be on PORTB!
#define LAT A3
#define OE  9
#define A   A4
#define B   A1
#define C   A2

int freq_array[36];

RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);

void setup() {
  matrix.begin();
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}



void lightcolumns(int rownum, int amplitude)
{
  if(amplitude>15)  // <-O-> set the threshold for the band to turn red
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(7, 0, 0));
  }
  for(int y = amplitude; y <16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  }
  
  else if(amplitude>13) // <-O-> set the threshold for the band to turn yellow
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(4, 4, 0));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  }
  
  else if(amplitude>9) // <-O-> set the threshold for the band to turn green
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(0, 5, 0));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  } 
  
  else
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 7));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  } 
}

void loop() {
  while (1) { // reduces jitter
   
    for (int i = 0 ; i < 128 ; i += 2) { // save 64 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
      fft_input[i] = k; // put real data into even bins
      fft_input[i + 1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft




        for (int j = 0; j < 32; j++) {

    if (fft_log_out[j] < 2000 && fft_log_out[j] > 255) {
      freq_array[j] = 16;
    }
    else {
      if (fft_log_out[j] <= 255 && fft_log_out[j] > 240) {
        freq_array[j] = 15;
      }
      else {
        if (fft_log_out[j] <= 240 && fft_log_out[j] > 225) {
          freq_array[j] = 14;
        }
        else {
          if (fft_log_out[j] <= 225 && fft_log_out[j] > 210) {
            freq_array[j] = 13;
          }
          else {
            if (fft_log_out[j] <= 210 && fft_log_out[j] > 195) {
              freq_array[j] = 12;
            }
            else {
              if (fft_log_out[j] <= 195 && fft_log_out[j] > 180) {
                freq_array[j] = 11;
              }
              else {
                if (fft_log_out[j] <= 180 && fft_log_out[j] > 165 ) {
                  freq_array[j] = 10;
                }
                else {
                  if (fft_log_out[j] <= 165 && fft_log_out[j] > 150) {
                    freq_array[j] = 9;
                  }
                  else {
                    if (fft_log_out[j] <= 150 && fft_log_out[j] > 135){
                      freq_array[j] = 8;
                    }
                    else {
                      if (fft_log_out[j] <= 135 && fft_log_out[j] > 120) {
                        freq_array[j] = 7;
                      }
                      else {
                        if (fft_log_out[j] <= 120 && fft_log_out[j] > 105) {
                          freq_array[j] = 6;
                        }
                        else {
                          if (fft_log_out[j] <= 105 && fft_log_out[j] > 90) {
                            freq_array[j] = 5;
                          }
                          else {
                            if (fft_log_out[j] <= 90 && fft_log_out[j] > 75) {
                              freq_array[j] = 4;
                            }
                            else {
                              if (fft_log_out[j] <= 75 && fft_log_out[j] > 60) {
                                freq_array[j] = 3;
                              }
                              else {
                                if (fft_log_out[j] <= 60 && fft_log_out[j] > 45) {
                                  freq_array[j] = 2;
                                }
                                else {
                                  if (fft_log_out[j] <= 45 && fft_log_out[j] > 15) {
                                    freq_array[j] = 1;
                                  }
                                  else {
                                    if (fft_log_out[j] <= 15 && fft_log_out[j] >= 0) {
                                      freq_array[j] = 0;
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }






      lightcolumns(31, freq_array[0]);
      lightcolumns(30, freq_array[1]);
      lightcolumns(29, freq_array[2]);
      lightcolumns(28, freq_array[3]);
      lightcolumns(27, freq_array[4]);
      lightcolumns(26, freq_array[5]);
      lightcolumns(25, freq_array[6]);
      lightcolumns(24, freq_array[7]);
      lightcolumns(23, freq_array[8]);
      lightcolumns(22, freq_array[9]);
      lightcolumns(21, freq_array[10]);
      lightcolumns(20, freq_array[11]);
      lightcolumns(19, freq_array[12]);
      lightcolumns(18, freq_array[13]);
      lightcolumns(17, freq_array[14]);
      lightcolumns(16, freq_array[15]);
      lightcolumns(15, freq_array[16]);
      lightcolumns(14, freq_array[17]);
      lightcolumns(13, freq_array[18]);
      lightcolumns(12, freq_array[19]);
      lightcolumns(11, freq_array[20]);
      lightcolumns(10, freq_array[21]);
      lightcolumns(9, freq_array[22]);
      lightcolumns(8, freq_array[23]);
      lightcolumns(7, freq_array[24]);
      lightcolumns(6, freq_array[25]);
      lightcolumns(5, freq_array[26]);
      lightcolumns(4, freq_array[27]);
      lightcolumns(3, freq_array[28]);
      lightcolumns(2, freq_array[29]);
      lightcolumns(1, freq_array[30]);
      lightcolumns(0, freq_array[31]);
      
     matrix.swapBuffers(false);

  }

}

Danke!
Grüße, Flitschi

FFT1.JPG

FFT2.JPG

fft_read_me.txt (12.7 KB)

Du hast mein volles Mitgefühl!

Sorry, hatte zu früh gepostet :smiley:
bin noch ein newbie hier...

Das sieht aus, wie ein Gleichspannungsanteil.

Oder 50 Hz Netzbrummen, möglicherweise durch falsche Schirmung oder Brummschleife in der Masse.

Gut möglich, dass das ein Gleichspannungsanteil oder ein Brummen ist aber wo ist der Fehler und wie kann ich diesen beheben. Außerdem wurde mein 2. Problem noch nicht besprochen.
Ist der Arduino für so etwas vllt auch nicht unbedingt geeignet?

  k -= 0x0200; // form into a signed int

Wenn der Wert nicht stimmt, bekommst du einen Gleichspannungsanteil.

Hey combie,
Ich bin mir nun ziemlich sicher, dass der Gleichspannungsanteil nicht von einem Netzbrummen kommt, da mir die FFT auch ohne Matrix und Audiocircuit verbunden (also nur Arduino via USB verbunden, Ergebnisse werden mit Serial.print() ausgegeben) ähliche Werte liefert.

Könntest du mir deine Idee erläutern? Da bei einer 256: k-= 0x0200; Müsste es für eine 64 punkt FFT 0x80 sein?

Da bei einer 256: k-= 0x0200; Müsste es für eine 64 punkt FFT 0x80 sein?

Nee, so nicht gemeint.

Könntest du mir deine Idee erläutern?

Da gibts ein kleines Problem.
Ich kenne die Lib nicht, nie genutzt.
Darum: Dünnes Eis.

Aber, ich versuche es mal:
Es dreht sich um die (mess)Werte, welche in das Array eingetragen werden.
Wenn diese Stützpunkte im Mittel ungleich Null sind, dann hast du einen Gleichspannungsanteil in den Daten. Und damit einen Ausschlag bei der niedrigsten Frequenz.
100%ig wird man das nicht hin bekommen, aber man kann sich Mühe geben, dass die Daten schön gleiche mäßig um Null schwanken