Sadržaj:

EasyFFT: Brza Fourierova transformacija (FFT) za Arduino: 6 koraka
EasyFFT: Brza Fourierova transformacija (FFT) za Arduino: 6 koraka

Video: EasyFFT: Brza Fourierova transformacija (FFT) za Arduino: 6 koraka

Video: EasyFFT: Brza Fourierova transformacija (FFT) za Arduino: 6 koraka
Video: Тренинг по обучению основам дебатного искусства в форматах игр АПФ и БПФ 2024, Lipanj
Anonim
Image
Image

Mjerenje frekvencije iz snimljenog signala može biti težak zadatak, posebno na Arduinu jer ima manju računalnu snagu. Dostupne su metode za snimanje ukrštanja nulte točke pri čemu se frekvencija hvata provjeravajući koliko puta signal prelazi nultu liniju unutar zadanog vremena. Takva metoda možda neće raditi ako je signal kombinacija različitih frekvencija.

Ovo je nekako teško kodirati ako niste iz takve pozadine. No, budući da je to tinker, ovaj kôd može biti vrlo koristan za razne projekte vezane uz glazbu, analizu signala. Motiv ovog projekta bio je pripremiti kôd koji je lako implementirati na Arduinu, a da ne ulazi u njegovu pozadinu.

Ovaj projekt ne objašnjava rad FFT -a, ali objašnjava primjenu funkcije FFT. Isti proces također je objašnjen u priloženom videu.

Ako vas zanima samo primjena koda, a ne njegovo objašnjenje. Možete izravno prijeći na korak 3.

Korak 1: Uvod u frekvencijsku transformaciju

Uvod u frekvencijsku transformaciju
Uvod u frekvencijsku transformaciju
Uvod u frekvencijsku transformaciju
Uvod u frekvencijsku transformaciju

Bilo koji signal može biti sastavljen od kombinacije različitih sinusoidnih valova. Dakle, bilo koji signal temeljen na vremenu može se prikazati i kao kombinacija različitih sinusa različitih amplituda.

Pokušao sam objasniti rad DFT-a (diskretna Fourierova transformacija) u jednom od prethodnih instrukcija (https://www.instructables.com/id/Arduino-Frequency…). Ove su metode izuzetno spore za bilo koju aplikaciju u stvarnom vremenu. što ga čini gotovo beskorisnim.

Na slici je prikazan signal koji je kombinacija dviju frekvencija f2 i f5. Ovaj se signal množi s ispitnim sinusnim valovima vrijednosti od f1 do f5.

Matematički se može pokazati da -zbroj množenja dvaju harmoničkih skupova podataka s različitom frekvencijom teži nuli (veći broj podataka može dovesti do rezultata testa). U našem slučaju, ako ove dvije frekvencije množenja imaju istu (ili vrlo blisku) frekvenciju, taj zbroj množenja je broj različit od nule.

Dakle, ako se naš signal pomnoži s f1, zbroj množenja bit će nula (blizu nule za stvarnu primjenu). sličan je slučaj za f3, f4. Međutim za vrijednost, izlaz f2 i f5 neće biti nula, već znatno veći od ostalih vrijednosti.

Ovdje se signal testira s 5 frekvencija, pa se signal mora pomnožiti s pet frekvencija. Takav intenzivan izračun zahtijeva duže vrijeme. Matematički je pokazano da je za N broj uzoraka potrebno N*N složeno množenje.

Korak 2: Brza Fourierova transformacija

Kako bi izračunavanje DFT -a bilo brže, algoritam FFT razvili su James Cooley i John Tukey. Ovaj se algoritam također smatra jednim od najvažnijih algoritama 20. stoljeća. On dijeli signal na neparni i parni niz koji smanjuje broj potrebnih izračuna. Njegovom upotrebom ukupno potrebno množenje složenog sloja može se smanjiti na NlogN. što je značajno poboljšanje.

Za detaljnije razumijevanje matematike iza FFT -a možete se pozvati na dolje navedene reference koje sam spomenuo dok sam pisao kôd:

1.

2.

3.

4.

Korak 3: Objašnjenje koda

1. Brzi sinus i kosinus:

Izračun FFT uzima vrijednost različitih sinusnih i kosinusnih više puta. Ugrađena funkcija Arduina nije dovoljno brza i potrebno je dosta vremena da se osigura potrebna vrijednost. Što kôd čini znatno sporijim (udvostručuje vrijeme za 64 uzorka). Kako bi se suprotstavili ovom problemu, vrijednost sinusa za 0 do 90 stupnjeva pohranjena je kao višekratnik 255. Time ćete ukloniti potrebu za pohranjivanjem brojeva kao float, a možemo ga pohraniti i kao bajt koji zauzima 1/4 prostora na Arduinu. Sine_data mora se zalijepiti na vrh koda da bi se deklarirao kao globalna varijabla.

Osim sine_data, niz nazvan f_peaks deklariran kao globalna varijabla. Nakon svakog pokretanja funkcije FFT ovaj niz se ažurira. Gdje je f_peaks [0] najdominantnija frekvencija i daljnje vrijednosti u opadajućem redoslijedu.

bajt sinus_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];

Kako smo pohranili vrijednost sinusa za 0 do 90 stupnjeva, može se izračunati bilo koja vrijednost sinusa ili kosinusa. Ispod funkcionira prvi krug broja do nule decimalne točke i povratna vrijednost iz pohranjenih podataka. ovoj metodi je potrebna samo jedna plutajuća podjela. To se može dodatno smanjiti izravnim pohranjivanjem sinusnih vrijednosti (ne 255 višestrukih). ali to jede mnogo memorije na Arduinu.

Korištenje gornjeg postupka smanjuje točnost, ali poboljšava brzinu. Za 64 boda daje prednost od 8 ms, a za 128 bodova prednost od 20 ms.

Korak 4: Objašnjenje koda: FFT funkcija

FFT se može izvesti samo za uzorke veličine 2, 4, 8, 16, 32, 64 i tako dalje. ako vrijednost nije 2^n, tada će uzeti donju stranu vrijednosti. Na primjer, ako odaberemo veličinu uzorka 70 tada će se uzeti u obzir samo prva 64 uzorka i izostaviti ostatak.

Uvijek se preporučuje veličina uzorka 2^n. što može biti:

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

Dva plutajuća out_r i out_im zauzet će veliku količinu memorije. jer Arduino nano neće raditi za uzorke veće od 128 (au nekim slučajevima i 128) zbog nedostatka dostupne memorije.

nepotpisani int podaci [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 ++) // izračunavanje razina {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // ulaz za sekvenciranje float out_r [data [o] = {}; // stvarni dio transformacije float out_im [data [o] = {}; // imaginarni dio transformacije

Daljnji tok je sljedeći:

1. Kôd generira obrnuti redoslijed bita za datu veličinu uzorka (detalji o preokretanju bita na referencama: korak 2)

2. Ulazni podaci poredani prema generiranoj narudžbi, 3. Izvršen FFT

4. Izračunata amplituda kompleksnog broja, 5. Vrhovi se detektiraju i poredaju silaznim redoslijedom

6. rezultatima se može pristupiti iz f_peaks.

[za pristup drugim podacima (osim vršne frekvencije) kôd treba izmijeniti, tako da se lokalna varijabla može kopirati u neku unaprijed definiranu globalnu varijablu]

Korak 5: Testiranje koda

Testiranje koda
Testiranje koda
Testiranje koda
Testiranje koda

Uzorak vala trokuta dat je kao ulaz. za ovaj val frekvencija uzorkovanja je 10 Hz, a frekvencija samog vala je 1,25 Hz.

Kao što se može vidjeti iz sirovog rezultata, vrijednost se podudara s FFT -om koji je izračunao Scilab. međutim, ove vrijednosti nisu baš iste kao mi niske točnosti, ali brži sinusni val.

U izlaznom frekvencijskom nizu frekvencije su 1,25 i 3,75. nije potrebno svaki put dobiti točnu vrijednost. obično se ti brojevi nazivaju frekvencijskim spremnicima. tako da izlazna vrijednost može biti bilo gdje unutar navedenih spremnika.

Ubrzati:

za Arduino nano potrebno je:

16 bodova: 4ms32 boda: 10ms 64 boda: 26ms 128 bodova: 53ms

Korak 6: Zaključak

Ovaj FFT kod može se koristiti u aplikacijama u stvarnom vremenu. Budući da je za dovršetak izračuna potrebno oko 30 ms. Međutim, njegovo razlučivanje ograničeno je brojem uzoraka. Broj uzorka ograničen je Arduino memorijom. Korištenjem Arduino Mega ili drugih ploča poboljšane su točnosti.

ako imate bilo kakvih upita, prijedloga ili ispravki, slobodno komentirajte.

Ažuriranje (2/5/21)

Ažuriranja: // ----------------------------- FFT funkcija --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

Tip podataka N promijenjen je u Integer (postojeći bajt) kako bi podržao> 255 veličinu uzorka. Ako je veličina uzorka <= 128, treba koristiti bajtni tip podataka.

Preporučeni: