विषयसूची:

EasyFFT: Arduino के लिए फास्ट फूरियर ट्रांसफॉर्म (FFT): 6 कदम
EasyFFT: Arduino के लिए फास्ट फूरियर ट्रांसफॉर्म (FFT): 6 कदम

वीडियो: EasyFFT: Arduino के लिए फास्ट फूरियर ट्रांसफॉर्म (FFT): 6 कदम

वीडियो: EasyFFT: Arduino के लिए फास्ट फूरियर ट्रांसफॉर्म (FFT): 6 कदम
वीडियो: EasyFFT: Fast Fourier Transform (FFT) for Arduino 2024, सितंबर
Anonim
Image
Image

कैप्चर किए गए सिग्नल से आवृत्ति का मापन एक मुश्किल काम हो सकता है, खासकर Arduino पर क्योंकि इसमें कम कम्प्यूटेशनल पावर है। शून्य-क्रॉसिंग पर कब्जा करने के लिए विधियां उपलब्ध हैं जहां आवृत्ति को चेक करके कैप्चर किया जाता है कि सिग्नल कितनी बार दिए गए समय के भीतर शून्य रेखाओं को पार करता है। जब सिग्नल विभिन्न आवृत्तियों का संयोजन होता है तो ऐसी विधि काम नहीं कर सकती है।

यदि आप ऐसी पृष्ठभूमि से नहीं हैं तो कोड करना किसी भी तरह मुश्किल है। लेकिन एक टिंकरर होने के नाते यह कोड संगीत, सिग्नल विश्लेषण से संबंधित विभिन्न परियोजनाओं के लिए अत्यधिक उपयोगी हो सकता है। इस परियोजना का उद्देश्य एक ऐसा कोड तैयार करना था जो बिना इसकी पृष्ठभूमि में आए Arduino पर लागू करना आसान हो।

यह परियोजना एफएफटी के कार्य की व्याख्या नहीं करती है लेकिन एफएफटी फ़ंक्शन के अनुप्रयोग की व्याख्या करती है। संलग्न वीडियो में भी यही प्रक्रिया बताई गई है।

यदि आप केवल कोड के आवेदन में रुचि रखते हैं, न कि इसकी व्याख्या में। आप सीधे चरण संख्या 3 पर जा सकते हैं।

चरण 1: आवृत्ति परिवर्तन का परिचय

आवृत्ति परिवर्तन का परिचय
आवृत्ति परिवर्तन का परिचय
आवृत्ति परिवर्तन का परिचय
आवृत्ति परिवर्तन का परिचय

कोई भी संकेत विभिन्न साइनसोइडल तरंगों के संयोजन से बना हो सकता है। तो किसी भी समय-आधारित संकेत को विभिन्न आयामों के विभिन्न साइन के संयोजन के रूप में भी दिखाया जा सकता है।

मैंने पिछले निर्देश (https://www.instructables.com/id/Arduino-Frequency…) में से एक में DFT (असतत फूरियर ट्रांसफॉर्म) के काम को समझाने की कोशिश की। किसी भी रीयल-टाइम एप्लिकेशन के लिए ये विधियां बेहद धीमी हैं। जो इसे लगभग बेकार बना देता है।

छवि में, एक संकेत दिखाया गया है जो दो आवृत्तियों f2 और f5 का संयोजन है। यह संकेत f1 से f5 के मान की परीक्षण साइन तरंगों से गुणा किया जाता है।

यह गणितीय रूप से दिखाया जा सकता है कि अलग-अलग आवृत्ति वाले दो हार्मोनिक डेटा-सेट के गुणन का योग शून्य हो जाता है (डेटा की अधिक संख्या बल्लेबाज परिणाम का कारण बन सकती है)। हमारे मामले में, यदि इन दो गुणन आवृत्ति में समान (या बहुत करीब) आवृत्ति होती है, तो गुणन का योग गैर-शून्य संख्या है।

इसलिए यदि हमारे संकेत को f1 से गुणा किया जाता है तो गुणन का योग शून्य होगा (वास्तविक अनुप्रयोग के लिए शून्य के करीब)। f3, f4 के मामले में भी ऐसा ही है। हालांकि, मान के लिए, f2 और f5 आउटपुट शून्य नहीं होंगे, लेकिन बाकी मानों की तुलना में काफी अधिक होंगे।

यहां 5 आवृत्तियों के साथ एक संकेत का परीक्षण किया जाता है, इसलिए संकेत को पांच आवृत्तियों से गुणा करने की आवश्यकता होती है। इस तरह की गहन गणना में अधिक समय लगता है। गणितीय रूप से यह दिखाया गया है कि N नमूनों की संख्या के लिए यह N*N जटिल गुणन लेता है।

चरण 2: फास्ट फूरियर ट्रांसफॉर्म

डीएफटी की गणना को तेज करने के लिए एफएफटी एल्गोरिथम को जेम्स कूली और जॉन टुके द्वारा विकसित किया गया था। इस एल्गोरिथम को 20वीं सदी के सबसे महत्वपूर्ण एल्गोरिदम में से एक भी माना जाता है। यह एक सिग्नल को एक विषम और यहां तक कि अनुक्रमित भाग में विभाजित करता है जो कई आवश्यक गणनाओं को कम करता है। इसका उपयोग करके कुल आवश्यक जटिल गुणन को NlogN तक घटाया जा सकता है। जो एक महत्वपूर्ण सुधार है।

एफएफटी के पीछे के गणित की विस्तृत समझ के लिए आप नीचे दिए गए संदर्भों का उल्लेख कर सकते हैं जिनका मैंने कोड लिखते समय उल्लेख किया था:

1.

2.

3.

4.

चरण 3: कोड की व्याख्या

1. तेज ज्या और कोज्या:

गणना FFT कई बार विभिन्न ज्या और कोज्या का मान लेता है। Arduino का इनबिल्ट फ़ंक्शन पर्याप्त तेज़ नहीं है और आवश्यक मान प्रदान करने में अच्छा समय लेता है। जो कोड को काफी धीमा बनाता है (64 नमूनों के लिए दोगुना समय)। इस समस्या का मुकाबला करने के लिए 0 से 90 डिग्री के लिए साइन का मान 255 के गुणक के रूप में संग्रहीत किया जाता है। ऐसा करने से फ्लोट के रूप में भंडारण संख्याओं का उपयोग करने की आवश्यकता समाप्त हो जाएगी और हम इसे बाइट के रूप में संग्रहीत कर सकते हैं जो Arduino पर 1/4 वां स्थान लेता है। sine_data को वैश्विक चर के रूप में घोषित करने के लिए कोड के शीर्ष पर पेस्ट करने की आवश्यकता है।

sine_data के अलावा, f_peaks नामक एक सरणी को वैश्विक चर के रूप में घोषित किया गया है। FFT फ़ंक्शन के प्रत्येक रन के बाद यह सरणी अपडेट होती है। जहां f_peaks[0] सबसे प्रमुख आवृत्ति और अवरोही क्रम में आगे के मान हैं।

बाइट साइन_डेटा [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}; फ्लोट f_peaks[5];

चूंकि हमने ज्या का मान 0 से 90 डिग्री तक संग्रहीत किया है, इसलिए साइन या कोसाइन के किसी भी मूल्य की गणना की जा सकती है। नीचे संख्या के पहले दौर को शून्य दशमलव बिंदु पर और संग्रहीत डेटा से वापसी मान पर कार्य करें। इस विधि को केवल एक अस्थायी विभाजन की आवश्यकता है। इसे सीधे साइन वैल्यू (255 मल्टीपल नहीं) को स्टोर करके और कम किया जा सकता है। लेकिन वह Arduino पर उच्च मेमोरी को खा जाता है।

उपरोक्त प्रक्रिया का उपयोग करने से सटीकता कम हो जाती है लेकिन गति में सुधार होता है। 64 अंक के लिए यह 8ms का लाभ देता है और 128 अंकों के लिए 20ms का लाभ देता है।

चरण 4: कोड की व्याख्या: एफएफटी फ़ंक्शन

FFT केवल 2, 4, 8, 16, 32, 64 और इसी तरह के नमूने के आकार के लिए किया जा सकता है। यदि मान 2^n नहीं है, तो यह मान का निचला भाग लेगा। उदाहरण के लिए, यदि हम 70 का नमूना आकार चुनते हैं तो यह केवल पहले 64 नमूनों पर विचार करेगा और बाकी को छोड़ देगा।

हमेशा 2^n का नमूना आकार रखने की अनुशंसा की जाती है। कौन हो सकता है:

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

दो फ़्लोट out_r और out_im अधिक मात्रा में मेमोरी लेंगे। Arduino नैनो के लिए उपलब्ध मेमोरी की कमी के कारण 128 (और कुछ मामलों में 128) से अधिक नमूनों के लिए काम नहीं करेगा।

अहस्ताक्षरित इंट डेटा [१३] = {१, २, ४, ८, १६, ३२, ६४, १२८, २५६, ५१२, १०२४, २०४८};

इंट ए, सी1, एफ, ओ, एक्स; ए = एन; for(int i=0;i<12;i++) // स्तरों की गणना करना {if(data<=a){o=i;} } int in_ps[data[o]={}; // अनुक्रमण के लिए इनपुट फ्लोट आउट_आर [डेटा [ओ] = {}; // ट्रांसफॉर्म का वास्तविक हिस्सा फ्लोट आउट_इम [डेटा [ओ] = {}; // परिवर्तन का काल्पनिक हिस्सा

आगे का प्रवाह इस प्रकार है:

1. कोड दिए गए नमूना आकार के लिए थोड़ा उलट क्रम उत्पन्न करता है (संदर्भों पर बिट रिवर्सिंग पर विवरण: चरण 2)

2. उत्पन्न आदेश के अनुसार इनपुट डेटा का आदेश दिया, 3. एफएफटी ने प्रदर्शन किया

4. गणना की गई जटिल संख्या का आयाम, 5. चोटियों का पता लगाया जाता है और अवरोही क्रम में क्रमबद्ध किया जाता है

6. परिणाम f_peaks से प्राप्त किए जा सकते हैं।

[अन्य डेटा तक पहुंचने के लिए (पीक फ़्रीक्वेंसी के अलावा) कोड को संशोधित किया जाना चाहिए, ताकि स्थानीय चर को कुछ पूर्वनिर्धारित वैश्विक चर में कॉपी किया जा सके]

चरण 5: कोड का परीक्षण

कोड का परीक्षण
कोड का परीक्षण
कोड का परीक्षण
कोड का परीक्षण

एक नमूना त्रिभुज तरंग इनपुट के रूप में दी गई है। इस तरंग के लिए नमूना आवृत्ति 10 हर्ट्ज है और तरंग की आवृत्ति स्वयं 1.25 हर्ट्ज है।

जैसा कि कच्चे आउटपुट से दिखाया जा सकता है, साइलैब द्वारा परिकलित एफएफटी के साथ मूल्य मेल खा रहा है। हालाँकि, ये मान ठीक उसी तरह नहीं हैं जैसे हम कम सटीकता लेकिन तेज़ साइन वेव करते हैं।

आउटपुट फ़्रीक्वेंसी में एरे फ़्रीक्वेंसी 1.25 और 3.75 हैं। हर बार सटीक मूल्य प्राप्त करना आवश्यक नहीं है। आमतौर पर इन नंबरों को फ़्रीक्वेंसी बिन कहा जाता है। इसलिए आउटपुट मान निर्दिष्ट डिब्बे के भीतर कहीं भी हो सकता है।

गति:

Arduino नैनो के लिए यह लेता है:

16 अंक: 4ms32 अंक: 10ms 64 अंक: 26ms 128 अंक: 53ms

चरण 6: निष्कर्ष

इस FFT कोड का उपयोग रीयल-टाइम अनुप्रयोगों में किया जा सकता है। चूंकि गणना को पूरा करने में लगभग 30 एमएस लगते हैं। हालाँकि, इसका रिज़ॉल्यूशन कई नमूनों द्वारा सीमित है। नमूने की संख्या Arduino मेमोरी द्वारा सीमित है। Arduino मेगा या अन्य उच्च प्रदर्शन बोर्ड सटीकता का उपयोग करके सुधार किया जा सकता है।

यदि आपके कोई प्रश्न, सुझाव या सुधार हैं तो बेझिझक टिप्पणी करें।

अपडेट (2/5/21)

अपडेट:--------------------------- एफएफटी फंक्शन----------- -----------------------------//फ्लोट एफएफटी (इंट इन , इंट एन, फ्लोट फ्रीक्वेंसी)

एन का डेटा प्रकार> 255 नमूना आकार का समर्थन करने के लिए इंटीजर (मौजूदा बाइट) में बदल गया। यदि नमूना आकार <=128 है, तो बाइट डेटा प्रकार का उपयोग किया जाना चाहिए।

सिफारिश की: