Indholdsfortegnelse:

EasyFFT: Fast Fourier Transform (FFT) til Arduino: 6 trin
EasyFFT: Fast Fourier Transform (FFT) til Arduino: 6 trin

Video: EasyFFT: Fast Fourier Transform (FFT) til Arduino: 6 trin

Video: EasyFFT: Fast Fourier Transform (FFT) til Arduino: 6 trin
Video: Fourier in Computers (with FFT demo in C++) 2024, November
Anonim
Image
Image

Måling af frekvens fra det indfangede signal kan være en vanskelig opgave, især på Arduino, da den har lavere beregningseffekt. Der er metoder til rådighed til at fange nulkrydsning, hvor frekvensen registreres ved at kontrollere, hvor mange gange signalet krydser nullinjer inden for den givne tid. En sådan metode virker muligvis ikke, når signalet er en kombination af forskellige frekvenser.

Dette er på en eller anden måde svært at kode, hvis du ikke er fra en sådan baggrund. Men som en tinkerer kan denne kode være meget nyttig til forskellige projekter relateret til musik, signalanalyse. Motivet for dette projekt var at udarbejde en kode, der er let at implementere på Arduino uden at komme i baggrunden for det.

Dette projekt forklarer ikke FFT's arbejde, men forklarer anvendelsen af FFT -funktionen. Den samme proces forklares også i den vedhæftede video.

Hvis du kun er interesseret i anvendelsen af kode og ikke til en forklaring på den. Du kan springe direkte til trin 3.

Trin 1: Introduktion til frekvensomdannelse

Introduktion til frekvensomdannelse
Introduktion til frekvensomdannelse
Introduktion til frekvensomdannelse
Introduktion til frekvensomdannelse

Ethvert signal kan være sammensat af en kombination af forskellige sinusformede bølger. Så ethvert tidsbaseret signal kan også vises som en kombination af de forskellige sinus for forskellige amplituder.

Jeg forsøgte at forklare driften af DFT (diskret Fourier-transform) i en af de tidligere instruerbare (https://www.instructables.com/id/Arduino-Frequency…). Disse metoder er ekstremt langsomme til enhver applikation i realtid. hvilket gør det næsten ubrugeligt.

På billedet vises et signal, som er en kombination af to frekvenser f2 og f5. Dette signal ganges med test -sinusbølger med værdierne f1 til f5.

Det kan matematisk vises, at -summation af multiplikation af to harmoniske datasæt med forskellige frekvenser har tendens til nul (højere antal data kan føre til batterresultat). I vores tilfælde, hvis disse to multiplikationsfrekvenser har den samme (eller meget tætte) frekvens, er multiplikationssummen nonzero -tallet.

Så hvis vores signal ganges med f1 summering af multiplikation vil være nul (tæt på nul for reel anvendelse). lignende er tilfældet for f3, f4. For værdien vil f2 og f5 output dog ikke være nul, men betydeligt højere end resten af værdierne.

Her testes et signal med 5 frekvenser, så signalet skal multipliceres med fem frekvenser. Sådan intens beregning tager en højere tid. Matematisk er det vist, at for N antal prøver tager det N*N kompleks multiplikation.

Trin 2: Hurtig Fourier -transformation

For at gøre beregningen af DFT hurtigere blev FFT -algoritmen udviklet af James Cooley og John Tukey. Denne algoritme betragtes også som en af de vigtigste algoritmer i det 20. århundrede. Det deler et signal i en ulige og lige rækkefølge del, der gør et antal nødvendige beregninger lavere. Ved at bruge det kan den samlede nødvendige komplekse multiplikation reduceres til NlogN. hvilket er en væsentlig forbedring.

Du kan henvise nedenfor til referencer, som jeg refererede til, mens du skrev koden for en detaljeret forståelse af matematikken bag FFT:

1.

2.

3.

4.

Trin 3: Forklaring af kode

1. Hurtig sinus og kosinus:

Beregning FFT tager værdien af forskellige sinus og cosinus flere gange. Den indbyggede funktion af Arduino er ikke hurtig nok og tager lang tid at levere den nødvendige værdi. Hvilket gør koden betydeligt langsommere (fordobler tiden for 64 prøver). For at imødegå dette problem gemmes værdien af sinus for 0 til 90 grader som flere af 255. Hvis du gør det, elimineres behovet for at bruge lagringstal som float, og vi kan gemme det som byte, hvilket tager 1/4 plads på Arduino. Sinusdata skal indsættes øverst i koden for at erklære den som en global variabel.

Bortset fra sine_data erklæres en matrix kaldet f_peaks som en global variabel. Efter hver kørsel af FFT -funktion opdateres dette array. Hvor f_peaks [0] er den mest dominerende frekvens og yderligere værdier i faldende rækkefølge.

byte sine_data [91] = {0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66, 70, 75, 79, 83, 87, 91, 96, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 206, 209, 211, 214, 216, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255}; float f_peaks [5];

Da vi har lagret sinusværdi for 0 til 90 grader, kan enhver værdi af sinus eller cosinus beregnes. Nedenfor fungerer den første runde af tallet til nul decimaltegn og returværdi fra lagrede data. denne metode behøver kun en flydende division. Dette kan reduceres yderligere ved direkte at lagre sinusværdier (ikke 255 multiple). men det æder høj hukommelse på Arduino.

Brug af ovenstående procedure reducerer nøjagtigheden, men forbedrer hastigheden. For 64 point giver det fordelen på 8ms og for 128 point giver det en fordel på 20ms.

Trin 4: Forklaring af kode: FFT -funktion

FFT kan kun udføres for prøvestørrelsen 2, 4, 8, 16, 32, 64 og så videre. hvis værdien ikke er 2^n, vil den tage den nedre side af værdien. For eksempel, hvis vi vælger prøvestørrelsen på 70, vil det kun overveje de første 64 prøver og udelade hvile.

Det anbefales altid at have en stikprøvestørrelse på 2^n. som kan være:

2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, …

To floats out_r og out_im tager en stor mængde hukommelse. for Arduino nano fungerer ikke for prøver højere end 128 (og i nogle tilfælde 128) på grund af mangel på tilgængelig hukommelse.

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

int a, c1, f, o, x; a = N; for (int i = 0; i <12; i ++) // beregning af niveauerne {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // input til sekventering float out_r [data [o] = {}; // reel del af transform float out_im [data [o] = {}; // fantasifuld del af transformation

Yderligere flow er som følger:

1. Koden genererer en smule omvendt rækkefølgen for den givne prøve størrelse (detaljer om bit reversering på referencer: trin 2)

2. Indtast data bestilt i henhold til genereret ordre, 3. FFT udført

4. Amplituden af det komplekse antal beregnet, 5. Toppe registreres og ordnes i faldende rækkefølge

6. resultater kan tilgås fra f_peaks.

[for at få adgang til andre data (bortset fra spidsfrekvens) skal koden ændres, så lokal variabel kan kopieres til en foruddefineret global variabel]

Trin 5: Test af koden

Test af koden
Test af koden
Test af koden
Test af koden

En prøve trekant bølge er givet som input. for denne bølgesamplingsfrekvens er 10 Hz, og frekvensen af selve bølgen er 1,25 Hz.

Som det kan fremgå af råproduktet, svarer værdien til FFT beregnet af Scilab. disse værdier er imidlertid ikke nøjagtig de samme som vi lav nøjagtighed, men hurtigere sinusbølge.

I outputfrekvensen er arrayfrekvensen 1,25 og 3,75. det er ikke nødvendigt at få den nøjagtige værdi hver gang. typisk kaldes disse tal frekvensbakker. så outputværdien kan være hvor som helst inden for angivne bakker.

Hastighed:

til Arduino nano tager det:

16 Points: 4ms32 Points: 10ms 64 Points: 26ms 128 Points: 53ms

Trin 6: Konklusion

Denne FFT-kode kan bruges i applikationer i realtid. Da det tager omkring 30 ms at gennemføre beregningen. Imidlertid er dens opløsning begrænset af et antal prøver. Antallet af prøver er begrænset af Arduino -hukommelse. Ved at bruge Arduino Mega eller anden højere ydeevne kan boardets nøjagtighed forbedres.

hvis du har spørgsmål, forslag eller rettelser, er du velkommen til at kommentere.

Opdatering (2/5/21)

Opdateringer: // ----------------------------- FFT-funktion --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

Datatypen N blev ændret til heltal (eksisterende byte) for at understøtte> 255 prøve størrelse. Hvis stikprøvestørrelsen er <= 128, skal byte datatype bruges.

Anbefalede: