Sommario:

QuickFFT: FFT ad alta velocità per Arduino: 3 passaggi
QuickFFT: FFT ad alta velocità per Arduino: 3 passaggi

Video: QuickFFT: FFT ad alta velocità per Arduino: 3 passaggi

Video: QuickFFT: FFT ad alta velocità per Arduino: 3 passaggi
Video: Come realizzare un semplice Analizzatore di Spettro con le FFT e Arduino - Video 347 2024, Dicembre
Anonim
QuickFFT: FFT ad alta velocità per Arduino
QuickFFT: FFT ad alta velocità per Arduino

Il tipico Arduino ha RAM e potenza di elaborazione limitate e FFT è un processo ad alta intensità di calcolo. Per molte applicazioni in tempo reale, l'unico requisito è ottenere la frequenza con l'ampiezza massima o necessaria per rilevare i picchi di frequenza.

In uno dei miei istruttori, ho preparato un codice per FFT che può essere trovato qui: EasyFFT

Questo codice è stato in grado di eseguire FFT fino a 128 campioni su Arduino nano. Un numero di campioni superiore a questo non è possibile a causa della memoria limitata di Arduino. Ho modificato leggermente la funzione per migliorare la velocità e ridurre il consumo di memoria. Questa modifica consente ad Arduino di eseguire FFT cinque volte più velocemente e consuma quasi la metà della memoria. Questo Instructable non copre il funzionamento di FFT, i riferimenti per esso possono essere trovati su EasyFFT.

Passaggio 1: lavoro

Lavorando
Lavorando
Lavorando
Lavorando
Lavorando
Lavorando
Lavorando
Lavorando

La tipica funzione FFT viene modificata per migliorare la velocità con minore precisione. Come mostrato nell'immagine, un segnale di prova deve essere moltiplicato per forme d'onda seno o coseno. Questi valori possono essere compresi tra 0 e 1, quindi è necessario eseguire una moltiplicazione mobile. in Arduino, la moltiplicazione mobile è lenta rispetto alle operazioni intere.

In questa funzione, l'onda seno/coseno è sostituita da un'onda quadra. Poiché dobbiamo moltiplicare un segnale di prova con un'onda quadra che può avere valore 0, 1 o -1. A causa di ciò, possiamo sostituire la moltiplicazione mobile con una semplice addizione o sottrazione di numeri interi. Per Arduino l'addizione o la sottrazione di interi è circa 5 volte più veloce. Questo rende la risoluzione circa 5 volte più veloce.

A causa di questa modifica ora i valori del bin di frequenza possono essere memorizzati come un numero intero (che in precedenza era float) e otteniamo un altro vantaggio di un minor consumo di memoria. In Arduino Nano, int consuma 2 byte di memoria mentre float consuma 4 byte di memoria. Grazie a questo vantaggio nel nuovo codice, siamo in grado di eseguire FFT per quasi 256 campioni (in precedenza 128 campioni).

In Normal FFT avevamo bisogno di memorizzare il valore del seno per rendere una soluzione più veloce. Nella nuova funzione, poiché non sono più richiesti valori seno/coseno, possiamo eliminarlo e salvare un po' di memoria.

Implementazione:

L'implementazione di questa funzione è semplice. Possiamo semplicemente copiare la funzione all'en del codice. Questa funzione può essere eseguita utilizzando il comando seguente:

float f= Q_FFT(data, 256, 100);Nella funzione Q_FFT, data: questo termine è un array con valori di segnale, le dimensioni del campione consigliate sono 2, 4, 8, 32, 64, 128, 256, 512, … in poi. se la dimensione del campione non appartiene a questi valori, verrà ritagliata sul lato inferiore più vicino dei valori. ad esempio, se la dimensione del campione è 75, la FFT verrà eseguita per 64 numeri di campioni. Il numero massimo di dimensioni del campione è limitato dalla RAM disponibile su Arduino.

Il secondo termine specifica il numero di campioni in un array e l'ultimo termine è la frequenza di campionamento in Hz.

Passaggio 2: codice

Questa sezione spiega la modifica apportata al codice EasyFFT che deve essere tenuta presente durante la modifica del codice, 1. Come spiegato prima, qui gli interi sono usati per fare FFT. Int in Arduino è un numero a 16 bit e può contenere valori da -32768 a 32768. ogni volta che il valore di questo int supera questo intervallo causa il problema. per eliminare questo problema dopo ogni calcolo del livello. se uno qualsiasi dei valori supera i 15000 gli array completi verranno divisi per 100. questo impedirà l'overflow di int.

2. Calcolo dell'ampiezza: per calcolare l'ampiezza, la parte reale e immaginaria devono essere al quadrato e la radice quadrata della somma. la quadratura e la radice quadrata della funzione richiedono tempo. per rendere il processo più veloce, questo codice eseguirà semplicemente alcune delle grandezze delle parti reali e immaginarie. Questo è sicuramente meno accurato e in alcuni casi può portare a conclusioni errate. puoi scegliere di tornare al metodo Normale per il calcolo della magnitudo, ma ci vorrà più tempo e dovrai anche fare qualche disposizione per memorizzare questi numeri.

3. Questo codice non ha un modulo per il rilevamento di picchi multipli. Sceglierà semplicemente il valore con l'ampiezza massima (escludendo il primo numero che è offset DC). Se hai bisogno di più picchi puoi fare riferimento al codice EasyFFT e apportare le modifiche richieste qui. In tal caso, è necessario dichiarare anche alcuni array/variabili come variabili globali.

4. La funzione contiene la seguente riga:

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

dichiarare le variabili di cui sopra come una variabile globale (incollandola all'inizio del codice) farà risparmiare da qualche parte 1 millisecondo di tempo ad ogni esecuzione.

5. A differenza della funzione EasyFFT, in cui i primi 5 picchi sono stati memorizzati nell'array predefinito. Questa funzione restituirà un valore float. questo valore rappresenta la frequenza con ampiezza massima in Hz. Quindi la rappresentazione del codice sarà simile a questa.

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

6. Rilevamento del picco: una volta trovata la frequenza con l'ampiezza massima, questa funzione utilizza un'ampiezza di frequenza appena prima e dopo di essa per calcolare i risultati accurati. L'ampiezza utilizzata in questo calcolo è anche la somma del modulo (non la radice quadrata della somma dei quadrati)

se Fn è la frequenza con ampiezza massima, la frequenza può essere calcolata dalla formula seguente.

F effettivo = (A n-1 *Fn-1 + An-1 *Fn-1 + An-1 *Fn-1) / (An-1+An+An+1)

dove An è l'ampiezza di n la frequenza e Fn-1 è il valore della frequenza.

Passaggio 3: risultati:

Risultati
Risultati
Risultati
Risultati

Il tempo di risoluzione è mostrato nel confronto dell'immagine sopra con EasyFFT. Velocità di esso mostrata con il confronto.

Per i dati di esempio con 3 onde sinusoidali con frequenze diverse è mostrato. Il risultato di QuickFFT viene confrontato con l'output di Scilab. Come possiamo vedere nell'immagine, 3 picchi con ampiezza massima corrispondono all'uscita Scilab. Tuttavia, l'uscita è costituita da molto rumore, che può essere fuorviante per alcune applicazioni. Quindi si consiglia di controllare correttamente il codice prima di applicare alla tua applicazione.

Spero che tu abbia trovato questo codice utile per il tuo progetto. In caso di qualsiasi domanda o suggerimento, si prega di commentare.

Consigliato: