فهرست مطالب:

EasyFFT: Fast Fourier Transform (FFT) برای آردوینو: 6 مرحله
EasyFFT: Fast Fourier Transform (FFT) برای آردوینو: 6 مرحله

تصویری: EasyFFT: Fast Fourier Transform (FFT) برای آردوینو: 6 مرحله

تصویری: EasyFFT: Fast Fourier Transform (FFT) برای آردوینو: 6 مرحله
تصویری: Analisador de Sinais com Esp e FFT 2024, نوامبر
Anonim
Image
Image

اندازه گیری فرکانس از سیگنال گرفته شده می تواند کار دشواری باشد ، به ویژه در آردوینو زیرا قدرت محاسباتی کمتری دارد. روش هایی برای ضبط عبور صفر وجود دارد که در آن فرکانس با بررسی اینکه چند بار سیگنال از صفر خطوط در زمان معین عبور می کند ، گرفته می شود. وقتی سیگنال ترکیبی از فرکانس های مختلف باشد ، ممکن است چنین روشی کار نکند.

اگر از چنین سابقه ای نیستید ، کدگذاری آن به نوعی دشوار است. اما این کد می تواند برای پروژه های مختلف مربوط به موسیقی ، تجزیه و تحلیل سیگنال بسیار مفید باشد. انگیزه این پروژه تهیه کدی بود که به راحتی در آردوینو پیاده سازی شود بدون اینکه وارد پیش زمینه آن شوید.

این پروژه کار FFT را توضیح نمی دهد ، بلکه کاربرد تابع FFT را توضیح می دهد. همین روند نیز در ویدئوی پیوست توضیح داده شده است.

اگر فقط به کاربرد کد علاقه مند هستید و توضیحی درباره آن ندارید. شما می توانید مستقیماً به مرحله شماره 3 بروید.

مرحله 1: مقدمه ای بر تغییر فرکانس

مقدمه ای بر تغییر فرکانس
مقدمه ای بر تغییر فرکانس
مقدمه ای بر تغییر فرکانس
مقدمه ای بر تغییر فرکانس

هر سیگنالی می تواند از ترکیبی از امواج مختلف سینوسی تشکیل شده باشد. بنابراین هر سیگنال مبتنی بر زمان را می توان به عنوان ترکیبی از سینوس های مختلف دامنه های مختلف نیز نشان داد.

من سعی کردم عملکرد DFT (تبدیل فوریه گسسته) را در یکی از دستورالعمل های قبلی (https://www.instructables.com/id/Arduino-Frequency…) توضیح دهم. این روشها برای هر برنامه زمان واقعی بسیار کند است. که تقریباً بی فایده است

در تصویر ، سیگنالی نشان داده شده است که ترکیبی از دو فرکانس f2 و f5 است. این سیگنال با امواج سینوسی مقادیر f1 تا f5 ضرب می شود.

از نظر ریاضی می توان نشان داد که -جمع ضرب دو مجموعه داده هارمونیک با فرکانس متفاوت به صفر می رسد (تعداد بیشتر داده ها می تواند منجر به نتیجه خمیر شود). در مورد ما ، اگر این دو فرکانس ضرب دارای فرکانس یکسان (یا بسیار نزدیک) باشند ، مجموع ضرب عدد غیر صفر است.

بنابراین اگر سیگنال ما در f1 ضرب شود ، جمع ضرب صفر می شود (برای کاربرد واقعی نزدیک به صفر). این مورد در مورد f3 ، f4 نیز صادق است. با این حال ، برای مقدار ، خروجی f2 و f5 صفر نخواهد بود ، اما به طور قابل توجهی بیشتر از بقیه مقادیر است.

در اینجا یک سیگنال با 5 فرکانس آزمایش می شود ، بنابراین سیگنال باید در پنج فرکانس ضرب شود. چنین محاسبه شدید زمان بیشتری می برد. از نظر ریاضی نشان داده شده است که برای N تعداد نمونه ضرب N*N پیچیده طول می کشد.

مرحله 2: تبدیل سریع فوریه

برای سرعت بخشیدن به محاسبه DFT ، الگوریتم FFT توسط جیمز کولی و جان توکی توسعه داده شد. این الگوریتم همچنین به عنوان یکی از مهمترین الگوریتم های قرن بیستم محسوب می شود. سیگنال را به قسمت فرد و زنجیره ای تقسیم می کند که تعدادی از محاسبات مورد نیاز را کمتر می کند. با استفاده از آن ، کل ضرب پیچیده مورد نیاز را می توان به NlogN کاهش داد. که پیشرفت قابل توجهی است.

برای درک دقیق ریاضیات پشت FFT ، ممکن است به منابع زیر که هنگام نوشتن کد به آنها اشاره کرده ام اشاره کنید:

1.

2.

3.

4.

مرحله 3: توضیح کد

1. سینوس سریع و کسینوس:

محاسبه FFT مقدار سینوس و کسینوس مختلف را چندین بار می گیرد. عملکرد داخلی آردوینو به اندازه کافی سریع نیست و زمان زیادی طول می کشد تا مقدار مورد نیاز را ارائه دهد. این باعث می شود کد به طور قابل توجهی کندتر شود (زمان را برای 64 نمونه دو برابر می کند). برای مقابله با این مسئله مقدار سینوس برای 0 تا 90 درجه به عنوان مضرب 255 ذخیره می شود. با این کار نیازی به استفاده از ذخیره اعداد به عنوان float ندارید و می توانیم آن را به عنوان بایت ذخیره کنیم که 1/4 فضا را در آردوینو اشغال می کند. 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}؛ شناور f_peaks [5]؛

همانطور که ما مقدار سینوس را برای 0 تا 90 درجه ذخیره کرده ایم ، هر مقدار سینوس یا کسینوس را می توان محاسبه کرد. در زیر ، دور اول عدد را به صفر اعشار و مقدار داده های ذخیره شده را بر می گردانیم. این روش فقط به یک تقسیم شناور نیاز دارد. این می تواند با ذخیره مستقیم مقادیر سینوسی (نه 255 چندگانه) بیشتر کاهش یابد. اما حافظه بالایی را در آردوینو می خورد.

استفاده از روش فوق دقت را کاهش می دهد اما سرعت را بهبود می بخشد. برای 64 امتیاز ، مزیت 8 میلی ثانیه و برای 128 امتیاز مزیت 20 میلی ثانیه است.

مرحله 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, …

دو شناور out_r و out_im مقدار زیادی حافظه را می گیرند. برای آردوینو نانو برای نمونه های بالاتر از 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] = {}؛ // بخش واقعی تبدیل float out_im [data [o] = {}؛ // بخش خیالی تبدیل

جریان بیشتر به شرح زیر است:

1. کد کمی سفارش معکوس برای اندازه نمونه داده شده ایجاد می کند (جزئیات مربوط به معکوس شدن بیت در منابع: مرحله 2)

2. داده های ورودی طبق سفارش ایجاد شده ،

3. FFT انجام شده است

4. دامنه عدد مختلط محاسبه شده ،

5. قله ها به ترتیب نزولی شناسایی و مرتب می شوند

6. از f_peaks می توان به نتایج دسترسی داشت.

[برای دسترسی به داده های دیگر (به غیر از حداکثر فرکانس) کد باید اصلاح شود ، به طوری که متغیر محلی می تواند در برخی از متغیرهای جهانی از پیش تعیین شده کپی شود]

مرحله 5: تست کد

تست کد
تست کد
تست کد
تست کد

یک نمونه موج مثلث به عنوان ورودی داده می شود. برای این نمونه فرکانس نمونه برداری 10 هرتز و فرکانس خود موج 1.25 هرتز است.

همانطور که از خروجی خام نشان داده می شود ، مقدار با FFT محاسبه شده توسط Scilab مطابقت دارد. با این حال ، این مقادیر دقیقاً مشابه دقت پایین ما نیستند ، اما موج سینوسی سریعتر هستند.

در خروجی فرکانس آرایه 1.25 و 3.75 است. لازم نیست هر بار مقدار دقیق را بدست آورید. معمولاً به این اعداد سطل فرکانس می گویند. بنابراین مقدار خروجی ممکن است در هر کجای سطل های مشخص باشد.

سرعت:

برای آردوینو نانو به موارد زیر نیاز است:

16 امتیاز: 4ms32 امتیاز: 10ms 64 امتیاز: 26ms 128 امتیاز: 53ms

مرحله 6: نتیجه گیری

این کد FFT را می توان در برنامه های زمان واقعی استفاده کرد. برای تکمیل محاسبه حدود 30 میلی ثانیه طول می کشد. با این حال ، وضوح آن توسط تعدادی نمونه محدود شده است. تعداد نمونه توسط حافظه آردوینو محدود می شود. با استفاده از آردوینو مگا یا سایر عملکردهای بالاتر ، می توان دقت برد را افزایش داد.

در صورت داشتن هرگونه سوال ، پیشنهاد یا اصلاح ، نظر دهید.

به روز رسانی (2/5/21)

به روز رسانی: // ----------------------------- عملکرد FFT --------------- ---------------------------------- // شناور FFT (int در ، int N ، فرکانس شناور)

نوع داده N به عدد صحیح (بایت موجود) تغییر کرده است تا از حجم نمونه 255 پشتیبانی کند. اگر اندازه نمونه <= 128 باشد ، باید از نوع داده بایت استفاده شود.

توصیه شده: