Benutzer-Werkzeuge

Webseiten-Werkzeuge


arduino:spektrumanalysator:programmversion_0.4

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
arduino:spektrumanalysator:programmversion_0.4 [10.09.2017 16:00] Frickelpietarduino:spektrumanalysator:programmversion_0.4 [18.05.2023 12:34] (aktuell) – Externe Bearbeitung 127.0.0.1
Zeile 14: Zeile 14:
   * https://www.techfak.uni-bielefeld.de/~walter/lehre/dm2/vis/Farbmetrik.html   * https://www.techfak.uni-bielefeld.de/~walter/lehre/dm2/vis/Farbmetrik.html
   * Hexadezimale in dezimale Werte umrechnen: http://www.numberplanet.com/number/40/index.html   * Hexadezimale in dezimale Werte umrechnen: http://www.numberplanet.com/number/40/index.html
 +
 +<code>
 +// Spektrumanalysator
 +// Für einen NeoPixel-Streifen mit 72 NeoPixeln
 +
 +//Bibliotheken
 +#include <Audio.h>                                        // Audio
 +#include <Wire.h>
 +#include <SPI.h>
 +#include <SD.h>
 +#include <SerialFlash.h>
 +#include <Encoder.h>                                      // Encoder
 +#include <Adafruit_NeoPixel.h>                            // NeoPixel
 +
 +// Pins
 +#define encoderChannelA  24                               // Kanal A
 +#define encoderChannelB  25                               // Kanal B
 +#define NEOPIXELPIN      33                               // NeoPixel-Streifen
 +
 +// Dreh-Encoder
 +Encoder myEnc(encoderChannelA, encoderChannelB);
 +
 +long newPosition = 0;
 +long oldPosition;
 +
 +// Menü Spektrumanalysator
 +byte displayMode = 0;                                     // Verschiedene Anzeigemodi
 +
 +// Automatische Eingangspegelregelung
 +boolean autoInputLevelControl = true;                     // Aktiviert und deaktiviert die automatische Eingangspegelregelung
 +float peakMaxDecrease = 0.001;                            // Wert, um den der Maximalpeak kontinuierlich verringert wird. (Kann später im Menü angepasst werden.)
 +
 +float level_L[36];                                        // Array für die Daten der FFT (linker Kanal)
 +float level_R[36];                                        // Array für die Daten der FFT (rechter Kanal)
 +float leftPeak;                                           // Pegel linker Kanal. Kann Werte zwischen 0.00 und 1.00 annehmen.
 +float rightPeak;                                          // Pegel rechter Kanal. Kann Werte zwischen 0.00 und 1.00 annehmen.
 +float masterPeak;                                         // Pegel des rechten und des linken Kanals. Kann Werte zwischen 0.00 und 1.00 annehmen.
 +float masterPeakMax;                                      // Maximalpegel beider Audiokanäle, von dem schrittweise "peakDecrease" substrahiert wird. Kann Werte zwischen 0.00 und 1.00 annehmen.
 +float peakDecrease = 0.001;
 +float autoGain;                                           // Anhebung des Eingangssignals: Dämpfung zwischen 0.00 bis 1.00, Anhebung ab 1.01
 +
 +// Konfiguriert den NeoPixel-Ring
 +int numPixels = 72;                                             // Anzahl der NeoPixel
 +Adafruit_NeoPixel strip = Adafruit_NeoPixel(numPixels, NEOPIXELPIN, NEO_GRBW + NEO_KHZ800);
 +
 +// Anzeige Spektrumanalysator
 +float n;
 +int i;                                                    // Variable zum zählen
 +byte r = 0;
 +byte g = 0;
 +byte b = 0;
 +byte w = 0;
 +
 +// GUItool: begin automatically generated code
 +AudioInputI2S            i2s1;             //xy=98,272
 +AudioMixer4              mixer_R;          //xy=245,320
 +AudioMixer4              mixer_L;          //xy=247,235
 +AudioAnalyzePeak         peak_R;           //xy=442,293
 +AudioAnalyzeFFT1024      fft1024_R;        //xy=451,327
 +AudioAnalyzePeak         peak_L;           //xy=455,146
 +AudioAnalyzeFFT1024      fft1024_L;        //xy=461,184
 +AudioConnection          patchCord1(i2s1, 0, mixer_L, 0);
 +AudioConnection          patchCord2(i2s1, 1, mixer_R, 0);
 +AudioConnection          patchCord3(mixer_R, peak_R);
 +AudioConnection          patchCord4(mixer_R, fft1024_R);
 +AudioConnection          patchCord5(mixer_L, peak_L);
 +AudioConnection          patchCord6(mixer_L, fft1024_L);
 +AudioControlSGTL5000     sgtl5000_1;        //xy=107,430
 +// GUItool: end automatically generated code
 +
 +// Definiert die Tracking-Variablen für die IF-Abfragen
 +unsigned long previousMillisAutoInputLevelControl = 0;          // Berechnung des maximalen Peaks für die automatische Inputlevel-Regelung
 +
 +// Definiert die Intervalle für die IF-Abfragen in Millisekunden
 +unsigned long intervalAutoInputLevelControl = 100;              // Berechnung des maximalen Peaks für die automatische Inputlevel-Regelung
 +
 +// Taktung Schleifen
 +unsigned long lastMillis = 0;
 +unsigned long duration = 0;
 +
 +
 +void setup() {
 +  Serial.begin(115200);                 
 +    
 +  AudioMemory(22);                                              // Audiospeicher
 +
 +  // enable the audio shield
 +  sgtl5000_1.enable();
 +  sgtl5000_1.muteHeadphone();
 +  sgtl5000_1.muteLineout();
 +  sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN);
 +  sgtl5000_1.lineInLevel(5);
 +  //sgtl5000_1.autoVolumeControl(2, 3, 0, -18, 3, 30);           // (maxGain, response, hardLimit, threshold, attack, decay)
 +  //sgtl5000_1.autoVolumeEnable();
 +  
 +  // Configure the window algorithm to use
 +  fft1024_L.windowFunction(AudioWindowHanning1024);
 +  //myFFT.windowFunction(NULL);
 +
 +  // Initialisiert den NeoPixel-Teststrip
 +  strip.begin();
 +  strip.show();                                                 // Initialize all pixels to 'off'
 +  strip.setBrightness(64);                                      // 1/4 der maximalen Helligkeit
 +  
 +  // Legt den Anzeigemodus fest (provisorisch)
 +  displayMode = 0;
 +
 +  // Schaltet die automatische Inputlevelregelung ein bzw. aus. (Kann später im Menü aktiviert und deaktiviert werden.)
 +  autoInputLevelControl = true;
 +}
 +
 +void loop() {
 +  // Aktuelle Zeit abfragen
 +  unsigned long currentMillis = millis();
 +  
 +  // Encoder
 +  newPosition = myEnc.read();
 +  if (newPosition != oldPosition) {
 +    oldPosition = newPosition;
 +  }
 +  if (newPosition < 0) {
 +    newPosition = 0;
 +  }
 +  if (newPosition >= 120) {
 +    newPosition = 120;
 +  }  
 +
 +  // Gain Control  
 +  if (autoInputLevelControl == false) {                        // Die manuelle Inputlevel-Kontrolle ist nur aktiv, wenn die automatische Inputlevel-Regelung deaktiviert ist
 +    mixer_L.gain(0, (newPosition / 40.0));
 +    mixer_R.gain(0, (newPosition / 40.0));
 +  }
 +
 +  // Fast Fourier Transformation (FFT)
 +  if (fft1024_L.available() && fft1024_R.available()) {        // Wenn die FFT neue Daten berechnet hat, werden für beide Kanäle je 512 FFT Frequenzen ausgelesen und in je 36 Bändern zusammengefasst.
 +    // Zuerst ist der linke Kanal an der Reihe
 +    level_L[35] =  fft1024_L.read(0);
 +    level_L[34] =  fft1024_L.read(1);
 +    level_L[33] =  fft1024_L.read(2);
 +    level_L[32] =  fft1024_L.read(3);
 +    level_L[31] =  fft1024_L.read(4, 5);
 +    level_L[30] =  fft1024_L.read(6, 7);
 +    level_L[29] =  fft1024_L.read(8, 9);
 +    level_L[28] =  fft1024_L.read(10, 11);
 +    level_L[27] =  fft1024_L.read(12, 14);
 +    level_L[26] =  fft1024_L.read(15, 17);
 +    level_L[25] = fft1024_L.read(18, 20);
 +    level_L[24] = fft1024_L.read(21, 24);
 +    level_L[23] = fft1024_L.read(25, 28);
 +    level_L[22] = fft1024_L.read(29, 32);
 +    level_L[21] = fft1024_L.read(33, 37);
 +    level_L[20] = fft1024_L.read(38, 43);
 +    level_L[19] = fft1024_L.read(44, 49);
 +    level_L[18] = fft1024_L.read(50, 56);
 +    level_L[17] = fft1024_L.read(57, 64);
 +    level_L[16] = fft1024_L.read(65, 73);
 +    level_L[15] = fft1024_L.read(74, 83);
 +    level_L[14] = fft1024_L.read(84, 94);
 +    level_L[13] = fft1024_L.read(95, 107);
 +    level_L[12] = fft1024_L.read(108, 121);
 +    level_L[11] = fft1024_L.read(122, 137);
 +    level_L[10] = fft1024_L.read(138, 155);
 +    level_L[9] = fft1024_L.read(156, 175);
 +    level_L[8] = fft1024_L.read(176, 198);
 +    level_L[7] = fft1024_L.read(199, 223);
 +    level_L[6] = fft1024_L.read(224, 251);
 +    level_L[5] = fft1024_L.read(252, 283);
 +    level_L[4] = fft1024_L.read(284, 319);
 +    level_L[3] = fft1024_L.read(320, 359);
 +    level_L[2] = fft1024_L.read(360, 404);
 +    level_L[1] = fft1024_L.read(405, 454);
 +    level_L[0] = fft1024_L.read(455, 511);
 +      
 +    // Und dann der rechte Kanal
 +    level_R[0] =  fft1024_R.read(0);
 +    level_R[1] =  fft1024_R.read(1);
 +    level_R[2] =  fft1024_R.read(2);
 +    level_R[3] =  fft1024_R.read(3);
 +    level_R[4] =  fft1024_R.read(4, 5);
 +    level_R[5] =  fft1024_R.read(6, 7);
 +    level_R[6] =  fft1024_R.read(8, 9);
 +    level_R[7] =  fft1024_R.read(10, 11);
 +    level_R[8] =  fft1024_R.read(12, 14);
 +    level_R[9] =  fft1024_R.read(15, 17);
 +    level_R[10] = fft1024_R.read(18, 20);
 +    level_R[11] = fft1024_R.read(21, 24);
 +    level_R[12] = fft1024_R.read(25, 28);
 +    level_R[13] = fft1024_R.read(29, 32);
 +    level_R[14] = fft1024_R.read(33, 37);
 +    level_R[15] = fft1024_R.read(38, 43);
 +    level_R[16] = fft1024_R.read(44, 49);
 +    level_R[17] = fft1024_R.read(50, 56);
 +    level_R[18] = fft1024_R.read(57, 64);
 +    level_R[19] = fft1024_R.read(65, 73);
 +    level_R[20] = fft1024_R.read(74, 83);
 +    level_R[21] = fft1024_R.read(84, 94);
 +    level_R[22] = fft1024_R.read(95, 107);
 +    level_R[23] = fft1024_R.read(108, 121);
 +    level_R[24] = fft1024_R.read(122, 137);
 +    level_R[25] = fft1024_R.read(138, 155);
 +    level_R[26] = fft1024_R.read(156, 175);
 +    level_R[27] = fft1024_R.read(176, 198);
 +    level_R[28] = fft1024_R.read(199, 223);
 +    level_R[29] = fft1024_R.read(224, 251);
 +    level_R[30] = fft1024_R.read(252, 283);
 +    level_R[31] = fft1024_R.read(284, 319);
 +    level_R[32] = fft1024_R.read(320, 359);
 +    level_R[33] = fft1024_R.read(360, 404);
 +    level_R[34] = fft1024_R.read(405, 454);
 +    level_R[35] = fft1024_R.read(455, 511);
 +
 +    // Anzeigemodi
 +    //Effekt "0"
 +    if (displayMode == 0) { 
 +     
 +      // Anschließend werden Farbwerte für die linke Seite des NeoPixel-Streifens berechnet
 +      for (i=0; i<(numPixels/2); i++) {
 +        n = level_L[i];
 +        if (n >= 0.01) {
 +          // Scale 'heat' down from 0-255 to 0-191
 +          byte t192 = round((n * 2000  /255.0) * 191);
 +      
 +          byte heatramp = t192 & 0x3F; // 0..63
 +          heatramp <<= 2; // scale up to 0..252
 +       
 +          if(t192 > 0x80) {                       // hottest
 +            strip.setPixelColor(i, 255, 255, heatramp, 0);
 +            } 
 +          else if(t192 > 0x40) {             // middle
 +            strip.setPixelColor(i, 255, heatramp, 0, 0);
 +            }
 +          else {                               // coolest
 +            strip.setPixelColor(i, heatramp, 0, 0, 0);
 +          }
 +        }
 +        else {
 +          strip.setPixelColor(i, 0, 0, 0, 0);
 +        }
 +      }
 +
 +      // Dann werden die Farbwerte für die rechte Seite des NeoPixel-Streifens berechnet
 +      for (i=0; i<(numPixels/2); i++) {
 +        n = level_R[i];
 +        if (n >= 0.01) {
 +          // Scale 'heat' down from 0-255 to 0-191
 +          byte t192 = round((n * 2000  /255.0) * 191);
 +      
 +          byte heatramp = t192 & 0x3F; // 0..63
 +          heatramp <<= 2; // scale up to 0..252
 +      
 +          if(t192 > 0x80) {                       // hottest
 +            strip.setPixelColor(i+36, 255, 255, heatramp, 0);
 +            } 
 +          else if(t192 > 0x40) {             // middle
 +            strip.setPixelColor(i+36, 255, heatramp, 0, 0);
 +            }
 +          else {                               // coolest
 +            strip.setPixelColor(i+36, heatramp, 0, 0, 0);
 +          }
 +        }
 +        else {
 +          strip.setPixelColor(i+36, 0, 0, 0, 0);
 +        }
 +      }
 +
 +      // Die Daten werden an den NeoPixel-Streifen geschickt
 +      strip.show();
 +    }
 +
 +
 +    // Automatische Eingangspegelregelung
 +    if (autoInputLevelControl == true) {
 +      // Es werden die Pegel des linken und rechten Audiokanals ausgelesen.
 +      if (peak_L.available() && peak_R.available()) {
 +        leftPeak = peak_L.read();                                       // Der Pegel des linken Kanals wird in die Variable geschrieben.
 +        rightPeak = peak_R.read();                                      // Der Pegel des rechten Kanals wird in die Variable geschrieben.
 +      }
 +      // Für die automatische Eingangspegelregelung wird der lautere der beiden Audiokanäle verwendet.
 +      masterPeak = max(leftPeak, rightPeak);
 + 
 +      // Der Maximalpegel wird gespeichert
 +      if (masterPeak > masterPeakMax) {
 +        masterPeakMax = masterPeak;
 +      }
 +      // Alle 100 Millikekunden wird die Eingangspegelanpassung berechnet
 +      if ((unsigned long)(currentMillis - previousMillisAutoInputLevelControl) >= intervalAutoInputLevelControl) {
 +        // Die automatische Eingangspegelanpassung hebt leise Eingangspegel an, aber ohne den Pegel vollständig zu kompensieren.
 +        // Auf diese Weise haben leise Eingangssignale einen geringeren Pegelausschalg als laute, es wird aber dennoch "mehr" angezeigt. 
 +        masterPeakMax = masterPeakMax - peakDecrease;                   // Der Maximalpegel wird schrittweise um den Wert "peakDecrease" verringert.   
 +
 +        autoGain = (1.00 - masterPeakMax) * 4;                          // autoGain wird berechnet
 +        if (autoGain > 4.00) {                                          // Die Maximale Pegelanhebung soll den Faktor 4 nicht überschreiten
 +          autoGain = 4.00;
 +        }
 +        if (autoGain < 1.00) {                                          // Die Maximale Pegelanhebung soll den Faktor 1 nicht unterschreiten
 +          autoGain = 1.00;
 +        }
 +        mixer_L.gain(0, autoGain);                                      // Der Eingangspegel des linken Kanals wird angepasst
 +        mixer_R.gain(0, autoGain);                                      // Der Eingangspegel des rechten Kanals wird angepasst
 +      
 +        previousMillisAutoInputLevelControl = currentMillis;
 +      }    
 +    }
 +
 +
 +    // Es wird die Zeit in Millisekunden berechnet, die für einen Durchgang benötigt wurde
 +    duration = millis()- lastMillis;
 +      
 +    // Serieller Output
 +    Serial.print(" cpu:");
 +    Serial.print(AudioProcessorUsageMax());
 +    Serial.print(" mem:");
 +    Serial.print(AudioMemoryUsageMax());
 +    Serial.print(" duration:");
 +    Serial.print(duration);
 +    Serial.print(" pos:");
 +    Serial.print(float(newPosition) / 40);
 +    Serial.print(" peak_L:");
 +    Serial.print(leftPeak);
 +    Serial.print(" peak_R:");
 +    Serial.print(rightPeak);
 +    Serial.print(" masterPeak:");
 +    Serial.print(masterPeak);
 +    Serial.print(" masterPeakMax:");
 +    Serial.print(masterPeakMax);
 +    if (autoInputLevelControl == true) {
 +      Serial.print(" autoGain:");
 +      Serial.print(autoGain);
 +    }
 +    Serial.println();
 +
 +    lastMillis = millis();
 +  }
 +}                                                     // Void Loop Ende
 +</code>
 +{{tag>Arduino Spektrumanalysator Teensy}}
arduino/spektrumanalysator/programmversion_0.4.txt · Zuletzt geändert: 18.05.2023 12:34 von 127.0.0.1