Taula de continguts:

EasyFFT: Transformada de Fourier ràpida (FFT) per Arduino: 6 passos
EasyFFT: Transformada de Fourier ràpida (FFT) per Arduino: 6 passos

Vídeo: EasyFFT: Transformada de Fourier ràpida (FFT) per Arduino: 6 passos

Vídeo: EasyFFT: Transformada de Fourier ràpida (FFT) per Arduino: 6 passos
Vídeo: QuickFFT: High Speed FFT for Arduino 2024, Setembre
Anonim
Image
Image

La mesura de la freqüència del senyal capturat pot ser una tasca difícil, especialment a Arduino, ja que té una potència de càlcul inferior. Hi ha mètodes disponibles per capturar el pas de zero en què la freqüència es capta comprovant quantes vegades el senyal creua les línies de zero en el temps donat. És possible que aquest mètode no funcioni quan el senyal és una combinació de diverses freqüències.

Això és d'alguna manera difícil de codificar si no sou d'aquests antecedents. Però en ser un pirata, aquest codi pot ser molt útil per a diversos projectes relacionats amb la música, l’anàlisi de senyals. El motiu d’aquest projecte era preparar un codi fàcil d’implementar a Arduino sense entrar en el segon pla.

Aquest projecte no explica el funcionament de FFT però explica l’aplicació de la funció FFT. El mateix procés també s’explica al vídeo adjunt.

Si només us interessa l’aplicació de codi i no una explicació del mateix. Podeu passar directament al pas núm. 3.

Pas 1: Introducció a la transformació de freqüència

Introducció a la transformació de freqüència
Introducció a la transformació de freqüència
Introducció a la transformació de freqüència
Introducció a la transformació de freqüència

Qualsevol senyal pot estar compost per una combinació de diverses ones sinusoïdals. Per tant, qualsevol senyal basat en el temps també es pot mostrar com una combinació dels diversos sinus de diferents amplituds.

Vaig intentar explicar el funcionament de DFT (transformada de Fourier discreta) en una de les instruccions anteriors (https://www.instructables.com/id/Arduino-Frequency…). Aquests mètodes són extremadament lents per a qualsevol aplicació en temps real. cosa que el fa gairebé inútil.

A la imatge, es mostra un senyal que és una combinació de dues freqüències f2 i f5. Aquest senyal es multiplica per ones sinusoïdals de prova dels valors f1 a f5.

Es pot demostrar matemàticament que -la suma de la multiplicació de dos conjunts de dades harmònics de diferent freqüència tendeix a zero (un nombre més gran de dades pot donar lloc a resultats). En el nostre cas, si aquestes dues freqüències de multiplicació tenen la mateixa (o molt propera) freqüència, la suma de multiplicació és el nombre diferent de zero.

Per tant, si el nostre senyal es multiplica per f1 la suma de la multiplicació serà zero (prop de zero per a l’aplicació real). similar és el cas de f3, f4. Tanmateix, per al valor, la sortida f2 i f5 no serà nul·la, sinó significativament superior a la resta de valors.

Aquí es prova un senyal amb 5 freqüències, de manera que cal multiplicar el senyal per cinc freqüències. Un càlcul tan intens requereix un temps superior. Matemàticament es demostra que per N nombre de mostres es necessita N * N multiplicació complexa.

Pas 2: Transformada de Fourier ràpida

Per fer el càlcul del DFT més ràpid l’algorisme FFT va ser desenvolupat per James Cooley i John Tukey. Aquest algorisme també es considera un dels algorismes més importants del segle XX. Divideix un senyal en una part seqüencial i parella que fa que els càlculs necessaris siguin inferiors. En utilitzar-lo es pot reduir la multiplicació complexa necessària total a NlogN. la qual cosa suposa una millora significativa.

A continuació, podeu consultar referències a què he fet referència mentre escrivia el codi per obtenir una comprensió detallada de les matemàtiques darrere de FFT:

1.

2.

3.

4.

Pas 3: explicació del codi

1. Senus ràpid i cosinus:

El càlcul FFT pren el valor de diversos sinus i cosinus diverses vegades. La funció incorporada d'Arduino no és prou ràpida i triga una bona quantitat de temps a proporcionar el valor requerit. La qual cosa fa que el codi sigui molt més lent (es duplica el temps per a 64 mostres). Per contrarestar aquest problema, el valor de sinus entre 0 i 90 graus s'emmagatzema com a múltiple de 255. Si ho feu, s'eliminarà la necessitat d'utilitzar els números d'emmagatzematge com a flotant i el podem emmagatzemar com a byte que ocupa 1 / 4a espai a Arduino. La sine_data ha d’enganxar-se a la part superior del codi per declarar-la com a variable global.

A part de sine_data, una matriu anomenada f_peaks declarada com a variable global. Després de cada execució de la funció FFT, aquesta matriu s'actualitza. On f_peaks [0] és la freqüència més dominant i altres valors en ordre descendent.

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

Com hem emmagatzemat el valor de sinus entre 0 i 90 graus, es pot calcular qualsevol valor de sinus o cosinus. A continuació funciona la primera ronda del número a punt decimal i torna el valor de les dades emmagatzemades. aquest mètode només necessita una divisió flotant. Això es pot reduir encara més emmagatzemant directament valors sinusals (no 255 múltiples). però això consumeix molta memòria a Arduino.

L’ús del procediment anterior redueix la precisió però millora la velocitat. Per a 64 punts, dóna l'avantatge de 8 ms i per a 128 punts, proporciona un avantatge de 20 ms.

Pas 4: Explicació del codi: funció FFT

FFT només es pot realitzar per a la mida de la mostra de 2, 4, 8, 16, 32, 64, etc. si el valor no és 2 ^ n, tindrà la part inferior del valor. Per exemple, si escollim la mida de la mostra de 70, només considerarà les primeres 64 mostres i ometrà la resta.

Sempre es recomana tenir una mida de mostra de 2 ^ n. que pot ser:

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

Dos flotadors out_r i out_im ocuparan una gran quantitat de memòria. per Arduino nano no funcionarà per a mostres superiors a 128 (i en alguns casos 128) a causa de la manca de memòria disponible.

dades int sense signar [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 ++) // calculant els nivells {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // entrada per seqüenciar float out_r [dades [o] = {}; // part real de la transformació float out_im [dades [o] = {}; // part imaginària de transformar

El flux addicional és el següent:

1. El codi genera un ordre inversat una mica per a la mida de mostra donada (detalls sobre la reversió de bits a les referències: pas 2)

2. Dades d'entrada ordenades segons la comanda generada, 3. FFT realitzat

4. L’amplitud del nombre complex calculat, 5. Els pics es detecten i s’ordenen en ordre descendent

6. es pot accedir als resultats des de f_peaks.

[per accedir a altres dades (a part de la freqüència màxima) s'ha de modificar el codi, de manera que la variable local es pugui copiar a alguna variable global predefinida]

Pas 5: provar el codi

Prova del codi
Prova del codi
Prova del codi
Prova del codi

Es dóna com a entrada una ona triangular de mostra. per a aquesta ona, la freqüència de mostreig és de 10 Hz i la freqüència de l'ona mateixa és d'1,25 Hz.

Com es pot demostrar a la sortida bruta, el valor coincideix amb el FFT calculat per Scilab. tanmateix, aquests valors no són exactament els mateixos que els de baixa precisió, sinó l'ona sinusoïdal més ràpida.

A la freqüència de sortida, la freqüència de la matriu és de 1,25 i 3,75. no cal obtenir el valor exacte cada vegada. normalment aquests números es diuen papereres de freqüència. de manera que el valor de sortida podria estar a qualsevol lloc dins dels contenidors especificats.

Velocitat:

per a Arduino nano es necessita:

16 punts: 4 ms 32 punts: 10 ms 64 punts: 26 ms 128 punts: 53 ms

Pas 6: Conclusió

Aquest codi FFT es pot utilitzar en aplicacions en temps real. Ja que triga uns 30 ms en completar el càlcul. No obstant això, la seva resolució està limitada per diverses mostres. El nombre de la mostra està limitat per la memòria Arduino. Mitjançant l’ús d’Arduino Mega o amb una altra placa es pot millorar la precisió de la placa.

si teniu cap pregunta, suggeriment o correcció, no dubteu a fer comentaris.

Actualització (21/02/21)

Actualitzacions: // ----------------------------- Funció FFT --------------- ------------------------------- // float FFT (int a , int N, freqüència flotant)

El tipus de dades de N ha canviat a Integer (Byte existent) per admetre una mida de mostra> 255. Si la mida de la mostra és <= 128, s'ha d'utilitzar el tipus de dades de bytes.

Recomanat: