In diesem Artikel werde ich meine Inspiration in der Laborarbeit Nr. 3 bereits in der Drüse
weiter verkörpern. Wir sprechen über das Erkennen einer Ziffer durch Ton im Tonmodus des Wählens auf dem Arduino unter Verwendung des Goertzel-Algorithmus.
Um dies zu implementieren, verwendete ich Arduino UNO, ein Elektretmikrofon (
Adafruit ) und ein 8x8-Display mit dem MAX7219-Treiber.
Aktionsplan
- Diskretisieren Sie eine ausreichende Anzahl von Proben (mit dem Programm aus dem vorherigen Artikel war ich überzeugt, dass 256 genug ist).
- Finden Sie die Amplituden des Frequenzgangs, die den gewünschten Frequenzen entsprechen, die die Zeichen codieren.
- Die zwei Maximalwerte der Amplitude geben die Zeilen- und Spaltenindizes des gewünschten Zeichens an, beispielsweise sieht die Abbildung 3 so aus.

Implementierung
Bevor wir mit einer Implementierung beginnen, beantworten wir die Frage: Wird Arduino UNO genug Leistung für uns haben?
Taktfrequenz: 16MHz
Ein Abtastzyklus dauert 13 Taktzyklen
Prescaler-Wert mit der höchsten Genauigkeit: 128
Es stellt sich heraus, 16 MHz / 13/128 ~ 9615 Hz - die gewünschte Abtastfrequenz, was bedeutet, dass Sie mit Frequenzen bis zu 4,8 kHz arbeiten können.
ADC-Abstimmung
Es gibt verschiedene Modi für den ADC-Betrieb. Die interessantesten sind unten aufgeführt (eine vollständige Liste im
Datenblatt für das Schlüsselwort ADCSRB).
- Single Read - mit der analogRead () -Methode, aber dies ist ein blockierender Aufruf, der 100µs dauert, und mit ihm ist es unmöglich, eine konstante Abtastrate bereitzustellen
- Freilaufmodus - In diesem Modus beginnt der nächste Abtastzyklus unmittelbar nach dem Ende des vorherigen und die maximale Abtastfrequenz wird angegeben
- Timer-Überlauf - Die Abtastung beginnt mit dem Timer-Überlauf. Auf diese Weise können Sie die Abtastfrequenz fein einstellen
ADC-Setup-Code, der Einfachheit halber habe ich den Freilaufmodus verwendet.
ADMUX = 0;
Signalverarbeitung
Sobald das gesamte Array von Samples eingegeben ist, schalten wir die Unterbrechung durch den ADC aus und berechnen die Amplitude des Spektrums mit dem Goertzel-Algorithmus. Ich werde in der Beschreibung des Algorithmus nicht mit dieser erschöpfenden
Ressource konkurrieren, aber ich werde meine Implementierung geben:
void goertzel(uint8_t *samples, float *spectrum) { float v_0, v_1, v_2; float re, im, amp; for (uint8_t k = 0; k < IX_LEN; k++) { float cos = pgm_read_float(&(cos_t[k])); float sin = pgm_read_float(&(sin_t[k])); float a = 2. * cos; v_0 = v_1 = v_2 = 0; for (uint16_t i = 0; i < N; i++) { v_0 = v_1; v_1 = v_2; v_2 = (float)(samples[i]) + a * v_1 - v_0; } re = cos * v_2 - v_1; im = sin * v_2; amp = sqrt(re * re + im * im); spectrum[k] = amp; } }
Sinus und Cosinus wurden zuvor für Proben berechnet, die den gewünschten Frequenzen entsprachen. Die Vollversion des Codes finden Sie
hier .
Schlussfolgerungen
Vor allem stellte sich heraus, dass die UNO-Ressourcen von Arduino für eine einfache Klangverarbeitung ausreichen.
Die wichtigste Lektion, die ich gelernt habe, dass der ADC eine sensible Sache ist, nachdem ich den Charakter erfolgreich erkannt und an die Konsole gesendet hatte, verbrachte ich eine Woche damit, ihn zu debuggen, um mit dem Display zu arbeiten, da ich den Boden des Mikrofons und des max7219 angeschlossen hatte und alle Samples sofort in Rauschen umgewandelt wurden.
Könnte es besser sein? Ja, es wäre korrekter, die Abtastfrequenz und die Anzahl der Abtastungen so zu wählen, dass die gewünschten Frequenzen mit dem Abtastgitter übereinstimmen. Dies würde die Ausbreitung des Spektrums verhindern. Solche Parameter sind bereits f = 8 kHz, N = 205, in welchem Fall Sie ADC nicht im Freilaufmodus, sondern im Timerüberlauf ausführen müssen, und der Unterschied wäre offensichtlich.
Der Kurs neigt sich dem Ende zu, aber es gibt noch viele Ideen.
Vielen Dank für Ihre Aufmerksamkeit.