Tartalomjegyzék:

EasyFFT: Gyors Fourier -transzformáció (FFT) Arduino számára: 6 lépés
EasyFFT: Gyors Fourier -transzformáció (FFT) Arduino számára: 6 lépés

Videó: EasyFFT: Gyors Fourier -transzformáció (FFT) Arduino számára: 6 lépés

Videó: EasyFFT: Gyors Fourier -transzformáció (FFT) Arduino számára: 6 lépés
Videó: QuickFFT: High Speed FFT for Arduino 2024, November
Anonim
Image
Image

A rögzített jel frekvenciájának mérése nehéz feladat lehet, különösen az Arduino esetében, mivel alacsonyabb a számítási teljesítménye. Vannak módszerek a nulla-keresztezés rögzítésére, ahol a frekvenciát úgy rögzítik, hogy ellenőrzik, hogy a jel hányszor lépi át a nulla vonalakat az adott időn belül. Ez a módszer nem működik, ha a jel különböző frekvenciák kombinációja.

Ezt valahogy nehéz kódolni, ha nem ilyen hátterű vagy. De barkácsoló lévén ez a kód nagyon hasznos lehet a zenével, a jelméréssel kapcsolatos különféle projekteknél. Ennek a projektnek az volt az indítéka, hogy készítsen egy kódot, amely könnyen megvalósítható az Arduino -n anélkül, hogy a háttérbe kerülne.

Ez a projekt nem az FFT működését magyarázza, hanem az FFT függvény alkalmazását. Ugyanezt a folyamatot a mellékelt videó is ismerteti.

Ha csak a kód alkalmazása érdekli, nem pedig annak magyarázata. Ugorhat közvetlenül a 3. lépésre.

1. lépés: Bevezetés a frekvenciaátalakításba

Bevezetés a frekvenciaátalakításba
Bevezetés a frekvenciaátalakításba
Bevezetés a frekvenciaátalakításba
Bevezetés a frekvenciaátalakításba

Bármely jel különböző szinuszos hullámok kombinációjából állhat össze. Tehát minden időalapú jel a különböző amplitúdójú szinuszok kombinációjaként is megjeleníthető.

Megpróbáltam elmagyarázni a DFT (diszkrét Fourier-transzformáció) működését az egyik előző utasításban (https://www.instructables.com/id/Arduino-Frequency…). Ezek a módszerek rendkívül lassúak bármilyen valós idejű alkalmazás esetén. ami szinte használhatatlanná teszi.

A képen egy jel látható, amely két f2 és f5 frekvencia kombinációja. Ezt a jelet megszorozzák az f1 – f5 értékű szinuszhullámokkal.

Matematikailag kimutatható, hogy két különböző frekvenciájú harmonikus adathalmaz szorzatának összeadása nullára hajlik (a nagyobb számú adat tésztaeredményhez vezethet). Esetünkben, ha ennek a két szorzási frekvenciának azonos (vagy nagyon közel) gyakorisága van, akkor a szorzás összege a nullától eltérő szám.

Tehát ha a jelünket megszorozzuk f1 -gyel, akkor a szorzás összegzése nulla lesz (valós alkalmazás esetén nulla közelében). hasonló a helyzet az f3, f4 esetében is. Az érték esetén azonban az f2 és f5 kimenet nem lesz nulla, de jelentősen magasabb, mint a többi érték.

Itt egy jelet 5 frekvenciával tesztelnek, ezért a jelet meg kell szorozni öt frekvenciával. Egy ilyen intenzív számítás hosszabb időt vesz igénybe. Matematikailag kimutatható, hogy N mintaszámhoz N*N komplex szorzás szükséges.

2. lépés: Gyors Fourier -transzformáció

A DFT gyorsabb kiszámítása érdekében James Cooley és John Tukey kifejlesztették az FFT algoritmust. Ezt az algoritmust a 20. század egyik legfontosabb algoritmusának is tekintik. A jel egy páratlan és páros szekvenciájú részre oszlik, ami számos szükséges számítást lecsökkent. Használatával a teljes szükséges komplex szorzás NlogN -re csökkenthető. ami jelentős javulás.

Az FFT mögötti matematika részletes megértéséhez hivatkozhat az alábbi hivatkozásokra, amelyekre a kód írásakor hivatkoztam:

1.

2.

3.

4.

3. lépés: A kód magyarázata

1. Gyors szinusz és koszinusz:

Számítás Az FFT többszörösei a különböző szinuszok és koszinuszok értékét. Az Arduino beépített funkciója nem elég gyors, és jó időbe telik a szükséges érték megadásához. Ez jelentősen lelassítja a kódot (megduplázza az időt 64 mintánál). Ennek a problémának a kiküszöbölésére a szinusz értéke 0 és 90 fok között 255 -ös többszöröseként kerül tárolásra. Ha így tesz, megszűnik a számok tárolásának úszóként való használata, és tárolhatjuk byte -ként, ami 1/4 helyet foglal el az Arduino -n. A sine_data -nak be kell illesztenie a kód tetejére, hogy globális változónak nyilvánítsa.

A sine_data -n kívül az f_peaks nevű tömb globális változóként deklarált. Az FFT funkció minden futtatása után ez a tömb frissül. Ahol az f_csúcsok [0] a domináns gyakoriság és a további értékek csökkenő sorrendben.

bájt 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];

Mivel a szinusz értékét 0 és 90 fok között tároltuk, a szinusz vagy a koszinusz bármely értéke kiszámítható. Az alábbi funkció a szám első fordulóját tizedesjegyig nullára adja, és visszaadja az értéket a tárolt adatokból. ez a módszer csak egy lebegő felosztást igényel. Ez tovább csökkenthető a szinuszértékek közvetlen tárolásával (nem 255 többszörös). de ez felfalja az Arduino memóriáját.

A fenti eljárás alkalmazása csökkenti a pontosságot, de javítja a sebességet. 64 pontért 8 ms, 128 pontért 20 ms előnyt biztosít.

4. lépés: A kód magyarázata: FFT függvény

Az FFT csak a minta 2, 4, 8, 16, 32, 64 és így tovább végrehajtható. ha az érték nem 2^n, akkor az érték alsó oldalát veszi fel. Például, ha a 70 -es minta méretét választjuk, akkor az csak az első 64 mintát veszi figyelembe, és kihagyja a többi részt.

Mindig ajánlott, hogy a minta mérete 2^n legyen. Melyik lehet:

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

Két float out_r és out_im nagy mennyiségű memóriát vesz igénybe. az Arduino esetében a nano nem fog működni 128 (és egyes esetekben 128) -nál magasabb minták esetén a rendelkezésre álló memória hiánya miatt.

előjel nélküli int adatok [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 ++) // a szintek kiszámítása {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // bemenet a szekvenáláshoz float out_r [adatok [o] = {}; // a transzformáció valós része float out_im [adatok [o] = {}; // az átalakítás képzeleti része

A további áramlás a következő:

1. A kód egy kicsit megfordított sorrendet generál az adott minta méretéhez (részletek a bitfordításról a hivatkozásokon: 2. lépés)

2. A generált sorrend szerint megrendelt bemeneti adatok, 3. FFT végrehajtva

4. A számított komplex szám amplitúdója, 5. A csúcsokat csökkenő sorrendben észleli és rendezi

6. az eredmények az f_peaks oldalról érhetők el.

[más adatok eléréséhez (a csúcsfrekvencia kivételével) a kódot módosítani kell, hogy a helyi változó átmásolható legyen valamely előre meghatározott globális változóba]

5. lépés: A kód tesztelése

A kódex tesztelése
A kódex tesztelése
A kódex tesztelése
A kódex tesztelése

Bemenetként egy minta háromszög hullámot adunk meg. ehhez a hullám mintavételi frekvenciája 10 Hz, maga a hullám frekvenciája pedig 1,25 Hz.

Amint a nyers kimenetből látható, az érték megegyezik a Scilab által kiszámított FFT -vel. ezek az értékek azonban nem pontosan ugyanazok, mint az alacsony pontosságú, de gyorsabb szinuszhullám.

A kimeneti frekvencia tömb frekvenciája 1,25 és 3,75. nem szükséges minden alkalommal pontos értéket kapni. ezeket a számokat általában frekvenciatartályoknak nevezik. így a kimeneti érték bárhol lehet a megadott tartályokon belül.

Sebesség:

az Arduino nano esetében:

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

6. lépés: Következtetés

Ez az FFT kód valós idejű alkalmazásokban használható. Mivel a számítás befejezése körülbelül 30 ms -ot vesz igénybe. A felbontását azonban számos minta korlátozza. A minta számát az Arduino memória korlátozza. Az Arduino Mega vagy más nagyobb teljesítményű tábla pontossága javítható.

ha bármilyen kérdése, javaslata vagy javítása van, írjon megjegyzést.

Frissítés (2/5/21)

Frissítések: // ----------------------------- FFT funkció --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

Az N adattípusa Integer (meglévő bájt) értékre változott, hogy támogassa a> 255 mintaméretet. Ha a minta mérete <= 128, akkor bájt adattípust kell használni.

Ajánlott: