Neues aus dem Make-Labor: Von Bins, Beton und VFDs

Immer Mittwochs berichten wir über spannende Erkenntnisse, neue Bauteile und Tools, raffinierte Schaltungskniffe und zukünftige Projekte.

Lesezeit: 4 Min.
In Pocket speichern
vorlesen Druckansicht Kommentare lesen 4 Beiträge
Von
  • Carsten Meyer

Während die ersten Abonnenten unsere Make-Ausgabe 3/21 in den Händen halten, wird in unserer Werkstatt bereits wieder eifrig an der nächsten Ausgabe geschraubt. Heinz Behling wird, wenn er seine Experimente unbeschadet überlebt, einen Artikel über die optische Justage eines Lasercutters bringen. Darauf bin ich besonders gespannt, denn auch mein Gerät hätte so etwas nach der letzten, wohl etwas zu beherzten Spiegel-Reinigung mal nötig. Kollege Carsten Wartmann hat derweil Erfahrungen mit Beton gesammelt – er will mit dem 3D-Drucker Formen dafür bauen.

Bei mir lagert noch ein Vorrat an vierstelligen Siebensegment-VFDs von Pollin, die es neulich als Restposten zu einem unschlagbaren Preis gab. Einen Entwurf für einen sensortastenbedienten Wecker habe ich schon fertig. Leider kann man sich auf die Lagerbestände von Pollin nie so recht verlassen, deshalb taugen die Pläne wohl nur für ein wohl nur für ein Github-Repo, aber nicht für einen Artikel.

Könnte bei genügend Interesse ein Projekt werden: Touch-bedienter VFD-Wecker mit ATmega328P und 70-Cent-Display.

Am Wochenende bin ich über ein interessantes Problem gestolpert: Meine Idee war, Klänge eines Musikinstruments per FFT zu analysieren und hieraus auch gleich die Frequenz der Grundschwingung zu berechnen. Mit der ebenso beliebten wie großartigen BASS-DLL ist das kein großer Akt: Die enthaltene Funktion BASS_ChannelGetData(Channel, @FFT, BASS_DATA_FFT4096) liefert einen Buffer (@FFT) mit den Hann-gefensterten und transformierten "Bins" – das sind sozusagen die in einem festen Frequenzraster aufgeteilten Spektrallinien.

Eine FFT liefert genau halb so viele Bins wie Eingangswerte vorhanden sind – bei 4096 Samples also 2048, wobei jeder Bin exakt fs/N (mit fs = Sampling-Frequenz, N = Anzahl der Samples) breit ist und Bin 0 im fft-Buffer den Gleichspannungs-Anteil repräsentiert. Bei 44,1 kHz und 4096 Samples ergibt sich also eine Bin-Breite von 10,766 Hz. Um die Grundfrequenz zu bestimmen, sucht man den FFT-Buffer einfach nach dem ersten Maximum ab, die Grundfrequenz ist dann Bin-Breite mal Buffer-Index.

Das ist für die Bestimmung einer musikalischen Tonhöhe leider zu wenig: Noten im Bass-Bereich unterscheiden sich nur um wenige Hertz. Um nun eine höhere Auflösung im unteren Frequenzbereich zu erzielen, kann man die Sample-Frequenz halbieren oder die Anzahl der Samples verdoppeln/vervierfachen, wobei letzteres wegen des rasant ansteigenden Rechenaufwands nicht immer in Frage kommt.

Die Note C2# auf einem Musikinstrument: Die Grundfrequenz regt zwei nebeneinanderliegende FFT-Bins zu fast gleichen Teilen an. Mein Analyzer ermittelt neben der Grundfrequenz auch gleich die Klirranteile der Obertöne. Die horizontale Achse wird hier logarithmisch dargestellt (Rasterlinien im Oktavabstand).

Beim Betrachten der FFT-Daten im Tiefton-Bereich bin ich (leider nicht als erster) auf die Idee gekommen, zu einer möglichst exakten Ermittlung der Grundfrequenz nebeneinanderliegende Bin-Werte zu interpolieren: Wenn zwei nebeneinanderliegende Bins den gleichen Wert haben, muss die angelieferte Frequenz genau in der Mitte liegen, weil sie beide Bins gleich "triggert"; diesen Offset addiert man dann einfach zum Buffer-Index. Die Fachwelt ist sich leider uneins, mit welchen Faktoren man die Nebenan-Bins gewichtet, um einen möglichst passenden Offset zu finden; zudem ist die Gewichtung abhängig von der bei der FFT verwendeten Fenster-Funktion.

In der Tat lieferten die zum Teil hochakademisch hergeleiteten Interpolations-Formeln bei der BASS-FFT eher mäßige Ergebnisse. Hier mein einfaches Rezept, das jeweils drei nebeneinanderliegende Spektralanteile interpoliert:

offset:= 1.6 * (fft[n+1]-fft[n-1]) / ((1.4 * fft[n])+fft[n-1]+fft[n+1]);

mit n = Index auf das Maximum im FFT-Buffer fft[]. Die Grundfrequenz ergibt sich dann zu f:= (n + offset) * 10,766. Experimente mit einem realen Musikinstrument ergaben im Bassbereich eine maximalen Abweichung von 0,2 Hz zur "echten" Frequenz – eine Verbesserung um den Faktor 50 gegenüber der groben 10,766-Hz-Auflösung!

Der bis hier aufmerksame Leser wird einwenden, dass man ja auch einfach die Samples von einer positiven Flanke des Eingangssignals zur nächsten zählen könnte. Wenn die Frequenz aber kein ganzzahliger Teiler der Sample-Frequenz ist, muss man auch hier über viele Schwingungszüge interpolieren. Das ist aber fast so zeitaufwendig wie das das Frequenzzähler-Verfahren, das bei tiefen Tönen Torzeiten im Sekunden-Bereich erfordert. Abschließend sei noch angemerkt, dass der spezialisierte Goertzel-Algorithmus ebenfalls zur Bestimmung der Grundfrequenz prädestiniert ist; Um ihn "mal eben" zu implementieren, fehlte mir allerdings nach den positiven Ergebnissen meiner Formel der rechte Antrieb.

Mehr von Make Mehr von Make

(cm)