Table des matières:

EasyFFT : Transformée de Fourier rapide (FFT) pour Arduino : 6 étapes
EasyFFT : Transformée de Fourier rapide (FFT) pour Arduino : 6 étapes

Vidéo: EasyFFT : Transformée de Fourier rapide (FFT) pour Arduino : 6 étapes

Vidéo: EasyFFT : Transformée de Fourier rapide (FFT) pour Arduino : 6 étapes
Vidéo: FFT d'un signal périodique 2024, Septembre
Anonim
Image
Image

La mesure de la fréquence à partir du signal capturé peut être une tâche difficile, en particulier sur Arduino car il a une puissance de calcul plus faible. Il existe des méthodes disponibles pour capturer le passage par zéro où la fréquence est capturée en vérifiant combien de fois le signal traverse les lignes zéro dans le temps donné. Une telle méthode peut ne pas fonctionner lorsque le signal est une combinaison de différentes fréquences.

C'est en quelque sorte difficile à coder si vous n'êtes pas issu d'un tel contexte. Mais étant un bricoleur, ce code peut être très utile pour divers projets liés à la musique, à l'analyse du signal. Le motif de ce projet était de préparer un code facile à implémenter sur Arduino sans entrer dans le fond.

Ce projet n'explique pas le fonctionnement de FFT mais explique l'application de la fonction FFT. Le même processus est également expliqué dans la vidéo ci-jointe.

Si vous n'êtes intéressé que par l'application du code et non par une explication de celui-ci. Vous pouvez passer directement à l'étape n° 3.

Étape 1: Introduction à la transformation de fréquence

Introduction à la transformation de fréquence
Introduction à la transformation de fréquence
Introduction à la transformation de fréquence
Introduction à la transformation de fréquence

Tout signal peut être composé d'une combinaison de diverses ondes sinusoïdales. Ainsi, tout signal basé sur le temps peut également être représenté comme une combinaison des divers sinus de différentes amplitudes.

J'ai essayé d'expliquer le fonctionnement de DFT (transformée de Fourier discrète) dans l'un des précédents instructables (https://www.instructables.com/id/Arduino-Frequency…). Ces méthodes sont extrêmement lentes pour toute application en temps réel. ce qui le rend presque inutile.

Dans l'image, un signal est montré qui est une combinaison de deux fréquences f2 et f5. Ce signal est multiplié par des ondes sinusoïdales de test de valeurs f1 à f5.

Il peut être démontré mathématiquement que la sommation de la multiplication de deux ensembles de données harmoniques ayant une fréquence différente tend vers zéro (un nombre plus élevé de données peut conduire à un résultat de battement). Dans notre cas, si ces deux fréquences de multiplication ont la même fréquence (ou très proche) cette somme de multiplication est le nombre différent de zéro.

Donc, si notre signal est multiplié par f1, la somme de la multiplication sera nulle (proche de zéro pour une application réelle). c'est pareil pour f3, f4. Cependant, pour la valeur, les sorties f2 et f5 ne seront pas nulles, mais nettement supérieures au reste des valeurs.

Ici, un signal est testé avec 5 fréquences, le signal doit donc être multiplié par cinq fréquences. Un calcul aussi intense prend plus de temps. Mathématiquement, il est montré que pour un nombre N d'échantillons, il faut N*N multiplication complexe.

Étape 2: Transformée de Fourier rapide

Pour rendre le calcul de DFT plus rapide, l'algorithme FFT a été développé par James Cooley et John Tukey. Cet algorithme est également considéré comme l'un des algorithmes les plus importants du 20e siècle. Il divise un signal en une partie séquencée impaire et paire, ce qui réduit le nombre de calculs requis. En l'utilisant, la multiplication complexe totale requise peut être réduite à NlogN. ce qui est une amélioration significative.

Vous pouvez vous référer aux références ci-dessous auxquelles j'ai fait référence lors de l'écriture du code pour une compréhension détaillée des mathématiques derrière FFT:

1.

2.

3.

4.

Étape 3: Explication du code

1. Sinus et cosinus rapides:

Le calcul FFT prend plusieurs fois la valeur de divers sinus et cosinus. La fonction intégrée d'Arduino n'est pas assez rapide et prend beaucoup de temps pour fournir la valeur requise. Ce qui rend le code considérablement plus lent (double le temps pour 64 échantillons). Pour contrer ce problème, la valeur du sinus de 0 à 90 degrés est stockée sous forme de multiple de 255. Cela éliminera le besoin d'utiliser le stockage de nombres comme flottant et nous pouvons le stocker sous forme d'octet qui prend 1/4 d'espace sur Arduino. Le sine_data doit être collé en haut du code pour le déclarer en tant que variable globale.

En dehors de sine_data, un tableau appelé f_peaks déclaré comme variable globale. Après chaque exécution de la fonction FFT, ce tableau est mis à jour. Où f_peaks[0] est la fréquence la plus dominante et les autres valeurs par ordre décroissant.

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

Comme nous avons stocké la valeur du sinus de 0 à 90 degrés, toute valeur de sinus ou de cosinus peut être calculée. Ci-dessous, la fonction du premier tour du nombre à zéro virgule décimale et la valeur de retour à partir des données stockées. cette méthode n'a besoin que d'une division flottante. Cela peut être encore réduit en stockant directement les valeurs sinus (pas 255 multiples). mais cela consomme beaucoup de mémoire sur Arduino.

L'utilisation de la procédure ci-dessus réduit la précision mais améliore la vitesse. Pour 64 points, il donne l'avantage de 8ms et pour 128 points il donne un avantage de 20ms.

Étape 4: Explication du code: Fonction FFT

La FFT ne peut être effectuée que pour la taille d'échantillon de 2, 4, 8, 16, 32, 64 et ainsi de suite. si la valeur n'est pas 2^n, alors il prendra le côté inférieur de la valeur. Par exemple, si nous choisissons la taille d'échantillon de 70, il ne considérera que les 64 premiers échantillons et omettra le reste.

Il est toujours recommandé d'avoir une taille d'échantillon de 2^n. qui peut être:

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

Deux flottants out_r et out_im prendront une grande quantité de mémoire. pour Arduino nano ne fonctionnera pas pour les échantillons supérieurs à 128 (et dans certains cas 128) en raison du manque de mémoire disponible.

données int non signées[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++) //calcul des niveaux { if(data<=a){o=i;} } int in_ps[data[o]={}; //entrée pour le séquençage float out_r[data[o]={}; //partie réelle de la transformation float out_im[data[o]={}; //partie imaginaire de la transformation

Le flux supplémentaire est le suivant:

1. Le code génère un ordre un peu inversé pour la taille d'échantillon donnée (détails sur l'inversion des bits sur les références: étape 2)

2. Saisir les données commandées selon la commande générée, 3. FFT effectuée

4. L'amplitude du nombre complexe calculé, 5. Les pics sont détectés et classés par ordre décroissant

6. les résultats sont accessibles à partir de f_peaks.

[pour accéder à d'autres données (en dehors de la fréquence de crête) le code doit être modifié, de sorte que la variable locale puisse être copiée dans une variable globale prédéfinie]

Étape 5: Tester le code

Tester le code
Tester le code
Tester le code
Tester le code

Un exemple d'onde triangulaire est donné en entrée. pour cette fréquence d'échantillonnage d'onde est de 10 Hz et la fréquence de l'onde elle-même est de 1,25 Hz.

Comme le montre la sortie brute, la valeur correspond à la FFT calculée par Scilab. Cependant, ces valeurs ne sont pas exactement les mêmes que celles d'une onde sinusoïdale de faible précision mais plus rapide.

Dans la fréquence de sortie, la fréquence du tableau est de 1,25 et 3,75. il n'est pas nécessaire d'obtenir la valeur exacte à chaque fois. généralement, ces nombres sont appelés groupes de fréquences. la valeur de sortie peut donc se trouver n'importe où dans les bacs spécifiés.

La vitesse:

pour Arduino nano il faut:

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

Étape 6: Conclusion

Ce code FFT peut être utilisé dans des applications temps réel. Comme il faut environ 30 ms pour terminer le calcul. Cependant, sa résolution limitée par un certain nombre d'échantillons. Le nombre d'échantillons est limité par la mémoire Arduino. En utilisant Arduino Mega ou une autre carte plus performante, la précision peut être améliorée.

si vous avez des questions, des suggestions ou des corrections, n'hésitez pas à commenter.

Mise à jour (2/5/21)

Mises à jour://-----------------------------Fonction FFT--------------- -------------------------------//float FFT(int in, int N, float Fréquence)

Le type de données de N est passé à Entier (octet existant) pour prendre en charge une taille d'échantillon > 255. Si la taille de l'échantillon est <=128, le type de données octet doit être utilisé.

Conseillé: