Sisukord:

EasyFFT: kiire Fourier 'teisendus (FFT) Arduino jaoks: 6 sammu
EasyFFT: kiire Fourier 'teisendus (FFT) Arduino jaoks: 6 sammu

Video: EasyFFT: kiire Fourier 'teisendus (FFT) Arduino jaoks: 6 sammu

Video: EasyFFT: kiire Fourier 'teisendus (FFT) Arduino jaoks: 6 sammu
Video: Arducopter на гоночном квадрокоптере. Это вам не INAV! Часть первая. Базовая настройка 2024, September
Anonim
Image
Image

Sageduse mõõtmine salvestatud signaalist võib olla keeruline ülesanne, eriti Arduino puhul, kuna sellel on väiksem arvutusvõimsus. Nullpunkti jäädvustamiseks on saadaval meetodeid, kus sagedust püütakse kontrollida, kontrollides, mitu korda signaal antud aja jooksul nulljooni ületab. Selline meetod ei pruugi töötada, kui signaal on erinevate sageduste kombinatsioon.

Seda on kuidagi raske kodeerida, kui te pole sellisest taustast pärit. Kuid näppijana võib see kood olla väga kasulik erinevate muusika- ja signaalianalüüsiga seotud projektide jaoks. Selle projekti motiiv oli valmistada ette kood, mida on lihtne Arduinole rakendada ilma selle taustale sattumata.

See projekt ei selgita FFT toimimist, vaid selgitab FFT funktsiooni rakendamist. Sama protsessi selgitatakse ka lisatud videos.

Kui olete huvitatud ainult koodi rakendamisest ja mitte selle selgitusest. Võite minna otse sammu nr 3 juurde.

1. samm: sissejuhatus sagedusmuundamisse

Sissejuhatus sagedusmuundamisse
Sissejuhatus sagedusmuundamisse
Sissejuhatus sagedusmuundamisse
Sissejuhatus sagedusmuundamisse

Iga signaal võib koosneda erinevate siinuslainete kombinatsioonist. Seega saab mis tahes ajapõhist signaali näidata ka erinevate amplituudide erinevate siinuste kombinatsioonina.

Üritasin selgitada DFT (diskreetne Fourier 'teisendus) toimimist ühes eelmistest juhenditest (https://www.instructables.com/id/Arduino-Frequency…). Need meetodid on reaalajas rakenduste jaoks äärmiselt aeglased. mis muudab selle peaaegu kasutuks.

Pildil on näidatud signaal, mis koosneb kahest sagedusest f2 ja f5. See signaal korrutatakse väärtuste f1 kuni f5 katse siinuslainetega.

Matemaatiliselt saab näidata, et kahe erineva sagedusega harmoonilise andmekogumi korrutamise kokkuvõte kaldub nulli (suurem andmete arv võib viia taigna tulemuseni). Meie puhul, kui neil kahel korrutussagedusel on sama (või väga lähedane) sagedus, on korrutussumma nullist erinev arv.

Seega, kui meie signaal korrutatakse f1 -ga, on korrutamine korrutamine null (reaalse rakenduse korral nullilähedane). sama on ka f3, f4 puhul. Kuid väärtuse puhul ei ole f2 ja f5 väljund null, vaid oluliselt suurem kui ülejäänud väärtused.

Siin testitakse signaali 5 sagedusega, seega tuleb signaal korrutada viie sagedusega. Selline intensiivne arvutamine võtab rohkem aega. Matemaatiliselt on näidatud, et N proovide arvu jaoks kulub N*N komplekskorrutamine.

2. samm: kiire Fourier -teisendus

DFT arvutamise kiirendamiseks töötasid James Cooley ja John Tukey välja FFT algoritmi. Seda algoritmi peetakse ka üheks 20. sajandi olulisemaks algoritmiks. See jagab signaali paaritu ja paaritu sektsiooniks, mis vähendab mitmeid nõutavaid arvutusi. Seda kasutades saab kogu vajaliku keerulise korrutamise vähendada NlogN -ni. mis on märkimisväärne paranemine.

FFT taga oleva matemaatika üksikasjalikuks mõistmiseks võite viidata allpool viidetele, millele viitasin koodi kirjutamise ajal:

1.

2.

3.

4.

3. samm: koodi selgitamine

1. Kiire siinus ja koosinus:

Arvutamine FFT võtab erinevate siinuste ja koosinususte väärtuse mitu korda. Arduino sisseehitatud funktsioon ei ole piisavalt kiire ja võtab vajaliku väärtuse andmiseks palju aega. Mis muudab koodi oluliselt aeglasemaks (64 proovi puhul kahekordistub aeg). Selle probleemi lahendamiseks salvestatakse siinuse väärtus 0 kuni 90 kraadi juures kordajana 255. Seda tehes kaob vajadus numbrite salvestamiseks ujukina ja saame selle salvestada baitidena, mis võtab Arduinole 1/4 ruumi. Sine_data tuleb kleepida koodi ülaossa, et kuulutada see globaalseks muutujaks.

Peale sine_data deklareeriti massiiv nimega f_peaks globaalse muutujana. Pärast iga FFT -funktsiooni käivitamist seda massiivi värskendatakse. Kus f_peaks [0] on kõige domineerivam sagedus ja edasised väärtused kahanevas järjekorras.

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

Kuna siinuse väärtus on salvestatud 0 kuni 90 kraadi, saab arvutada mis tahes siinuse või koosinuse väärtuse. Allpool on funktsiooni esimene voor numbrikohani pärast koma ja tagastatakse salvestatud andmete väärtus. see meetod vajab ainult ühte ujuvjaotust. Seda saab veelgi vähendada siinusväärtuste (mitte 255 mitmekordse) salvestamisega. kuid see sööb Arduino kõrge mälu.

Ülaltoodud protseduuri kasutamine vähendab täpsust, kuid parandab kiirust. 64 punkti eest annab see eelise 8 ms ja 128 punkti puhul 20 ms.

4. samm: koodi selgitus: FFT -funktsioon

FFT -d saab teha ainult valimi suurusega 2, 4, 8, 16, 32, 64 ja nii edasi. kui väärtus ei ole 2^n, siis võtab see väärtuse alumise külje. Näiteks kui valime valimi suuruseks 70, võtab see arvesse ainult 64 esimest proovi ja jätab ülejäänud välja.

Valimi suurus on alati soovitatav 2^n. mis võib olla:

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

Kaks ujukit out_r ja out_im võtavad palju mälu. Arduino jaoks nano ei tööta saadaolevate mälu puudumise tõttu proovide puhul, mis on suuremad kui 128 (ja mõnel juhul 128).

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

int a, c1, f, o, x; a = N; jaoks (int i = 0; i <12; i ++) // tasemete arvutamiseks {if (andmed <= a) {o = i;}} int in_ps [andmed [o] = {}; // sisend järjestamiseks float out_r [andmed [o] = {}; // tegelik osa teisendusest float out_im [andmed [o] = {}; // kujuteldav osa teisendusest

Edasine voog on järgmine:

1. Kood genereerib antud valimi suuruse jaoks natuke vastupidise järjekorra (üksikasjad bittide tagasipööramise kohta viidetel: samm 2)

2. Sisestatud andmed on tellitud vastavalt genereeritud tellimusele, 3. FFT teostatud

4. Arvutatud kompleksarvu amplituud, 5. Piigid tuvastatakse ja järjestatakse kahanevas järjekorras

6. Tulemustele pääseb ligi aadressilt f_peaks.

[muudele andmetele (peale tippsageduse) juurdepääsemiseks tuleks koodi muuta, et kohalikku muutujat saaks kopeerida mõnele eelnevalt määratletud globaalsele muutujale]

Samm: koodi testimine

Koodeksi testimine
Koodeksi testimine
Koodeksi testimine
Koodeksi testimine

Sisendiks on näidis kolmnurga laine. selle laine proovivõtu sagedus on 10 Hz ja laine sagedus on 1,25 Hz.

Nagu toortoodangust võib näha, on väärtus vastavuses Scilabi arvutatud FFT -ga. need väärtused pole aga täpselt samad, mis meil madala täpsusega, vaid kiirem siinuslaine.

Väljundsageduse massiivi sagedus on 1,25 ja 3,75. pole vaja iga kord täpset väärtust saada. tavaliselt nimetatakse neid numbreid sageduskaustadeks. seega võib väljundväärtus olla ükskõik kus määratud prügikastide piires.

Kiirus:

Arduino nano jaoks kulub:

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

6. samm: järeldus

Seda FFT-koodi saab kasutada reaalajas rakendustes. Kuna arvutuse lõpuleviimiseks kulub umbes 30 ms. Selle eraldusvõime on aga piiratud mitmete proovidega. Proovi arvu piirab Arduino mälu. Arduino Mega või mõne muu suurema jõudlusega plaadi täpsust saab parandada.

kui teil on küsimusi, ettepanekuid või parandusi, kommenteerige.

Värskendus (2/5/21)

Uuendused: // ----------------------------- FFT-funktsioon --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

N andmetüüp muudeti täisarvuks (olemasolev bait), et toetada> 255 valimi suurust. Kui valimi suurus on <= 128, tuleks kasutada baidi andmetüüpi.

Soovitan: