ich möchte für ein Goa Open Air einen Hut mit EL Wire darum leuchten lassen, allerdings nicht dauerhaft, sondern pulsierend mit dem Bass. Jetzt ist meine Frage wie ich am ehesten im Hut feststelle, dass Bass ist. Also würdet ihr da mit einem Mikrofon am Analogeingang nur auf die Lautstärke losgehen, und wenn sehr laut, dann Bass, oder wie stellt man ehesten Bass fest? Vorallem muss ich das ganze dann auch noch irgendwie von außen mit der Umgebungslautstärke "abgleichen" können, also entweder an einem zweiten AI einen Poti, oder den Poti als Widerstand am Mikrofon.
Wie würdet ihr da vorgehen?
Du bräuchtest noch einen Frequenzfilter. Das kann man zwar auch in Software mit einer Fourier Analyse machen (die Lib gibt es fertig), aber einfacher wäre wohl ein RC-Tiefpass.
Habe mir die Fourier Geschichte mal angeschaut. Die Grundlagen sind mathematisch außerhalb meiner Liga, sind aber prinzipiell wie viele Hinweise von Dir erstmal interessant für spätere Projekte. Für nur den Bass darstellen wird das zu komplex. Die von Dir favorisierte Methode mit RC Glied führt auch über meine Limits hinaus, das bekomme ich nie berechnet. Und vorallem, kann man sowas auch nach der Verstärkung des Mikrofons auf den 5V Pegel anbringen, oder muss das davor stattfinden?
Die Grenzfrequenz (bei der die Spannung auf 70,7% abgefallenen ist) ist 1 / (2 * Pi * R * C)
Wenn man mal für den Bass den Bereich unter 150Hz annimmt (?) hat R * C den Wert 1 / (2 * Pi * 150) = 1 / 942,5
Da kann man sich dann eine Kombination aus RC auswählen, die diesen Wert hat. z.B. 100nF und 10,6k Ohm. Die Werte müssen auch nicht genau passen, da die Übertragungsfunktion eines Tiefpasses 1. Ordnung sowieso ziemlich flach ist.
Für einen digitalen Tiefpass braucht man keine FFT. Eine einfache Mittelwertbildung tut's auch. Oder ein exponentieller Filter weil der einfacher zu implementieren ist: Exponentielle Glättung – Wikipedia
Danke Euch beiden. Die Links von Serenifly habe ich schon so gelesen vor Deiner Antwort, und sehe den FFt wirklich als Overkill für einfach den Bass abtrennen. Und ich glaube, dass es auch einiges an Denkaufwand erfordert, bis man versteht was die Library macht, nichtmal wie sie das tut. Da ich das ganze evtl wieder mit einem ATTiny aufziehen will, und die Library explizit für die ATMega geschrieben ist. So wie Du den Tiefpass erklärst verstehe ich die Mathematik zwar immer noch nicht, aber ich kann es berechnen. Danke!
Die expotentielle Glättung verwende ich gerne um Analogeingänge zu glätten. Wie kann man damit oder einer Mittelwertbildung jetzt von einem Analogeingang Frequenzen heraus filtern? Das verstehe ich nicht.
Es ging doch darum einen Tiefpass zu etablieren. Das ist nichts anderes als Glätten.
Wenn Du mehr als eine Frequenz suchst aber nicht sehr viele, dann ist statt einer FFT oft der Goertzel Algorithmus besser: Goertzel algorithm - Wikipedia.
sven222:
Und ich glaube, dass es auch einiges an Denkaufwand erfordert, bis man versteht was die Library macht
Frequenzspektrum dürfte dir aber schon ein Begriff sein, oder?
Das gibt dir die Amplitude der Frequenzbestandteile eines Signals an. Eine reine Sinuswelle hat nur eine Frequenz. Entsprechend hat man in solchen Diagrammen da nur einen Peak. Komplexere Signale sind aber aus verschiedenen Frequenzen zusammengesetzt. Und deren Amplitude kann man einzeln berechnen.
Aber lassen wird das
Wegen dem Tiefpass. Kondensatoren sind Frequenzabhängige Widerstände und der Kondensator verursacht eine Phasenverschiebung der Spannung. Statt da mit komplexen Zahlen zu rechnen, kann man das einfach an einem rechtwinkligen Dreieck betrachten:
Daher kommt dieser Ausdruck Z = sqrt(Xc² + R²). Einfacher Pythagoras.
Es ist ein Spannungsteiler, also ist Ua = Ue * Xc / Z. Wobei Xc der kapazitive Blindwiderstand ist und Z der Scheinwiderstand aus R und C. Das ist analog zu Teilspannung = Gesamtspannung * Teilwiderstand / Gesamtwiderstand bei reinen ohmschen Widerständen.
Der Scheinwiderstand Z ist praktisch der Gesamtwiderstand aus R und C, aber durch die Phasenverschiebung kann man den eben nicht einfach addieren, sondern muss den Pythagoras anwenden.
Dann ersetzt man Xc durch 1 / (2 * Pi * f * C), fasst das zusammen und fertig. 2 * Pi ist der Umfang eines Einheitskreises. Daher heißt 2 * Pi * f auch Kreisfrequenz.
Das gibt dir die Amplitude der Frequenzbestandteile eines Signals an. Eine reine Sinuswelle hat nur eine Frequenz. Entsprechend hat man in solchen Diagrammen da nur einen Peak. Komplexere Signale sind aber aus verschiedenen Frequenzen zusammengesetzt. Und deren Amplitude kann man einzeln berechnen.
Aber lassen wird das
Na prima. So wars nicht gedacht. Meine Aussage war eher darauf bezogen wie man die library behandeln muss, also wie man wo was im Code einbindet, und was welche Auswirkungen hat. Da geht ganz schnell ein Tag weg, bis man so eine Library verstanden hat.
Zum Rest von Deinem Beitrag kann ich wie immer nur danke sagen. Mit etwas googlen an einigen Stellen werde ich da heute abend wieder weniger dumm als gestern ins Bett gehen. Und auch mit Udos Link zum Görtzel Algorithmus habe ich noch einiges zum lesen und lernen. Ihr glaubt gar nicht wie ich mich ärgere, dass meine Mathelehererin, die ich von der 10ten bis zum Abi hatte, und ich nicht miteinander klar kamen, und ich mich deshalb komplett verweigert habe. Es ist einfach blöd, wenn einem die Grundlagen komplett fehlen.
Ich werde jetzt wohl einen Tiefpassfilter bauen aus 100nF und irgendwas zwischen 10 und 20kOhm, und dann mal schauen ob das schon ausreicht. Da bei solchen Veranstaltungen der Bass meist so betont und so tieffrequent ist wird das hoffentlich reichen. Mikrofon im Hut untergracht führt nochmal zu einer Dämpfung. Falls vor Ort dann doch noch irgendwas umgelötet oder programmiert werden muss ist das nicht so schlimm, da auf dem Festival ein Arduino für Einsteiger Workshop sein wird, da kann man sich dann schnell einen Lötkolben borgen.
ich habe mich mit dem Thema Beaterkennung länger und mit verschiedenen Ansätzen befasst. U.a. oben genannte. Ergebnis: für mich alles Mist weil aufwändig/anfällig/komplex/langsam.
Benutze jetzt einen MSGEQ7 für alles, was mit "Audio triggert Ereignis" zu tun hat.
Oh ha, der MSGEQ7 sieht interessant aus. Vorallem für die zweite Hutidee die ich habe, ein Hut mit WS2812, gibt es zwar schon, wie man Deinem Link entnehmen kann, aber egal. Lernt man zwar nicht so viel bei, aber es könnte einfach und sauber funktionieren. Danke! Und feine Dinge, die Du da mit den LEDs nd den Tönen tust.
Das hängt vollständig von der Signalquelle (dein Mikro+Verstärker+Verkabelung) und dem Audiomaterial selbst ab. Das 160 Hz Band reagiert auf jeden Fall schneller (steilere Flanke).
Die interessantere Frage ist: WO im Pegel von einem Frequenzband legt man den Schwellwert (und wie regelt man ihn dynamisch nach)?
Das auf dem Tisch aufzubauen und das Eingangssignal von Hand zu regeln, bis es halt passt, ist eine andere Nummer, als auf einer Party ständig wechselnde Schalldrücke geschickt ausregeln zu lassen.
Ja, das wird bestimmt noch spannend. Ich will auf alle Fälle einen Poti dranmachen, dass man zumindest von Hand nachregeln kann.
Und Laptop kommt auch mit, dann kann man nachjustieren unter realen Bedingungen.
In dem von dir geposteten Tutorial (http://tronixstuff.com/2013/01/31/tutorial-arduino-and-the-msgeq7-spectrum-analyzer/)
ist entweder ein Fehler drin, oder ich bin total daneben. In zwei verschiedenen for Schleifen wird jeweils dieselbe globale Variable verwendet und hochgezählt. Zeile 21 und 34 im ersten Codelisting. Das kann so nicht passen. Aber die Grundidee wird klar wie es gehen soll. Das sollte man hinbekommen. Vieleicht mache ich ja endlich mal eine Library, der MSGEQ7 wäre da vieleicht das rchtige Opfer dafür.
Einmal wird in der Funktion readMSGEQ7() die globale Variable band hochgezählt, um den MSGEQ7 auszulesen, das andere Mal wird die Variable band hochgezählt, um zwecks Ausgabe der gespeicherten Wert aus left[band] und right [band] auszulesen. Nacheinander.
Ja, ich habe gerade etwas Neues über for() Schleifen gelernt, nämlich dass sie wirklich Schleifen sind. Ging von einer anderen Funktionsweise dieser aus. Ich habe mir bisher an vielen Stellen das Leben unnötig verkompliziert, und einige Fehler in der Vergangenheit erklären sich nach einigem am rumgoogeln gerade.
Da ich leider meine Bastelkiste nicht da habe weil ich in einem Hotel in der Türkei sitze kann ich Sachen nicht einfach ausprobieren, deshalb meine Nachfragen hier ständig.
Helmuth hat weiter vorne was angesprochen, von wegen wo man den Schwellenwert setzt und wie man ihn dynamisch nachregelt. Und Udo hat die expotentielle Glättung eingebracht, wenn auch nicht dafür. Jetzt meine Frage: Könnte es funktionieren, dass ich den "Mittelwert" des Basslevels mit der expotentiellen Glättung mit sehr kleinem Alpha berechne, und dann einfach den Bassausschlag mit x% über diesem Mittelwert festlege? Oder sollte man da besser eine "richtige" Mittelwertbildung verwenden?
ich habe jetzt zur Bass-Erkennung dieses Mikrofon ( http://www.watterott.com/de/Breakout-Board-mit-Kondensatormikrofon) mit einem Tiefpassfilter (100kOhm und 100nF) am Start. Die Basserkennung läuft in der Software damit, dass ich den analogeingang expotentielle Glätte mit einem sehr niedrigen Faktor (0.11), und sobald der Eingangswert 15% darüber liegt wird es als "Bassschlag" erkannt, und eine LED blinkt. In einem gewissen Rahmen funktioniert das auch. Leider ist das Mirkrofon sehr schnell am Vollauschlag, und liefert dann sehr kleine Werte. Also nach 1024 dann plötzlich 36. Das haut dann natürlich alles zusamen. Kann man das Mikrofon dazu bringen etwas weniger empfindlich zu sein?
Das zweite Problem ist, dass die 15% Mittelwertüberschreitung auch nicht wirklich die Ideallösung sind. Bei sehr leiser Musik wären 10% besser, bei sehr lauter 20%. Wie kann ich das am ehesten dynamisch nachziehen? Code habe ich unten mal angehängt.
Danke schon einmal für etwaige Antworten,
Sven
int led = 13;
double ExpSensVal = 500;
double ExpSensVal2 = 500;
double glaetten();
long previousMillis = 0; // will store last time LED was updated
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
Serial.begin(9600);
}
// the loop routine runs over and over again forever
void loop() {
int SensVal = analogRead(A0);
ExpSensVal = glaetten(SensVal, ExpSensVal, 0.11);
ExpSensVal2 = glaetten(SensVal, ExpSensVal2, 0.99);
double BassVal = ExpSensVal * 1.15;
if (ExpSensVal2 > BassVal){
digitalWrite(led, HIGH);
}
else{
digitalWrite(led, LOW);
};
}
int glaetten(double wertaktuell, double wertalt, double faktor){
double tmp = wertaktuell * faktor;
tmp = (tmp +( wertalt * (1 - faktor) ) );
return tmp;
}