فهرست مطالب:

QuickFFT: FFT با سرعت بالا برای آردوینو: 3 مرحله
QuickFFT: FFT با سرعت بالا برای آردوینو: 3 مرحله

تصویری: QuickFFT: FFT با سرعت بالا برای آردوینو: 3 مرحله

تصویری: QuickFFT: FFT با سرعت بالا برای آردوینو: 3 مرحله
تصویری: Первые шаги - урок по vvvv 2024, ژوئن
Anonim
QuickFFT: FFT با سرعت بالا برای آردوینو
QuickFFT: FFT با سرعت بالا برای آردوینو

آردوینو معمولی دارای RAM و قدرت پردازشی محدودی است و FFT یک فرآیند محاسباتی فشرده است. برای بسیاری از برنامه های زمان واقعی ، تنها شرط دریافت فرکانس با حداکثر دامنه یا مورد نیاز برای تشخیص قله های فرکانس است.

در یکی از دستورالعمل های من ، من یک کد برای FFT تهیه کردم که در اینجا یافت می شود: EasyFFT

این کد قادر به انجام FFT تا 128 نمونه بر روی آردوینو نانو است. به دلیل محدودیت حافظه آردوینو ، تعداد نمونه بیشتر از این امکان پذیر نیست. برای بهبود سرعت و کاهش مصرف حافظه ، عملکرد را کمی تغییر داده ام. این تغییر به آردوینو اجازه می دهد تا FFT را پنج برابر سریعتر انجام دهد و تقریبا نیمی از حافظه را مصرف می کند. این دستورالعمل کار FFT را پوشش نمی دهد ، منابع آن را می توانید در EasyFFT پیدا کنید.

مرحله 1: کار کردن

کار کردن
کار کردن
کار کردن
کار کردن
کار کردن
کار کردن
کار کردن
کار کردن

تابع FFT معمولی برای بهبود سرعت با دقت کمتر اصلاح شده است. همانطور که در تصویر نشان داده شده است ، یک سیگنال آزمایشی باید در شکل موج سینوسی یا کسینوس ضرب شود. این مقادیر می توانند بین 0 تا 1 باشند ، بنابراین ایجاد ضرب شناور ضروری است. در آردوینو ، ضرب شناور در مقایسه با عملیات صحیح کند است.

در این تابع ، موج سینوس/کسینوس با موج مربعی جایگزین می شود. همانطور که باید سیگنال آزمایشی را با موج مربعی ضرب کنیم که ممکن است دارای مقدار 0 ، 1 یا -1 باشد. به همین دلیل ، ما می توانیم ضرب شناور را با جمع یا تفریق صحیح جایگزین کنیم. برای آردوینو جمع یا تفریق عدد صحیح حدود 5 برابر سریعتر است. این باعث می شود حل حدود 5 برابر سریعتر انجام شود.

با توجه به این تغییر ، اکنون می توان مقادیر سطل فرکانس را به صورت یک عدد صحیح (که قبلاً شناور بود) ذخیره کرد و ما مزیت دیگری از مصرف کمتر حافظه دریافت می کنیم. در آردوینو نانو ، int 2 بایت حافظه مصرف می کند در حالی که float 4 بایت حافظه مصرف می کند. با توجه به این مزیت در کد جدید ، ما قادر به انجام FFT برای تقریبا 256 نمونه (قبلاً 128 نمونه) هستیم.

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

پیاده سازی:

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

float f = Q_FFT (داده ها ، 256 ، 100) ؛ در تابع Q_FFT ،

داده ها: این عبارت یک آرایه است که دارای مقادیر سیگنال است ، اندازه نمونه توصیه شده 2 ، 4 ، 8 ، 32 ، 64 ، 128 ، 256 ، 512 ، … به بعد است. اگر اندازه نمونه متعلق به این مقادیر نباشد ، به نزدیکترین سمت پایین مقادیر بریده می شود. به عنوان مثال ، اگر حجم نمونه 75 باشد FFT برای 64 تعداد نمونه انجام می شود. حداکثر تعداد نمونه با RAM موجود در آردوینو محدود می شود.

عبارت دوم تعداد نمونه ها در یک آرایه را مشخص می کند و آخرین عبارت فرکانس نمونه برداری در هرتز است.

مرحله 2: کد

این بخش ، اصلاح ایجاد شده در کد EasyFFT را توضیح می دهد که هنگام ایجاد تغییر در کد باید در نظر داشته باشید ،

1. همانطور که قبلاً توضیح داده شد ، در اینجا از اعداد صحیح برای انجام FFT استفاده می شود. Int در آردوینو یک عدد 16 بیتی است و می تواند شامل مقادیری از -32768 تا 32768 باشد. هرگاه مقدار این int از این محدوده فراتر رود ، مشکل ایجاد می کند. برای از بین بردن این مشکل پس از محاسبه سطح. اگر هر یک از مقادیر بیش از 15000 آرایه کامل باشد بر 100 تقسیم می شود. این از سرریز int جلوگیری می کند.

2. محاسبه دامنه: برای محاسبه دامنه ، قسمت واقعی و خیالی نیاز به مربع دارد و ریشه مربع مجموع مورد نیاز است. مربع و ریشه مربعی تابع زمان بر است. برای سرعت بخشیدن به فرایند ، این کد به سادگی برخی از بزرگی بخشهای واقعی و خیالی را انجام می دهد. این مطمئناً از دقت کمتری برخوردار است و ممکن است در برخی موارد منجر به نتیجه گیری اشتباه شود. ممکن است برای محاسبه بزرگی به روش عادی برگردید ، اما زمان بیشتری طول می کشد و همچنین برای ذخیره این اعداد باید ترتیبی را انجام دهید.

3. این کد ماژولی برای تشخیص اوج چندگانه ندارد. به سادگی مقدار حداکثر دامنه را انتخاب می کند (به استثنای اولین عدد که DC Offset است). اگر به قله های متعدد نیاز دارید می توانید کد EasyFFT را ارجاع داده و تغییرات مورد نیاز را در اینجا انجام دهید. در این حالت ، برخی از آرایه ها/متغیرها نیز باید به عنوان یک متغیر جهانی اعلام شوند.

4- تابع شامل خط زیر است:

unsigned int Pow2 [13] = {1، 2، 4، 8، 16، 32، 64، 128، 256، 512، 1024، 2048}؛

اعلام متغیرهای فوق به عنوان یک متغیر سراسری (چسباندن آن در ابتدای کد) در هر اجرا 1 میلی ثانیه در زمان شما صرفه جویی می کند.

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

شناور f = Q_FFT (داده ها ، 256 ، 100) ؛

6. تشخیص قله: هنگامی که فرکانس با حداکثر دامنه پیدا شد ، این تابع از دامنه فرکانس درست قبل و بعد از آن برای محاسبه نتایج دقیق استفاده می کند. دامنه مورد استفاده در این محاسبه نیز مجموع مدول است (نه ریشه مربع مجموع مربع ها)

اگر Fn فرکانس با حداکثر دامنه باشد ، فرکانس را می توان از فرمول زیر محاسبه کرد.

واقعی F = (A n-1 *Fn-1+An-1 *Fn-1+An-1 *Fn-1) / (An-1+An+An+1)

جایی که An دامنه n فرکانس و Fn-1 مقدار فرکانس است.

مرحله 3: نتایج:

نتایج
نتایج
نتایج
نتایج

زمان حل در مقایسه تصویر فوق با EasyFFT نشان داده شده است. سرعت آن با مقایسه نشان داده شده است.

برای داده های نمونه دارای 3 موج سینوسی با فرکانس های مختلف نشان داده شده است. نتیجه QuickFFT با خروجی Scilab مقایسه می شود. همانطور که در تصویر می بینیم 3 قله با حداکثر دامنه با خروجی Scilab مطابقت دارد. با این حال ، خروجی شامل سر و صدای زیادی است که ممکن است برای برخی از برنامه ها گمراه کننده باشد. بنابراین توصیه می شود قبل از درخواست به برنامه خود ، کد را به درستی بررسی کنید.

امیدوارم این کد برای پروژه شما مفید واقع شده باشد. در صورت هر گونه سوال یا پیشنهاد لطفاً نظر دهید.

توصیه شده: