arduino:spektrumanalysator:programmversion_0.4
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende ÜberarbeitungLetzte ÜberarbeitungBeide Seiten der Revision | ||
arduino:spektrumanalysator:programmversion_0.4 [10.09.2017 01:09] – Frickelpiet | arduino:spektrumanalysator:programmversion_0.4 [18.12.2022 16:26] – Frickelpiet | ||
---|---|---|---|
Zeile 9: | Zeile 9: | ||
- | |||
- | |||
- | ToDos: | ||
- | * Ich habe immer noch ein sehr lautes Rauschen in den oberen Frequenzbändern. Um dieses abzustellen will ich das Audio Adaptor Board verwenden. Es könnte dann auch die Funktion autoVolumeControl verwendet werden, um leise Signale zu verstärken. | ||
Interessante Links: | Interessante Links: | ||
Zeile 18: | Zeile 14: | ||
* https:// | * https:// | ||
* Hexadezimale in dezimale Werte umrechnen: http:// | * Hexadezimale in dezimale Werte umrechnen: http:// | ||
+ | |||
+ | < | ||
+ | // Spektrumanalysator | ||
+ | // Für einen NeoPixel-Streifen mit 72 NeoPixeln | ||
+ | |||
+ | // | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | // Pins | ||
+ | #define encoderChannelA | ||
+ | #define encoderChannelB | ||
+ | #define NEOPIXELPIN | ||
+ | |||
+ | // Dreh-Encoder | ||
+ | Encoder myEnc(encoderChannelA, | ||
+ | |||
+ | 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; | ||
+ | |||
+ | float level_L[36]; | ||
+ | float level_R[36]; | ||
+ | float leftPeak; | ||
+ | float rightPeak; | ||
+ | float masterPeak; | ||
+ | float masterPeakMax; | ||
+ | float peakDecrease = 0.001; | ||
+ | float autoGain; | ||
+ | |||
+ | // Konfiguriert den NeoPixel-Ring | ||
+ | int numPixels = 72; // Anzahl der NeoPixel | ||
+ | Adafruit_NeoPixel strip = Adafruit_NeoPixel(numPixels, | ||
+ | |||
+ | // 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 | ||
+ | AudioMixer4 | ||
+ | AudioMixer4 | ||
+ | AudioAnalyzePeak | ||
+ | AudioAnalyzeFFT1024 | ||
+ | AudioAnalyzePeak | ||
+ | AudioAnalyzeFFT1024 | ||
+ | AudioConnection | ||
+ | AudioConnection | ||
+ | AudioConnection | ||
+ | AudioConnection | ||
+ | AudioConnection | ||
+ | AudioConnection | ||
+ | AudioControlSGTL5000 | ||
+ | // 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); | ||
+ | |||
+ | // enable the audio shield | ||
+ | sgtl5000_1.enable(); | ||
+ | sgtl5000_1.muteHeadphone(); | ||
+ | sgtl5000_1.muteLineout(); | ||
+ | sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); | ||
+ | sgtl5000_1.lineInLevel(5); | ||
+ | // | ||
+ | // | ||
+ | | ||
+ | // Configure the window algorithm to use | ||
+ | fft1024_L.windowFunction(AudioWindowHanning1024); | ||
+ | // | ||
+ | |||
+ | // Initialisiert den NeoPixel-Teststrip | ||
+ | strip.begin(); | ||
+ | strip.show(); | ||
+ | strip.setBrightness(64); | ||
+ | | ||
+ | // 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, | ||
+ | mixer_R.gain(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, | ||
+ | level_L[30] = fft1024_L.read(6, | ||
+ | level_L[29] = fft1024_L.read(8, | ||
+ | level_L[28] = fft1024_L.read(10, | ||
+ | level_L[27] = fft1024_L.read(12, | ||
+ | level_L[26] = fft1024_L.read(15, | ||
+ | level_L[25] = fft1024_L.read(18, | ||
+ | level_L[24] = fft1024_L.read(21, | ||
+ | level_L[23] = fft1024_L.read(25, | ||
+ | level_L[22] = fft1024_L.read(29, | ||
+ | level_L[21] = fft1024_L.read(33, | ||
+ | level_L[20] = fft1024_L.read(38, | ||
+ | level_L[19] = fft1024_L.read(44, | ||
+ | level_L[18] = fft1024_L.read(50, | ||
+ | level_L[17] = fft1024_L.read(57, | ||
+ | level_L[16] = fft1024_L.read(65, | ||
+ | level_L[15] = fft1024_L.read(74, | ||
+ | level_L[14] = fft1024_L.read(84, | ||
+ | level_L[13] = fft1024_L.read(95, | ||
+ | level_L[12] = fft1024_L.read(108, | ||
+ | level_L[11] = fft1024_L.read(122, | ||
+ | level_L[10] = fft1024_L.read(138, | ||
+ | level_L[9] = fft1024_L.read(156, | ||
+ | level_L[8] = fft1024_L.read(176, | ||
+ | level_L[7] = fft1024_L.read(199, | ||
+ | level_L[6] = fft1024_L.read(224, | ||
+ | level_L[5] = fft1024_L.read(252, | ||
+ | level_L[4] = fft1024_L.read(284, | ||
+ | level_L[3] = fft1024_L.read(320, | ||
+ | level_L[2] = fft1024_L.read(360, | ||
+ | level_L[1] = fft1024_L.read(405, | ||
+ | level_L[0] = fft1024_L.read(455, | ||
+ | | ||
+ | // 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, | ||
+ | level_R[5] = fft1024_R.read(6, | ||
+ | level_R[6] = fft1024_R.read(8, | ||
+ | level_R[7] = fft1024_R.read(10, | ||
+ | level_R[8] = fft1024_R.read(12, | ||
+ | level_R[9] = fft1024_R.read(15, | ||
+ | level_R[10] = fft1024_R.read(18, | ||
+ | level_R[11] = fft1024_R.read(21, | ||
+ | level_R[12] = fft1024_R.read(25, | ||
+ | level_R[13] = fft1024_R.read(29, | ||
+ | level_R[14] = fft1024_R.read(33, | ||
+ | level_R[15] = fft1024_R.read(38, | ||
+ | level_R[16] = fft1024_R.read(44, | ||
+ | level_R[17] = fft1024_R.read(50, | ||
+ | level_R[18] = fft1024_R.read(57, | ||
+ | level_R[19] = fft1024_R.read(65, | ||
+ | level_R[20] = fft1024_R.read(74, | ||
+ | level_R[21] = fft1024_R.read(84, | ||
+ | level_R[22] = fft1024_R.read(95, | ||
+ | level_R[23] = fft1024_R.read(108, | ||
+ | level_R[24] = fft1024_R.read(122, | ||
+ | level_R[25] = fft1024_R.read(138, | ||
+ | level_R[26] = fft1024_R.read(156, | ||
+ | level_R[27] = fft1024_R.read(176, | ||
+ | level_R[28] = fft1024_R.read(199, | ||
+ | level_R[29] = fft1024_R.read(224, | ||
+ | level_R[30] = fft1024_R.read(252, | ||
+ | level_R[31] = fft1024_R.read(284, | ||
+ | level_R[32] = fft1024_R.read(320, | ||
+ | level_R[33] = fft1024_R.read(360, | ||
+ | level_R[34] = fft1024_R.read(405, | ||
+ | level_R[35] = fft1024_R.read(455, | ||
+ | |||
+ | // Anzeigemodi | ||
+ | //Effekt " | ||
+ | if (displayMode == 0) { | ||
+ | |||
+ | // Anschließend werden Farbwerte für die linke Seite des NeoPixel-Streifens berechnet | ||
+ | for (i=0; i< | ||
+ | n = level_L[i]; | ||
+ | if (n >= 0.01) { | ||
+ | // Scale ' | ||
+ | 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, | ||
+ | } | ||
+ | else if(t192 > 0x40) { // middle | ||
+ | strip.setPixelColor(i, | ||
+ | } | ||
+ | else { // coolest | ||
+ | strip.setPixelColor(i, | ||
+ | } | ||
+ | } | ||
+ | else { | ||
+ | strip.setPixelColor(i, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Dann werden die Farbwerte für die rechte Seite des NeoPixel-Streifens berechnet | ||
+ | for (i=0; i< | ||
+ | n = level_R[i]; | ||
+ | if (n >= 0.01) { | ||
+ | // Scale ' | ||
+ | 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, | ||
+ | } | ||
+ | else if(t192 > 0x40) { // middle | ||
+ | strip.setPixelColor(i+36, | ||
+ | } | ||
+ | else { // coolest | ||
+ | strip.setPixelColor(i+36, | ||
+ | } | ||
+ | } | ||
+ | else { | ||
+ | strip.setPixelColor(i+36, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // 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(); | ||
+ | rightPeak = peak_R.read(); | ||
+ | } | ||
+ | // Für die automatische Eingangspegelregelung wird der lautere der beiden Audiokanäle verwendet. | ||
+ | masterPeak = max(leftPeak, | ||
+ | |||
+ | // 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 " | ||
+ | masterPeakMax = masterPeakMax - peakDecrease; | ||
+ | |||
+ | 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, | ||
+ | mixer_R.gain(0, | ||
+ | | ||
+ | previousMillisAutoInputLevelControl = currentMillis; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | // Es wird die Zeit in Millisekunden berechnet, die für einen Durchgang benötigt wurde | ||
+ | duration = millis()- lastMillis; | ||
+ | | ||
+ | // Serieller Output | ||
+ | Serial.print(" | ||
+ | Serial.print(AudioProcessorUsageMax()); | ||
+ | Serial.print(" | ||
+ | Serial.print(AudioMemoryUsageMax()); | ||
+ | Serial.print(" | ||
+ | Serial.print(duration); | ||
+ | Serial.print(" | ||
+ | Serial.print(float(newPosition) / 40); | ||
+ | Serial.print(" | ||
+ | Serial.print(leftPeak); | ||
+ | Serial.print(" | ||
+ | Serial.print(rightPeak); | ||
+ | Serial.print(" | ||
+ | Serial.print(masterPeak); | ||
+ | Serial.print(" | ||
+ | Serial.print(masterPeakMax); | ||
+ | if (autoInputLevelControl == true) { | ||
+ | Serial.print(" | ||
+ | Serial.print(autoGain); | ||
+ | } | ||
+ | Serial.println(); | ||
+ | |||
+ | lastMillis = millis(); | ||
+ | } | ||
+ | } // Void Loop Ende | ||
+ | </ | ||
+ | {{tag> |
arduino/spektrumanalysator/programmversion_0.4.txt · Zuletzt geändert: 18.05.2023 12:34 von 127.0.0.1