Inhaltsverzeichnis:

QuickFFT: Hochgeschwindigkeits-FFT für Arduino - Gunook
QuickFFT: Hochgeschwindigkeits-FFT für Arduino - Gunook

Video: QuickFFT: Hochgeschwindigkeits-FFT für Arduino - Gunook

Video: QuickFFT: Hochgeschwindigkeits-FFT für Arduino - Gunook
Video: Projekt Lichtorgel - Informatik 1 Labor/ "Einführung in die Mechatronik" - nopa1011 2024, November
Anonim
QuickFFT: Hochgeschwindigkeits-FFT für Arduino
QuickFFT: Hochgeschwindigkeits-FFT für Arduino

Typischer Arduino hat begrenzte RAM- und Rechenleistung, und FFT ist ein rechenintensiver Prozess. Für viele Echtzeitanwendungen besteht die einzige Anforderung darin, eine Frequenz mit maximaler Amplitude zu erhalten oder Frequenzspitzen zu erkennen.

In einem meiner anweisbaren habe ich einen Code für FFT vorbereitet, der hier zu finden ist: EasyFFT

Dieser Code war in der Lage, FFT von bis zu 128 Samples auf Arduino nano durchzuführen. Eine höhere Sampleanzahl als diese ist aufgrund des begrenzten Speichers von Arduino nicht möglich. Ich habe die Funktion ein wenig modifiziert, um die Geschwindigkeit zu verbessern und den Speicherverbrauch zu reduzieren. Diese Modifikation ermöglicht es Arduino, FFT fünfmal schneller durchzuführen und verbraucht fast die Hälfte des Speichers. Dieses Instructable deckt nicht das Arbeiten von FFT ab, Referenzen dafür finden Sie unter EasyFFT.

Schritt 1: Arbeiten

Arbeiten
Arbeiten
Arbeiten
Arbeiten
Arbeiten
Arbeiten
Arbeiten
Arbeiten

Die typische FFT-Funktion wird modifiziert, um die Geschwindigkeit mit geringerer Genauigkeit zu verbessern. Wie in der Abbildung gezeigt, muss ein Testsignal mit Sinus- oder Cosinuswellenformen multipliziert werden. Diese Werte können zwischen 0 und 1 liegen, daher ist eine Gleitmultiplikation ein Muss. In Arduino ist die Floating-Multiplikation im Vergleich zu Integer-Operationen langsam.

In dieser Funktion wird die Sinus-/Cosinuswelle durch eine Rechteckwelle ersetzt. Da müssen wir ein Testsignal mit einer Rechteckwelle multiplizieren, die den Wert 0, 1 oder -1 haben kann. Aus diesem Grund können wir die schwebende Multiplikation durch eine einfache ganzzahlige Addition oder Subtraktion ersetzen. Für Arduino ist die Addition oder Subtraktion ganzer Zahlen etwa 5-mal schneller. Dies macht das Lösen etwa 5-mal schneller.

Aufgrund dieser Modifikation können nun Frequenz-Bin-Werte als ganze Zahl gespeichert werden (was früher Float war) und wir erhalten einen weiteren Vorteil des geringeren Speicherverbrauchs. In Arduino Nano verbraucht int 2 Byte Speicher, während float 4 Byte Speicher verbraucht. Aufgrund dieses Vorteils im neuen Code sind wir in der Lage, FFT für fast 256 Samples (vorher 128 Samples) durchzuführen.

In der normalen FFT mussten wir den Sinuswert speichern, um eine Lösung schneller zu machen. Da wir in der neuen Funktion keine Sinus-/Cosinus-Werte mehr benötigen, können wir sie eliminieren und etwas Speicher sparen.

Implementierung:

Die Implementierung dieser Funktion ist unkompliziert. Wir können die Funktion einfach am Ende des Codes kopieren. Diese Funktion kann mit dem folgenden Befehl ausgeführt werden:

float f= Q_FFT(data, 256, 100);In der Funktion Q_FFT, data: Dieser Begriff ist ein Array mit Signalwerten, die empfohlene Samplegröße ist 2, 4, 8, 32, 64, 128, 256, 512, … und weiter. Wenn die Stichprobengröße nicht zu diesen Werten gehört, wird sie auf die nächste niedrigere Seite der Werte abgeschnitten. Wenn die Stichprobengröße beispielsweise 75 beträgt, wird die FFT für 64 Stichprobenzahlen durchgeführt. Die maximale Anzahl der Samples ist durch den verfügbaren RAM auf Arduino begrenzt.

Der zweite Term gibt die Anzahl der Abtastwerte in einem Array an und der letzte Term ist die Abtastfrequenz in Hz.

Schritt 2: Code

In diesem Abschnitt werden die im EasyFFT-Code vorgenommenen Änderungen erläutert, die bei der Änderung des Codes berücksichtigt werden müssen.

1. Wie zuvor erklärt, werden hier ganze Zahlen verwendet, um FFT durchzuführen. Int in Arduino ist eine 16-Bit-Zahl und kann Werte von -32768 bis 32768 enthalten. Wenn der Wert dieses int diesen Bereich überschreitet, verursacht dies das Problem. um dieses Problem nach jeder Levelberechnung zu beseitigen. Wenn einer der Werte 15000 überschreitet, werden komplette Arrays durch 100 geteilt. Dadurch wird ein Überlaufen von int verhindert.

2. Amplitudenberechnung: Um die Amplitude zu berechnen, müssen Real- und Imaginärteil quadriert und die Quadratwurzel der Summe benötigt werden. Quadrieren und die Quadratwurzel der Funktion ist zeitaufwendig. Um den Prozess zu beschleunigen, übernimmt dieser Code einfach einige der Größen von Real- und Imaginärteilen. Dies ist sicherlich weniger genau und kann in einigen Fällen zu falschen Schlussfolgerungen führen. Sie können für die Größenberechnung zur Normalmethode zurückkehren, aber es wird mehr Zeit in Anspruch nehmen und Sie müssen auch einige Vorkehrungen treffen, um diese Zahlen zu speichern.

3. Dieser Code hat kein Modul zur Mehrfachspitzenerkennung. Es wird einfach der Wert mit der maximalen Amplitude gewählt (mit Ausnahme der ersten Zahl, die DC-Offset ist). Wenn Sie mehrere Peaks benötigen, können Sie den EasyFFT-Code abrufen und die erforderlichen Änderungen hier vornehmen. In diesem Fall muss ein Array/eine Variable auch als globale Variable deklariert werden.

4. Die Funktion enthält folgende Zeile:

unsigned int Pow2[13]={1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

Wenn Sie die obigen Variablen als globale Variable deklarieren (am Anfang des Codes einfügen), sparen Sie bei jeder Ausführung 1 Millisekunde Zeit.

5. Im Gegensatz zur EasyFFT-Funktion, bei der die obersten 5 Peaks im vordefinierten Array gespeichert wurden. Diese Funktion gibt einen Float-Wert zurück. dieser Wert repräsentiert die Frequenz mit maximaler Amplitude in Hz. Die Codedarstellung sieht also ungefähr so aus.

float f= Q_FFT(Daten, 256, 100);

6. Spitzenwerterkennung: Sobald eine Frequenz mit maximaler Amplitude gefunden wurde, verwendet diese Funktion eine Frequenzamplitude direkt davor und danach, um die genauen Ergebnisse zu berechnen. Die in dieser Berechnung verwendete Amplitude ist auch die Summe des Moduls (nicht die Quadratwurzel der Summe der Quadrate).

Wenn Fn die Frequenz mit maximaler Amplitude ist, kann die Frequenz anhand der folgenden Formel berechnet werden.

Tatsächliches F= (A n-1 *Fn-1 + An-1 *Fn-1 + An-1 *Fn-1) / (An-1+An+An+1)

wobei An die Amplitude von n die Frequenz ist und Fn-1 der Frequenzwert ist.

Schritt 3: Ergebnisse:

Ergebnisse
Ergebnisse
Ergebnisse
Ergebnisse

Die Lösungszeit ist im obigen Bildvergleich mit EasyFFT dargestellt. Geschwindigkeit davon mit dem Vergleich gezeigt.

Für Beispieldaten werden 3 Sinuswellen mit unterschiedlichen Frequenzen gezeigt. Das Ergebnis von QuickFFT wird mit der Scilab-Ausgabe verglichen. Wie wir im Bild sehen können, stimmen 3 Peaks mit maximaler Amplitude mit der Scilab-Ausgabe überein. Die Ausgabe besteht jedoch aus viel Rauschen, was für einige Anwendungen irreführend sein kann. Es wird daher empfohlen, den Code ordnungsgemäß zu überprüfen, bevor Sie sich auf Ihre Bewerbung bewerben.

Ich hoffe, Sie fanden diesen Code für Ihr Projekt nützlich. Bei Fragen oder Anregungen bitte kommentieren.

Empfohlen: