Sisällysluettelo:

EasyFFT: Nopea Fourier -muunnos (FFT) Arduinolle: 6 vaihetta
EasyFFT: Nopea Fourier -muunnos (FFT) Arduinolle: 6 vaihetta

Video: EasyFFT: Nopea Fourier -muunnos (FFT) Arduinolle: 6 vaihetta

Video: EasyFFT: Nopea Fourier -muunnos (FFT) Arduinolle: 6 vaihetta
Video: QuickFFT: High Speed FFT for Arduino 2024, Marraskuu
Anonim
Image
Image

Taajuuden mittaus kaapatusta signaalista voi olla vaikea tehtävä, etenkin Arduinolla, koska sillä on pienempi laskentateho. Käytettävissä on menetelmiä nollanylityksen kaappaamiseen, jossa taajuus kaapataan tarkistamalla, kuinka monta kertaa signaali ylittää nollalinjat tietyn ajan kuluessa. Tällainen menetelmä ei ehkä toimi, kun signaali on eri taajuuksien yhdistelmä.

Tätä on jotenkin vaikea koodata, jos et ole tällaisesta taustasta. Mutta näppäränä koodina voi olla erittäin hyödyllistä erilaisissa musiikkiin ja signaalianalyysiin liittyvissä projekteissa. Tämän projektin motiivi oli valmistaa koodi, joka on helppo ottaa käyttöön Arduinolla ilman, että se joutuu taustalle.

Tämä projekti ei selitä FFT: n toimintaa, mutta selittää FFT -toiminnon soveltamisen. Sama prosessi selitetään myös oheisessa videossa.

Jos olet kiinnostunut vain koodin soveltamisesta etkä selittämään sitä. Voit siirtyä suoraan vaiheeseen 3.

Vaihe 1: Johdatus taajuusmuunnokseen

Johdatus taajuusmuunnokseen
Johdatus taajuusmuunnokseen
Johdatus taajuusmuunnokseen
Johdatus taajuusmuunnokseen

Mikä tahansa signaali voi koostua eri sinimuotoisten aaltojen yhdistelmästä. Joten mikä tahansa aikapohjainen signaali voidaan näyttää myös eri amplitudien eri sinien yhdistelmänä.

Yritin selittää DFT: n (diskreetti Fourier-muunnos) toimintaa yhdessä aiemmista ohjeista (https://www.instructables.com/id/Arduino-Frequency…). Nämä menetelmät ovat erittäin hitaita reaaliaikaisille sovelluksille. mikä tekee siitä lähes hyödyttömän.

Kuvassa näkyy signaali, joka on kahden taajuuden f2 ja f5 yhdistelmä. Tämä signaali kerrotaan arvojen f1 - f5 testisinisillä aalloilla.

Voidaan osoittaa matemaattisesti, että kahden eri taajuudella olevan harmonisen tietojoukon kertomisen yhteenlasku on yleensä nolla (suurempi datamäärä voi johtaa taikinatulokseen). Meidän tapauksessamme, jos näillä kahdella kertotaajuudella on sama (tai hyvin lähellä oleva) taajuus, kertomisen summa on nollasta poikkeava luku.

Joten jos signaalimme kerrotaan f1: llä, kertolasku on nolla (todellisen sovelluksen lähellä nolla). Sama koskee f3, f4. Arvon osalta f2- ja f5 -lähtö eivät kuitenkaan ole nollaa, mutta huomattavasti korkeammat kuin muut arvot.

Tässä signaali testataan viidellä taajuudella, joten signaali on kerrottava viidellä taajuudella. Tällainen intensiivinen laskeminen vie enemmän aikaa. Matemaattisesti on osoitettu, että N -näytteiden lukumäärä vaatii N*N -kompleksin kertomisen.

Vaihe 2: Nopea Fourier -muunnos

DFT: n laskemisen nopeuttamiseksi James Cooley ja John Tukey ovat kehittäneet FFT -algoritmin. Tätä algoritmia pidetään myös yhtenä 1900 -luvun tärkeimmistä algoritmeista. Se jakaa signaalin parittomaksi ja parilliseksi sekvenssiksi, mikä pienentää vaadittujen laskelmien määrää. Sen avulla vaadittu kokonaiskerroin voidaan laskea NlogN: ksi. mikä on merkittävä parannus.

Voit viitata alla oleviin viittauksiin, joihin viittasin koodia kirjoittaessasi, jotta ymmärrät yksityiskohtaisesti FFT: n takana olevan matematiikan:

1.

2.

3.

4.

Vaihe 3: Koodin selitys

1. Nopea sini ja kosini:

Laskenta FFT ottaa eri sinin ja kosinin arvon useita kertoja. Arduinon sisäänrakennettu toiminto ei ole riittävän nopea, ja vaaditun arvon saaminen vie paljon aikaa. Mikä hidastaa koodia merkittävästi (kaksinkertaistaa 64 näytteen ajan). Tämän ongelman ratkaisemiseksi sinin arvo 0-90 astetta varten tallennetaan moninkertaisena arvoon 255. Tällöin poistetaan tarve käyttää tallennusnumeroita kellukkeena ja voimme tallentaa sen tavuina, jotka vievät 1/4 tilaa Arduinolla. Sine_data on liitettävä koodin yläosaan, jotta se voidaan julistaa globaaliksi muuttujaksi.

Sine_datan lisäksi f_peaks -niminen taulukko julistettiin globaaliksi muuttujaksi. Jokaisen FFT -toiminnon jälkeen tämä taulukko päivittyy. Missä f_peaks [0] on hallitsevin taajuus ja muut arvot laskevassa järjestyksessä.

tavu 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];

Koska olemme tallentaneet siniarvon 0-90 astetta, voidaan laskea mikä tahansa sinin tai kosinin arvo. Alla toimii luvun ensimmäinen kierros nollan desimaalin tarkkuuteen ja palauttaa arvon tallennetuista tiedoista. tämä menetelmä tarvitsee vain yhden kelluvan jaon. Tätä voidaan pienentää entisestään tallentamalla siniarvot (ei 255 -kertaisia). mutta se syö paljon muistia Arduinolla.

Yllä olevan menettelyn käyttäminen vähentää tarkkuutta, mutta parantaa nopeutta. Se antaa 64 pisteen eduksi 8 ms ja 128 pisteen osalta 20 ms.

Vaihe 4: Koodin selitys: FFT -toiminto

FFT voidaan suorittaa vain näytteen koolle 2, 4, 8, 16, 32, 64 ja niin edelleen. jos arvo ei ole 2^n, se ottaa arvon alemman puolen. Jos esimerkiksi valitsemme näytteen koon 70, se ottaa huomioon vain 64 ensimmäistä näytettä ja jättää loput pois.

On aina suositeltavaa, että otoskoko on 2^n. Mikä voi olla:

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

Kaksi float out_r ja out_im vie paljon muistia. Arduino nano ei toimi yli 128 (ja joissakin tapauksissa 128) näytteissä käytettävissä olevan muistin puutteen vuoksi.

unsigned 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 ++) // tasojen laskeminen {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // tulo sekvensointia varten float out_r [data [o] = {}; // todellinen osa muunnosta float out_im [data [o] = {}; // kuvitteellinen osa muutosta

Lisävirtaus on seuraava:

1. Koodi luo hieman käänteisen järjestyksen annetulle otoskolle (lisätietoja bittien kääntämisestä viitteissä: vaihe 2)

2. Syötetyt tiedot on järjestetty generoidun tilauksen mukaan, 3. FFT suoritettu

4. Lasketun kompleksiluvun amplitudi, 5. Huiput havaitaan ja järjestetään laskevassa järjestyksessä

6. tuloksiin pääsee f_peaks : sta.

[päästäkseen muihin tietoihin (huipputaajuuden lisäksi) koodia on muutettava, jotta paikallinen muuttuja voidaan kopioida johonkin ennalta määritettyyn globaaliin muuttujaan]

Vaihe 5: Koodin testaaminen

Koodin testaaminen
Koodin testaaminen
Koodin testaaminen
Koodin testaaminen

Näyte kolmio aalto annetaan syöttö. tälle aallon näytteenottotaajuudelle on 10 Hz ja itse aallon taajuudelle 1,25 Hz.

Kuten raakatuotannosta voidaan nähdä, arvo vastaa Scilabin laskemaa FFT: tä. nämä arvot eivät kuitenkaan ole täsmälleen samat kuin alhainen tarkkuus, mutta nopeampi siniaalto.

Lähtötaajuusryhmän taajuus on 1,25 ja 3,75. tarkkaa arvoa ei tarvitse saada joka kerta. tyypillisesti näitä numeroita kutsutaan taajuusastioiksi. joten lähtöarvo voi olla missä tahansa määritettyjen säiliöiden sisällä.

Nopeus:

Arduino nano vaatii:

16 pistettä: 4 ms32 pistettä: 10 ms 64 pistettä: 26 ms 128 pistettä: 53 ms

Vaihe 6: Johtopäätös

Tätä FFT-koodia voidaan käyttää reaaliaikaisissa sovelluksissa. Laskun suorittaminen kestää noin 30 ms. Sen resoluutio on kuitenkin rajoitettu useilla näytteillä. Näytteen määrää rajoittaa Arduino -muisti. Käyttämällä Arduino Mega -laitetta tai muuta suorituskykyisemmän levyn tarkkuutta voidaan parantaa.

jos sinulla on kysyttävää, ehdotuksia tai korjauksia, voit kommentoida.

Päivitys (2.5.21)

Päivitykset: // ----------------------------- FFT-toiminto --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

N: n tietotyypiksi muutettiin kokonaisluku (olemassa oleva tavu), jotta otoskoko olisi> 255. Jos otoskoko on <= 128, on käytettävä tavutietotyyppiä.

Suositeltava: