Πίνακας περιεχομένων:

EasyFFT: Fast Fourier Transform (FFT) για Arduino: 6 βήματα
EasyFFT: Fast Fourier Transform (FFT) για Arduino: 6 βήματα

Βίντεο: EasyFFT: Fast Fourier Transform (FFT) για Arduino: 6 βήματα

Βίντεο: EasyFFT: Fast Fourier Transform (FFT) για Arduino: 6 βήματα
Βίντεο: ΤΑΧΥΣ ΜΕΤΑΣΧΗΜΑΤΙΣΜΟΣ FOURIER 2024, Νοέμβριος
Anonim
Image
Image

Η μέτρηση της συχνότητας από το σήμα που έχει ληφθεί μπορεί να είναι μια δύσκολη εργασία, ειδικά στο Arduino καθώς έχει χαμηλότερη υπολογιστική ισχύ. Υπάρχουν διαθέσιμες μέθοδοι για τη λήψη μηδενικής διέλευσης όπου η συχνότητα καταγράφεται ελέγχοντας πόσες φορές το σήμα διασχίζει μηδενικές γραμμές εντός του δεδομένου χρόνου. Μια τέτοια μέθοδος μπορεί να μην λειτουργεί όταν το σήμα είναι ένας συνδυασμός διαφόρων συχνοτήτων.

Αυτό είναι κατά κάποιο τρόπο δύσκολο να κωδικοποιηθεί εάν δεν είστε από τέτοιο υπόβαθρο. Όμως, ως τσιγκούνης αυτός ο κώδικας μπορεί να είναι ιδιαίτερα χρήσιμος για διάφορα έργα που σχετίζονται με τη μουσική, την ανάλυση σήματος. Το κίνητρο αυτού του έργου ήταν να προετοιμάσει έναν κώδικα που είναι εύκολο να εφαρμοστεί στο Arduino χωρίς να μπει στο παρασκήνιο του.

Αυτό το έργο δεν εξηγεί τη λειτουργία του FFT αλλά εξηγεί την εφαρμογή της συνάρτησης FFT. Η ίδια διαδικασία εξηγείται επίσης στο συνημμένο βίντεο.

Εάν ενδιαφέρεστε μόνο για την εφαρμογή του κώδικα και όχι για μια εξήγησή του. Μπορείτε να μεταβείτε απευθείας στο βήμα 3.

Βήμα 1: Εισαγωγή στον μετασχηματισμό συχνότητας

Εισαγωγή στον μετασχηματισμό συχνότητας
Εισαγωγή στον μετασχηματισμό συχνότητας
Εισαγωγή στον μετασχηματισμό συχνότητας
Εισαγωγή στον μετασχηματισμό συχνότητας

Κάθε σήμα μπορεί να αποτελείται από ένα συνδυασμό διαφόρων ημιτονοειδών κυμάτων. Έτσι, κάθε σήμα που βασίζεται στο χρόνο μπορεί επίσης να εμφανιστεί ως ένας συνδυασμός των διαφόρων ημιτόνων με διαφορετικά πλάτη.

Προσπάθησα να εξηγήσω τη λειτουργία του DFT (διακριτός μετασχηματισμός Fourier) σε ένα από τα προηγούμενα εκπαιδευτικά (https://www.instructables.com/id/Arduino-Frequency…). Αυτές οι μέθοδοι είναι εξαιρετικά αργές για κάθε εφαρμογή σε πραγματικό χρόνο. που το καθιστά σχεδόν άχρηστο.

Στην εικόνα, εμφανίζεται ένα σήμα που είναι ένας συνδυασμός δύο συχνοτήτων f2 και f5. Αυτό το σήμα πολλαπλασιάζεται με ημιτονοειδή κύματα τιμών f1 έως f5.

Μπορεί να αποδειχθεί μαθηματικά ότι -το άθροισμα του πολλαπλασιασμού δύο αρμονικών συνόλων δεδομένων με διαφορετική συχνότητα τείνει στο μηδέν (υψηλότερος αριθμός δεδομένων μπορεί να οδηγήσει σε αποτέλεσμα ζύμωσης). Στην περίπτωσή μας, εάν αυτές οι δύο συχνότητες πολλαπλασιασμού έχουν την ίδια (ή πολύ κοντινή) συχνότητα, το άθροισμα του πολλαπλασιασμού είναι ο μη μηδενικός αριθμός.

Έτσι, εάν το σήμα μας πολλαπλασιαστεί με f1, το άθροισμα του πολλαπλασιασμού θα είναι μηδέν (κοντά στο μηδέν για πραγματική εφαρμογή). Παρόμοια είναι η περίπτωση για f3, f4. Ωστόσο, για την τιμή, η έξοδος f2 και f5 δεν θα είναι μηδέν, αλλά σημαντικά υψηλότερη από τις υπόλοιπες τιμές.

Εδώ ένα σήμα δοκιμάζεται με 5 συχνότητες, οπότε το σήμα πρέπει να πολλαπλασιαστεί με πέντε συχνότητες. Ένας τέτοιος έντονος υπολογισμός απαιτεί μεγαλύτερο χρόνο. Μαθηματικά αποδεικνύεται ότι για Ν αριθμό δειγμάτων χρειάζεται πολλαπλασιασμός συμπλόκου Ν*Ν.

Βήμα 2: Γρήγορος μετασχηματισμός Fourier

Για να γίνει ο υπολογισμός του DFT γρηγορότερος αλγόριθμος FFT αναπτύχθηκε από τους James Cooley και John Tukey. Αυτός ο αλγόριθμος θεωρείται επίσης ένας από τους σημαντικότερους αλγόριθμους του 20ού αιώνα. Χωρίζει ένα σήμα σε ένα περιττό και ζυγό ακολουθία που μειώνει τον αριθμό των απαιτούμενων υπολογισμών. Με τη χρήση του, ο συνολικός απαιτούμενος πολύπλοκος πολλαπλασιασμός μπορεί να μειωθεί σε NlogN. που αποτελεί σημαντική βελτίωση.

Μπορείτε να ανατρέξετε στις παρακάτω αναφορές στις οποίες αναφέρθηκα κατά τη σύνταξη του κώδικα για λεπτομερή κατανόηση των μαθηματικών πίσω από το FFT:

1.

2.

3.

4.

Βήμα 3: Επεξήγηση του κώδικα

1. Fast sine and Cosine:

Υπολογισμός FFT λαμβάνει την τιμή διαφόρων ημιτόνων και συνημίτονων πολλές φορές. Η ενσωματωμένη λειτουργία του Arduino δεν είναι αρκετά γρήγορη και χρειάζεται πολύς χρόνος για να παρέχει την απαιτούμενη τιμή. Αυτό καθιστά τον κώδικα σημαντικά πιο αργό (διπλασιάζει το χρόνο για 64 δείγματα). Για την αντιμετώπιση αυτού του ζητήματος η τιμή του ημιτόνου για 0 έως 90 μοίρες αποθηκεύεται ως πολλαπλή του 255. Με αυτόν τον τρόπο θα εξαλειφθεί η ανάγκη χρήσης αποθήκευσης αριθμών ως float και μπορούμε να τον αποθηκεύσουμε ως byte, ο οποίος καταλαμβάνει το 1/4 του χώρου στο Arduino. Το sine_data πρέπει να επικολληθεί στο επάνω μέρος του κώδικα για να το δηλώσει ως καθολική μεταβλητή.

Εκτός από τα sine_data, ένας πίνακας που ονομάζεται f_peaks δηλώθηκε ως καθολική μεταβλητή. Μετά από κάθε εκτέλεση της λειτουργίας FFT, αυτός ο πίνακας ενημερώνεται. Όπου f_peaks [0] είναι η κυρίαρχη συχνότητα και περαιτέρω τιμές σε φθίνουσα σειρά.

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

Καθώς έχουμε αποθηκεύσει την τιμή του ημιτόνου για 0 έως 90 μοίρες, μπορεί να υπολογιστεί οποιαδήποτε τιμή ημιτόνου ή συνημίτονου. Κάτω από τη λειτουργία ο πρώτος κύκλος του αριθμού σε μηδέν δεκαδικό ψηφίο και η τιμή επιστροφής από τα αποθηκευμένα δεδομένα. αυτή η μέθοδος χρειάζεται μόνο μία κυμαινόμενη διαίρεση. Αυτό μπορεί να μειωθεί περαιτέρω με την απευθείας αποθήκευση τιμών ημιτόνου (όχι 255 πολλαπλάσια). αλλά αυτό τρώει υψηλή μνήμη στο Arduino.

Η χρήση της παραπάνω διαδικασίας μειώνει την ακρίβεια αλλά βελτιώνει την ταχύτητα. Για 64 πόντους, δίνει το πλεονέκτημα των 8ms και για 128 πόντους δίνει πλεονέκτημα 20ms.

Βήμα 4: Επεξήγηση του κώδικα: Λειτουργία FFT

Το FFT μπορεί να εκτελεστεί μόνο για το μέγεθος δείγματος 2, 4, 8, 16, 32, 64 και ούτω καθεξής. αν η τιμή δεν είναι 2^n, τότε θα πάρει την κάτω πλευρά της τιμής. Για παράδειγμα, εάν επιλέξουμε το μέγεθος δείγματος 70 τότε θα λάβει υπόψη μόνο τα πρώτα 64 δείγματα και θα παραλείψει το υπόλοιπο.

Συνιστάται πάντα να έχετε μέγεθος δείγματος 2^n. Το οποίο μπορεί να είναι:

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

Δύο floats out_r και out_im θα χρειαστούν μεγάλη ποσότητα μνήμης. για Arduino nano δεν θα λειτουργήσει για δείγματα υψηλότερα από 128 (και σε ορισμένες περιπτώσεις 128) λόγω έλλειψης διαθέσιμης μνήμης.

ανυπόγραφα δεδομένα int [13] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

int a, c1, f, o, x; a = N; για (int i = 0; i <12; i ++) // υπολογισμός των επιπέδων {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // είσοδος για αλληλουχία float out_r [data [o] = {}; // πραγματικό μέρος του transform float out_im [data [o] = {}; // φανταστικό μέρος του μετασχηματισμού

Η περαιτέρω ροή έχει ως εξής:

1. Ο κώδικας δημιουργεί λίγο αντίστροφη σειρά για το δεδομένο μέγεθος δείγματος (λεπτομέρειες για την αναστροφή bit σε αναφορές: βήμα 2)

2. Τα δεδομένα εισαγωγής ταξινομούνται σύμφωνα με την παραγόμενη παραγγελία, 3. Πραγματοποιήθηκε FFT

4. Υπολογίζεται το πλάτος του μιγαδικού αριθμού, 5. Οι κορυφές εντοπίζονται και διατάσσονται με φθίνουσα σειρά

6. Μπορείτε να έχετε πρόσβαση στα αποτελέσματα από το f_peaks.

[για πρόσβαση σε άλλα δεδομένα (εκτός από τη μέγιστη συχνότητα) ο κώδικας πρέπει να τροποποιηθεί, έτσι ώστε η τοπική μεταβλητή να μπορεί να αντιγραφεί σε κάποια προκαθορισμένη καθολική μεταβλητή]

Βήμα 5: Δοκιμή του κώδικα

Δοκιμή του Κώδικα
Δοκιμή του Κώδικα
Δοκιμή του Κώδικα
Δοκιμή του Κώδικα

Ένα δείγμα κύματος τριγώνου δίνεται ως είσοδος. για αυτό το κύμα η συχνότητα δειγματοληψίας είναι 10 Hz και η συχνότητα του ίδιου του κύματος είναι 1,25 Hz.

Όπως μπορεί να φανεί από την ακατέργαστη παραγωγή, η τιμή αντιστοιχεί στο FFT που υπολογίζεται από τον Scilab. Ωστόσο, αυτές οι τιμές δεν είναι ακριβώς οι ίδιες με αυτές της χαμηλής ακρίβειας αλλά του ταχύτερου ημιτονοειδούς κύματος.

Στη συχνότητα εξόδου συχνότητα συστοιχίας είναι 1,25 και 3,75. δεν είναι απαραίτητο να λαμβάνετε την ακριβή τιμή κάθε φορά. συνήθως αυτοί οι αριθμοί ονομάζονται κάδοι συχνότητας. έτσι η τιμή εξόδου μπορεί να βρίσκεται οπουδήποτε εντός καθορισμένων κάδων.

Ταχύτητα:

για το Arduino nano χρειάζεται:

16 Πόντοι: 4ms32 Πόντοι: 10ms 64 Πόντοι: 26ms 128 Πόντοι: 53ms

Βήμα 6: Συμπέρασμα

Αυτός ο κώδικας FFT μπορεί να χρησιμοποιηθεί σε εφαρμογές σε πραγματικό χρόνο. Καθώς χρειάζονται περίπου 30 ms για να ολοκληρωθεί ο υπολογισμός. Ωστόσο, η ανάλυση του περιορίζεται από έναν αριθμό δειγμάτων. Ο αριθμός του δείγματος περιορίζεται από τη μνήμη Arduino. Με τη χρήση του Arduino Mega ή άλλης υψηλότερης απόδοσης, η ακρίβεια του πίνακα μπορεί να βελτιωθεί.

εάν έχετε ερωτήσεις, προτάσεις ή διορθώσεις, μη διστάσετε να σχολιάσετε.

Ενημέρωση (2/5/21)

Ενημερώσεις: // ----------------------------- Λειτουργία FFT --------------- ---------------------------------- // float FFT (int in , int N, float Frequency)

Ο τύπος δεδομένων του Ν άλλαξε σε Ακέραιο (υπάρχον Byte) για υποστήριξη> 255 μεγέθους δείγματος. Εάν το μέγεθος του δείγματος είναι <= 128, θα πρέπει να χρησιμοποιηθεί τύπος δεδομένων byte.

Συνιστάται: