תוכן עניינים:

QuickFFT: FFT במהירות גבוהה עבור Arduino: 3 שלבים
QuickFFT: FFT במהירות גבוהה עבור Arduino: 3 שלבים

וִידֵאוֹ: QuickFFT: FFT במהירות גבוהה עבור Arduino: 3 שלבים

וִידֵאוֹ: QuickFFT: FFT במהירות גבוהה עבור Arduino: 3 שלבים
וִידֵאוֹ: פתירת תרגיל FFT – אלגוריתמים – Hebrew FFT Tutorial 2024, נוֹבֶמבֶּר
Anonim
QuickFFT: FFT במהירות גבוהה עבור Arduino
QuickFFT: FFT במהירות גבוהה עבור Arduino

ל- Arduino טיפוסי יש זיכרון RAM מוגבל וכוח עיבוד, ו- FFT הוא תהליך אינטנסיבי לחישוב. עבור יישומים רבים בזמן אמת, הדרישה היחידה היא לקבל תדר עם משרעת מרבית או נדרש לזהות שיאי תדרים.

באחד המורים שלי הכנתי קוד ל- FFT שניתן למצוא כאן: EasyFFT

קוד זה הצליח לבצע FFT של עד 128 דגימות בננו Arduino. מספר מדגם גבוה מזה אינו אפשרי בשל הזיכרון המוגבל של Arduino. שיניתי מעט את הפונקציה כדי לשפר את המהירות ולהפחית את צריכת הזיכרון. שינוי זה מאפשר ל- Arduino לבצע FFT מהיר פי חמישה וצורך כמעט חצי זיכרון. מדריך זה אינו מכסה עבודה של FFT, ניתן למצוא הפניות אליו ב- EasyFFT.

שלב 1: עבודה

עובד
עובד
עובד
עובד
עובד
עובד
עובד
עובד

הפונקציה האופיינית ל- FFT משתנה כדי לשפר את המהירות עם דיוק פחות. כפי שמוצג בתמונה יש להכפיל אות בדיקה בצורות גל סינוס או קוסינוס. ערכים אלה יכולים להיות בין 0 ל -1, כך שכדאי לבצע ריבוי צף. בארדואינו, הכפל הצף איטי בהשוואה לפעולות שלמות.

בפונקציה זו, גל הסינוס/קוסינוס מוחלף בגל מרובע. מכיוון שעלינו להכפיל אות בדיקה עם גל מרובע שיכול להיות בעל ערך 0, 1 או -1. בשל כך, אנו יכולים להחליף את הכפל הצף לתוספת או חיסור שלם. עבור חיבור או חיסור שלם של Arduino מהיר פי 5 בערך. זה הופך את הפיתרון של פי 5 למהיר יותר.

בשל שינוי זה כעת ניתן לאחסן ערכי סל תדרים כמספר שלם (שהיה בעבר צף) ואנו מקבלים יתרון נוסף של צריכת זיכרון נמוכה יותר. ב- Arduino Nano, 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 זמין ב- Arduino.

המונח השני מציין את מספר הדגימות במערך והמונח האחרון הוא תדר הדגימה ב- Hz.

שלב 2: קוד

חלק זה מסביר את השינוי שבוצע בקוד EasyFFT שיש לזכור בעת ביצוע השינוי בקוד, 1. כפי שהוסבר קודם, כאן משתמשים במספרים שלמים לביצוע FFT. Int in Arduino הוא מספר של 16 סיביות ויכול להכיל ערכים מ -32768 עד 32768. בכל פעם שהערך של int זה חורג מטווח זה הוא גורם לבעיה. לחסל בעיה זו לאחר חישוב רמות. אם אחד מהערכים יעלה על 15000 מערכים מלאים יחולקו ב- 100. הדבר ימנע את ההצפה של ה- int.

2. חישוב משרעת: כדי לחשב משרעת, יש צורך בריבוע החלק האמיתי והדמיוני ונדרש שורש הריבוע של הסכום. ריבוע והשורש הריבועי של הפונקציה לוקח זמן. כדי להפוך את התהליך למהיר יותר, הקוד הזה פשוט יעשה חלק מהגדלים של חלקים אמיתיים ודמיוניים. זה בוודאי פחות מדויק ועשוי להוביל למסקנה שגויה במקרים מסוימים. אתה יכול לבחור לחזור לשיטה הרגילה לחישוב גודל, אבל זה ייקח יותר זמן ואתה גם צריך לעשות סידור כלשהו כדי לאחסן את המספרים האלה.

3. לקוד זה אין מודול לאיתור שיא מרובה. הוא פשוט יבחר את הערך עם משרעת מרבית (לא כולל המספר הראשון שהוא קיזוז DC). אם אתה צריך מספר פסגות אתה יכול להפנות את קוד EasyFFT ולבצע את הנדרש כאן. במקרה זה, צריך להכריז גם על מערך/משתנה כלשהו כמשתנה גלובלי.

4. הפונקציה מכילה את השורה הבאה:

int signed Pow2 [13] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

הכרזת המשתנים לעיל כמשתנה גלובלי (הדבקתה בתחילת הקוד) תחסוך איפשהו זמן של מילי שניות בכל ביצוע.

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. עם זאת, הפלט כולל הרבה רעש, שעלול להטעות עבור יישומים מסוימים. לכן מומלץ לבדוק את הקוד כראוי לפני הגשת בקשה ליישום שלך.

אני מקווה שמצאת קוד זה שימושי לפרויקט שלך. בכל שאלה או הצעה אנא הגיבו.

מוּמלָץ: