Innholdsfortegnelse:

EasyFFT: Fast Fourier Transform (FFT) for Arduino: 6 trinn
EasyFFT: Fast Fourier Transform (FFT) for Arduino: 6 trinn

Video: EasyFFT: Fast Fourier Transform (FFT) for Arduino: 6 trinn

Video: EasyFFT: Fast Fourier Transform (FFT) for Arduino: 6 trinn
Video: FFT Code 2024, November
Anonim
Image
Image

Måling av frekvens fra det fangede signalet kan være en vanskelig oppgave, spesielt på Arduino siden den har lavere beregningseffekt. Det er metoder tilgjengelig for å fange nullkryssing der frekvensen blir fanget ved å sjekke hvor mange ganger signalet krysser nulllinjer innenfor den gitte tiden. En slik metode fungerer kanskje ikke når signalet er en kombinasjon av forskjellige frekvenser.

Dette er på en eller annen måte vanskelig å kode hvis du ikke er fra en slik bakgrunn. Men å være en tinkerer denne koden kan være svært nyttig for ulike prosjekter relatert til musikk, signalanalyse. Motivet for dette prosjektet var å utarbeide en kode som er lett å implementere på Arduino uten å komme inn i bakgrunnen.

Dette prosjektet forklarer ikke Working of FFT, men forklarer anvendelsen av FFT -funksjonen. Den samme prosessen er også forklart i den vedlagte videoen.

Hvis du bare er interessert i bruk av kode og ikke til en forklaring på den. Du kan hoppe direkte til trinn 3.

Trinn 1: Introduksjon til frekvensomforming

Introduksjon til frekvensomforming
Introduksjon til frekvensomforming
Introduksjon til frekvensomforming
Introduksjon til frekvensomforming

Ethvert signal kan være sammensatt av en kombinasjon av forskjellige sinusformede bølger. Så et hvilket som helst tidsbasert signal kan også vises som en kombinasjon av de forskjellige sinusene til forskjellige amplituder.

Jeg prøvde å forklare arbeidet til DFT (diskret Fourier-transform) i en av de tidligere instruerbare (https://www.instructables.com/id/Arduino-Frequency…). Disse metodene er ekstremt treg for alle sanntidsapplikasjoner. som gjør det nesten ubrukelig.

På bildet vises et signal som er en kombinasjon av to frekvenser f2 og f5. Dette signalet multipliseres med test -sinusbølger med verdiene f1 til f5.

Det kan vises matematisk at -summasjon av multiplikasjon av to harmoniske datasett med forskjellig frekvens har en tendens til null (høyere antall data kan føre til batterresultat). I vårt tilfelle, hvis disse to multiplikasjonsfrekvensen har den samme (eller veldig nære) frekvensen, er summen av multiplikasjon null -tallet.

Så hvis signalet vårt multipliseres med f1 vil summeringen av multiplikasjon være null (nær null for ekte applikasjon). lignende er tilfellet for f3, f4. For verdien vil imidlertid f2 og f5 -utgangen ikke være null, men betydelig høyere enn resten av verdiene.

Her testes et signal med 5 frekvenser, så signalet må multipliseres med fem frekvenser. En slik intens beregning tar lengre tid. Matematisk er det vist at for N antall prøver tar det N*N kompleks multiplikasjon.

Trinn 2: Fast Fourier Transform

For å gjøre beregningen av DFT raskere ble FFT -algoritmen utviklet av James Cooley og John Tukey. Denne algoritmen regnes også som en av de viktigste algoritmene på 1900 -tallet. Det deler et signal i en merkelig og jevn sekvensert del som gjør en rekke nødvendige beregninger lavere. Ved å bruke den totale nødvendige komplekse multiplikasjonen kan reduseres til NlogN. som er en betydelig forbedring.

Du kan referere nedenfor til referanser som jeg refererte til mens du skrev koden for en detaljert forståelse av matematikken bak FFT:

1.

2.

3.

4.

Trinn 3: Forklaring av kode

1. Rask sinus og kosinus:

Beregning FFT tar verdien av forskjellige sinus og cosinus flere ganger. Den innebygde funksjonen til Arduino er ikke rask nok og tar god tid å gi den nødvendige verdien. Noe som gjør koden betydelig tregere (dobler tiden for 64 prøver). For å motvirke dette problemet blir verdien av sinus for 0 til 90 grader lagret som flere av 255. Hvis du gjør det, elimineres behovet for å bruke lagringstall som flyter, og vi kan lagre det som byte som tar 1/4 plass på Arduino. Sinusdata må limes inn øverst i koden for å deklarere den som en global variabel.

Bortsett fra sine_data, ble en matrise kalt f_peaks erklært som en global variabel. Etter hver kjøring av FFT -funksjonen oppdateres denne matrisen. Hvor f_peaks [0] er den mest dominerende frekvensen og ytterligere verdier i synkende rekkefø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];

Siden vi har lagret sinusverdien for 0 til 90 grader, kan enhver verdi av sinus eller cosinus beregnes. Nedenfor fungerer den første runden av tallet til null desimal og returverdien fra lagrede data. denne metoden trenger bare en flytende divisjon. Dette kan reduseres ytterligere ved direkte lagring av sinusverdier (ikke 255 multiple). men det tærer på mye minne på Arduino.

Bruk av prosedyren ovenfor reduserer nøyaktigheten, men forbedrer hastigheten. For 64 poeng gir den fordelen på 8 ms og for 128 poeng gir den en fordel på 20 ms.

Trinn 4: Forklaring av kode: FFT -funksjon

FFT kan bare utføres for prøvestørrelsen 2, 4, 8, 16, 32, 64 og så videre. hvis verdien ikke er 2^n, vil den ta undersiden av verdien. For eksempel, hvis vi velger prøvestørrelsen på 70, vil den bare vurdere de første 64 prøvene og utelate hvile.

Det anbefales alltid å ha en prøvestørrelse på 2^n. som kan være:

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

To flyter out_r og out_im vil ta mye minne. for Arduino nano vil ikke fungere for prøver høyere enn 128 (og i noen tilfeller 128) på grunn av mangel på tilgjengelig minne.

usignerte 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 av nivåene {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // input for sekvensering float out_r [data [o] = {}; // ekte del av transform float out_im [data [o] = {}; // fantasifull del av transform

Ytterligere flyt er som følger:

1. Koden genererer litt omvendt rekkefølgen for den angitte prøvestørrelsen (detaljer om bitreversering på referanser: trinn 2)

2. Inndata som er bestilt i henhold til generert ordre, 3. FFT utført

4. Amplituden til det komplekse tallet beregnet, 5. Topper oppdages og ordnes i synkende rekkefølge

6. resultatene kan nås fra f_peaks.

[for å få tilgang til andre data (bortsett fra toppfrekvens) bør koden endres, slik at lokal variabel kan kopieres til en forhåndsdefinert global variabel]

Trinn 5: Testing av koden

Testing av koden
Testing av koden
Testing av koden
Testing av koden

En prøve trekant bølge er gitt som input. for denne bølgesamplingsfrekvensen er 10 Hz og frekvensen av selve bølgen er 1,25 Hz.

Som det kan vises fra råproduksjonen, samsvarer verdien med FFT beregnet av Scilab. Imidlertid er disse verdiene ikke akkurat det samme som vi med lav nøyaktighet, men raskere sinusbølge.

I utgangsfrekvensen er arrayfrekvensen 1,25 og 3,75. det er ikke nødvendig å få den eksakte verdien hver gang. vanligvis kalles disse tallene frekvensbinger. så utgangsverdien kan være hvor som helst innenfor de angitte hyllene.

Hastighet:

for Arduino nano tar det:

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

Trinn 6: Konklusjon

Denne FFT-koden kan brukes i sanntidsapplikasjoner. Siden det tar rundt 30 ms å fullføre beregningen. Imidlertid er oppløsningen begrenset av et antall prøver. Antall prøver er begrenset av Arduino -minne. Ved å bruke Arduino Mega eller annen høyere ytelse kan brettets nøyaktighet forbedres.

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

Oppdatering (2/5/21)

Oppdateringer: // ----------------------------- FFT-funksjon --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

Datatypen N ble endret til Heltall (eksisterende byte) for å støtte> 255 utvalgsstørrelse. Hvis prøvestørrelsen er <= 128, bør byte datatype brukes.

Anbefalt: