Audio Analyser Hardware fragen

Moin Coder Profis,

ich habe da ne Frage zum Audio Spectrum Analyser.
Was wäre besser die Audioeingänge direkt am Pin an zu schließen oder wäre es sinnvoller ein Modul zu benutzen?
Wäre schon besser denke ich um die CPU zu entlasten, sehe ich das richtig?

Hab zwar probiert direkt drauf zu gehen, aber da gibt es nen Beispiel da kriege ich überhaupt nicht hin die fix_fft.h zum laufen zu bekommen.

Anderes Beispiel aus Netzt nutzt ein Modul, dieses als Beispiel und Random Daten habe ich zum laufen bekommen.

Daher wollte ich fragen was die bessere Lösung wäre, Chip ist übrigens ESP32 Wroom, fast alle Pins sind belegt 36, 39 sind noch frei am i2C hängt DS3231 dran.

Dankeschön für eure Tipps.

Grüße

Ich finde Audio Analyser auch klasse, aber bei Deinem Text verstehe ich nur Bahnhof :thinking:

1 Like

Hallo,

ja tut mir leid, war noch sehr früh am morgen.

Frage lautet: Ist es besser zum anschließen am ESP32 3.3V ein IC benutzen oder einfache Anbindung mit Widerständen geht auch?

Das ist erst die erste Hürde, die zweite schaue noch nicht ganz durch wie ich die Daten aus der Leitung auf das Display bekomme.

Grüße

Was sind das für Displays,wen I2C mit 5V dann bittet sich level shifter an der past die Pegel an.

1 Like

Danke für die Antwort,

Displays sind SPI, das läuft an sich alles. Dank auch euch, musste mehrere Themen erstellen, zu verschiedenen Fragen.

Jetzt hänge ich am Analyser fest, ein Beispiel funktioniert aber mit random Werten. Show quasi.

Jetzt möchte ich vom Chinch Kabel das Audiosignal abgreifen und diesen ESP32 auswerten lassen und es dann auf den Display bringen.

Frage war ja, soll man mit paar Widerständen die Leitung anschließen, oder ein Modul nehmen der ein IC hat.

Sketch muss ich dan herumfummeln, ohne aber des Anschlusses ist es schwer was zu testen.

Grüße

Eine Frage wie wird das Signal auf die einzelne Frequenzbände zerlegt?
Denk dran das der ESP nur mit max 3,3V an den Pins arbeitet. Zeige mal den test Sketch.

1 Like

Moin,

den Code habe ich an meine Bedürfnisse angepasst, damit wie im ersten Post die Balken halt hin und her springen nach Randomzahlen. Der Code stamm von diesem Beispiel:

Youtube

Änderung auf mein Setup:

#define _LCDML_cfg_use_ram 

  // include libs
  #include <WiFi.h>     // For WiFi
  #include <LCDMenuLib2.h>
  #include "time.h"     // For time things
  #include "RTClib.h"   // For DS3231 RTC Module

  // U8g2lib
  #include <Arduino.h>
  #include <U8g2lib.h>

  #ifdef U8X8_HAVE_HW_SPI
  #include <SPI.h>
  #endif
  #ifdef U8X8_HAVE_HW_I2C
  #include <Wire.h>
  #endif

#define SDA_PIN 21
#define SCL_PIN 22


U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/2, /* dc=*/U8X8_PIN_NONE, /* reset=*/15);
U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2_2(U8G2_R0, /* cs=*/19, /* dc=*/U8X8_PIN_NONE, /* reset=*/U8X8_PIN_NONE);
U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2_3(U8G2_R0, /* cs=*/4, /* dc=*/U8X8_PIN_NONE, /* reset=*/U8X8_PIN_NONE);
U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2_4(U8G2_R0, /* cs=*/5, /* dc=*/U8X8_PIN_NONE, /* reset=*/U8X8_PIN_NONE);


byte audio_bar_height[7]; // sizes for the individual bars
byte audio_bar_peak[7]; // positions for the individual peaks (lines over the bars)

void setup() {
  
     pinMode(25, OUTPUT);
     pinMode(26, OUTPUT);
     pinMode(27, OUTPUT);
     pinMode(33, OUTPUT);
     
     Serial2.begin(9600);
     Wire.begin();
     u8g2.begin();
     u8g2_2.begin();
     u8g2_3.begin();
     u8g2_4.begin();
}


void loop() { // main loop

    digitalWrite(25, HIGH);
    digitalWrite(26, HIGH);
    digitalWrite(27, HIGH);
    digitalWrite(33, HIGH);

  u8g2.clearBuffer();  // clear buffer for storing display content in RAM
  u8g2_2.clearBuffer();  // clear buffer for storing display content in RAM
  u8g2_3.clearBuffer();  // clear buffer for storing display content in RAM
  u8g2_4.clearBuffer();  // clear buffer for storing display content in RAM

  for (int i=0; i<16; i++) { // loop for every fraquency (63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25kHz and 16kHz)

    int random_value = random(1024); // calculate random value between 0-1024
    audio_bar_height[i] = audio_bar_height[i] + ((map(random_value, 0, 1024, 0, 48) - audio_bar_height[i]) / 4.0); // update the bar with a new value (slowly)

    // calculate the peak position
    if (audio_bar_peak[i] < audio_bar_height[i]) { // if the peak is below the current bar size
      audio_bar_peak[i] = audio_bar_height[i]; // move peak to the new max. position (i.e. size of the bar)
    } else if (audio_bar_peak[i] > audio_bar_height[i]) { // if the bar is lower than the peak
      audio_bar_peak[i]--; // slowly move the peak down, one pixel every frame
    }

    u8g2.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak

    u8g2_2.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2_2.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak

    u8g2_3.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2_3.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak

    u8g2_4.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2_4.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak
  }
     


  u8g2.sendBuffer(); // send buffer from RAM to display controller
  u8g2_2.sendBuffer(); // send buffer from RAM to display controller
  u8g2_3.sendBuffer(); // send buffer from RAM to display controller
  u8g2_4.sendBuffer(); // send buffer from RAM to display controller



}

Meine erste Versuche da die Line anzubinden waren folgende:

#define _LCDML_cfg_use_ram 

  // include libs
  #include <WiFi.h>     // For WiFi
  #include <LCDMenuLib2.h>
  #include "time.h"     // For time things
  #include "RTClib.h"   // For DS3231 RTC Module

  // U8g2lib
  #include <Arduino.h>
  #include <U8g2lib.h>

  #ifdef U8X8_HAVE_HW_SPI
  #include <SPI.h>
  #endif
  #ifdef U8X8_HAVE_HW_I2C
  #include <Wire.h>
  #endif

#define SDA_PIN 21
#define SCL_PIN 22

#define DEBUG 0
#define L_IN 36 // Audio input A0 Arduino
#define R_IN 39 // Audio input A1 Arduino


U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/2, /* dc=*/U8X8_PIN_NONE, /* reset=*/15);
U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2_2(U8G2_R0, /* cs=*/19, /* dc=*/U8X8_PIN_NONE, /* reset=*/U8X8_PIN_NONE);
U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2_3(U8G2_R0, /* cs=*/4, /* dc=*/U8X8_PIN_NONE, /* reset=*/U8X8_PIN_NONE);
U8G2_GP1294AI_256X48_F_4W_HW_SPI u8g2_4(U8G2_R0, /* cs=*/5, /* dc=*/U8X8_PIN_NONE, /* reset=*/U8X8_PIN_NONE);


const int Yres = 8;
const int gain = 3;
float peaks[64];
char im[64], data[64];
char Rim[64], Rdata[64];
char data_avgs[64];
int debugLoop;
int i;
int load;


byte audio_bar_height[7]; // sizes for the individual bars
byte audio_bar_peak[7]; // positions for the individual peaks (lines over the bars)


void setup() {
  
     pinMode(25, OUTPUT);
     pinMode(26, OUTPUT);
     pinMode(27, OUTPUT);
     pinMode(33, OUTPUT);
     
     Serial2.begin(9600);
     Wire.begin();
     u8g2.begin();
     u8g2_2.begin();
     u8g2_3.begin();
     u8g2_4.begin();
}


void loop() { // main loop

    digitalWrite(25, HIGH);
    digitalWrite(26, HIGH);
    digitalWrite(27, HIGH);
    digitalWrite(33, HIGH);

    u8g2.clearBuffer();  // clear buffer for storing display content in RAM
    u8g2_2.clearBuffer();  // clear buffer for storing display content in RAM
    u8g2_3.clearBuffer();  // clear buffer for storing display content in RAM
    u8g2_4.clearBuffer();  // clear buffer for storing display content in RAM

    for (int i = 0; i < 64; i++) {    // 64 bins = 32 bins of usable spectrum data

    data[i]  = ((analogRead(L_IN) / 8 ) - 256);  // chose how to interpret the data from analog in
    im[i]  = 0;   // imaginary component
    Rdata[i] = ((analogRead(R_IN) / 8 ) - 256);  // chose how to interpret the data from analog in
    Rim[i] = 0;   // imaginary component


    // calculate the absolute values of bins in the array - only want positive values
    for (int i = 0; i < 40; i++) {
    data[i] = sqrt(data[i]  *  data[i] +  im[i] *  im[i]);
    Rdata[i] = sqrt(Rdata[i] * Rdata[i] + Rim[i] * Rim[i]);

    // COPY the Right low-band (0-15) into the Left high-band (16-31) for display ease
    if (i < 20) {
      data_avgs[i] = data[i];
    }
    else {
      data_avgs[i] = Rdata[i - 20];
    }

    // Remap values to physical display constraints... that is, 8 display custom character indexes + "_"
    data_avgs[i] = constrain(data_avgs[i], 0, 9 - gain);     //data samples * range (0-9) = 9
    data_avgs[i] = map(data_avgs[i], 0, 9 - gain, 0, Yres);  // remap averaged values
  }

    u8g2.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak

    u8g2_2.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2_2.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak

    u8g2_3.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2_3.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak

    u8g2_4.drawBox(3 + i*16, 48-audio_bar_height[i], 10, audio_bar_height[i]); // draw bar

    u8g2_4.drawBox(3 + i*16, 48-audio_bar_peak[i], 10, 1); // draw peak
  }
     


  
  u8g2_2.sendBuffer(); // send buffer from RAM to display controller
  u8g2_3.sendBuffer(); // send buffer from RAM to display controller
  u8g2_4.sendBuffer(); // send buffer from RAM to display controller

}

  void Two16_LCD() {

  for (int x = 1; x < 20; x++) {  // init 0 to show lowest band overloaded with hum
    int y = x + 20; // second display line
    if (data_avgs[x] > peaks[x]) peaks[x] = data_avgs[x];
    if (data_avgs[y] > peaks[y]) peaks[y] = data_avgs[y];

    u8g2.setCursor(12, 12); // draw first (top) row Left
    if (peaks[x] == 0) {
      u8g2.print("_");  // less LCD artifacts than " "
    }
    else {
      u8g2.print(peaks[x]);
    }

    u8g2.setCursor(20, 20); // draw second (bottom) row Right
    if (peaks[y] == 0) {
      u8g2.print("_");
    }
    else {
      u8g2.print(peaks[y]);
    }

      debugLoop++;
    if (DEBUG && (debugLoop > 99)) {
    debugLoop = 0;
    u8g2.sendBuffer(); // send buffer from RAM to display controller
  }
}
}

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
  }


void decay(int decayrate) {
  int DecayTest = 1;
  // reduce the values of the last peaks by 1
  if (DecayTest == decayrate) {
    for (int x = 0; x < 40; x++) {
      peaks[x] = peaks[x] - 1;  // subtract 1 from each column peaks
      DecayTest = 0;
    } 
  }

  DecayTest++;
}

Es gibt noch eine gute Lösung, aber da kriege ich fix_fft.h net zum laufen:

Youtube

Ja versuche immer Beispiele an zu sehen und mich irgendwie durch zu mogeln.

Im ersten Video verwendet er ein Sound Modul, im zweiten direkt am Pin mit ein paar Widerständen. Ich weiß nicht welche Lösung für den ESP32 einfacher wäre. CPU lastig weniger belastbar z.B.

Grüße

Das ist aber keine Spectrum analyze nur Audiopegelanzeige :wink:
Um ein Audiosignal zerlegen gibt es extra Bausteine, die einfache arbeiten mit LED, die könte man nehmen dafür.

1 Like

Aha interessant, dachte das wäre mehr oder weniger das selbe... Höhe der einzelnen Frequenz oder halt eines Bereiches.
Autolevel wäre auch mal schön zu haben, das Teil soll eher nur Mäusekino sein.

Also wäre ein Modul besser? Genau den Chip hat er auch im ersten Beispiel, hoffe das Uhrenmodul, hat keine Probleme damit.

Schaue gerade den Schaltplan dieses Projekts an, wollte so in etwa nachbauen:

Arduino Spectrum

Wenn aber man mit dem Modul besser fährt, würde den auch nehmen.
Wenn ich richtig liege hat er diesen verwendet:

Link

ist ja der was habe gezeigt :wink:

1 Like

Ja ich weiß 100% der selbe.

Nun ist es den Sinnvoll und besser so einen IC zu verwenden?

Glaube hab fast ne Woche dran gesessen und herum experimentiert, alles für die Katz, außer das das Display schon mal für die Anzeige vorbereitet ist.
Mann will ja nicht gleich im Forum euch mit belästigen, für einen ist es einfach und der andere sucht sich dumm und dämlich. Da nie was mit zutun gehabt.

Dankeschön sehr für Deine Hilfe, wenn Du mir jetzt noch bitte sagen würdest, das es mit dem Chip besser ist wie ohne. Dann kann ich den schon mal bestellen.

Glaube hier darf man keine Videos hochladen, kann mein halb fertiges Projekt auch mal zeigen, natürlich wenn Interesse besteht...

Grüße

Vor XX J habe was gebaut mit LED für meinen Sohnemann, erinnere mich dass das eine Platine war zum selberlöten, der Ic war in DIP18, habe aber den nicht gefunden == vergessen was für einer das war.
Wegen dem Modul such mall nach MSGQ7, 20€ sind schon heftig.

1 Like

Ja ist schon krass. oder man lötet dann das ganze drum herum selber.
Glaube den Chip habe ich einzeln in DE nicht gefunden gehabt, muss noch mal schauen.

Also ist es besser mit IC zu arbeiten, richtig?

Glaube hier darf man keine Videos hochladen, kann mein halb fertiges Projekt auch mal zeigen, natürlich wenn Interesse besteht...

Einfach irgend wo hochladen, hier Link zeigen das geht.

Ich schau mall ob ich nicht was finde

wen nicht eilt wurde bei Ali suchen nach Modulen :wink:

1 Like

Vielleicht hilft dir auch Fast Fourier Transformation.

Arduino Color Organ Fourier Transform Power Spectrum (youtube.com)

Hatte ich vor einiger Zeit mal auf einem Arduino Uno (Clone) nachgebaut.

Hardware für Frequenzfilter für Audiosignal (arduinoforum.de)
Ein ESP ist da natürlich Leistungsstärker und kann detailierter berechnen.

1 Like

Danke euch für die antworten.

Gut suche nach Modulen, kann dann etwas andere Sachen noch erledigen.

Werde gleich schauen ob ich was zu Youtube bekomme.

Ja der ESP32 ist stärker, der hat aber bei mir viel zutun. Fast alle Pins sind belegt...
Erst waren 4 ESP's grdacht, Ihr habt mir aber den richtigen weg gezeigt, das einer ausreicht und das dieser 3.3v nur verträgt, dachte das er 5v kann davor...

Genau berechnen muss der ESP die Anzeige für Analyser nicht genau, es soll etwa zappeln nach Musik mehr nicht.

Habe über den Code bißchen drüber geschaut, wie bestimmt man den den Eingang? Bestimmt habe ich was übersehen.

Getrennte Kanäle R und L wäre natürlich schön, aber zumindest so wie in meinem Beispiel gleich.
Schaue mal ob ich hochgeladen bekomme.

Grüße

So hat wohl geklappt.

Das erste Video ist der Test als Analyzer mit Random Zahlen, ist der erste Sketch irgendwo weiter oben.
Die sind eigentlich viel zu schnell, wenn nur auf elnen Display läuft, ist es noch viel schneller. Später war gedacht das der linke untere Display immer den Analyzer hat.

Analyzer Test

Nun meine Baustelle , ist noch etwas zu tun. Aber geht laaaangsam voran.
Echtzeituhr mit Wlan schon mal angebunden, ECU mit K-Line testweise auch. Naja... Hoffe wird was.
Wen Ihr wollt könnt gerne Kritik aussprechen, aber steinigt mich bitte nicht, bin kein Profi wie Ihr es seid.

Halbfertiger Müll :wink:

Grüße

vReal[i] = analogRead(A0);

Falls du das meinst.

1 Like

Stimmt, ich blindfisch...

Scheint aber echt gut zu funktionieren, theoretisch könnte man was daraus basteln.
Muss mal genauer anschauen, code scheint auch ziemlich schmal zu sein.

Dankeschön

Hallo,

wollte heute den Code aus dem Link probieren.
Beide ESP32 gehen damit in den Bootloop.

#include "arduinoFFT.h"                     // Bibliothek Arduino FFT

arduinoFFT FFT = arduinoFFT();              // Objekt erstellen

#define SAMPLES 128                         // Muss eine Potenz von 2 sein (z.B. 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024) // Mehr als 128 Übersteigt den Arbeitsspeicher vom Arduino Uno/Nano
#define SAMPLING_FREQUENCY 10000            // Hz, muss aufgrund der ADC-Konvertierungszeit 10000 oder weniger betragen. Bestimmt die maximale Häufigkeit, die vom FFT analysiert werden kann.
//#define amplitude 50                        // Teiler für die Amplitude Anzeige
unsigned int sampling_period_us;            // Variable für die Aufnahmelänge
double vReal[SAMPLES];                      // Speicher für die Stichproben
double vImag[SAMPLES];                      // Speicher für die Stichproben
unsigned long newTime, oldTime;             // Variablen zur Zeitberechnung
byte channel[] = {3,5,6};                   // LED Ausgänge

void setup() {
  for(byte i=0; i<sizeof(channel); i++){
    pinMode(channel[i],OUTPUT);
  }
  Serial.begin(115200);
  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY)); // Aufnahmelänge berechnen
}

void loop() {
  for (int i = 0; i < SAMPLES; i++) {
    newTime = micros()-oldTime;
    oldTime = newTime;
    vReal[i] = analogRead(36);                                      // Ein Konvertierung dauert ca. 1mS auf einem ESP8266
    vImag[i] = 0;
    while (micros() < (newTime + sampling_period_us)) { /* do nothing to wait */ }
  }
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
  for (byte i = 2; i < (SAMPLES/2); i++){                            // Verwende nicht SAMPLE 0 und nur die ersten SAMPLES/2 sind verwendbar. Jedes Array-Eleement stellt eine Frequenz und ihren Wert die Amplitude dar.
    if(i==2){
      for (byte j=0; j<sizeof(channel); j++){
        digitalWrite(channel[j],LOW);
      }
    }
    if (vReal[i] > 1000) {                                           // Rauschfilter, alles unter dem Wert wird unterdrückt
      if (i<=12){ // unter 700Hz
        Serial.print("bis 700Hz "); Serial.println((int)vReal[i]);
        digitalWrite(channel[0],HIGH);
      }
      if (i>16 && i<35 ){ // 700Hz bis 3000Hz
        Serial.print("700Hz bis 3000Hz "); Serial.println((int)vReal[i]);
        digitalWrite(channel[1],HIGH);
      }
      if (i>38){ // über 3000Hz
        Serial.print("über 3000Hz"); Serial.println((int)vReal[i]);
        digitalWrite(channel[2],HIGH);
      }
    }
  }
}