Агуулгын хүснэгт:

EasyFFT: Arduino -д зориулсан Fast Fourier Transform (FFT): 6 алхам
EasyFFT: Arduino -д зориулсан Fast Fourier Transform (FFT): 6 алхам

Видео: EasyFFT: Arduino -д зориулсан Fast Fourier Transform (FFT): 6 алхам

Видео: EasyFFT: Arduino -д зориулсан Fast Fourier Transform (FFT): 6 алхам
Видео: QuickFFT: High Speed FFT for Arduino 2024, Есдүгээр
Anonim
Image
Image

Баригдсан дохионоос давтамжийг хэмжих нь хэцүү ажил байж магадгүй, ялангуяа тооцоолох чадвар багатай тул Arduino дээр. Өгөгдсөн хугацаанд дохио тэг шугамыг хэдэн удаа давсан болохыг шалгаж, давтамжийг барьж авах тэг огтлолцол хийх аргууд байдаг. Дохио нь янз бүрийн давтамжийн хослол байх үед ийм арга ажиллахгүй байж магадгүй юм.

Хэрэв та ийм суурьтай хүн биш бол код бичих нь ямар нэгэн байдлаар хэцүү байдаг. Гэхдээ энэ код нь хөгжим, дохионы шинжилгээтэй холбоотой янз бүрийн төслүүдэд маш их хэрэгтэй байж магадгүй юм. Энэхүү төслийн зорилго нь Arduino дээр арын дэвсгэр рүү орохгүйгээр хэрэгжүүлэхэд хялбар код бэлтгэх явдал байв.

Энэхүү төсөл нь 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 алгоритмыг Жеймс Кули, Жон Тукей нар боловсруулсан болно. Энэхүү алгоритмыг 20 -р зууны хамгийн чухал алгоритмуудын нэг гэж үздэг. Энэ нь дохиог сондгой, тэгш дараалсан хэсэгт хувааж, шаардлагатай хэд хэдэн тооцооллыг бууруулдаг. Үүнийг ашигласнаар нийт шаардлагатай цогц үржүүлгийг NlogN болгон бууруулж болно. энэ нь мэдэгдэхүйц сайжруулалт юм.

Та FFT -ийн математикийг нарийвчлан ойлгохын тулд кодыг бичихдээ миний дурдсан ишлэлүүдийг иш татаж болно.

1.

2.

3.

4.

Алхам 3: Кодын тайлбар

1. Хурдан синус ба косинус:

FFT тооцоолол нь янз бүрийн синус ба косинусын утгыг хэд хэдэн удаа авдаг. Arduino -ийн суулгагдсан функц нь хангалттай хурдан биш бөгөөд шаардлагатай утгыг өгөхөд маш их цаг хугацаа шаардагддаг. Энэ нь кодыг мэдэгдэхүйц удаашруулдаг (64 дээжийн хугацааг хоёр дахин нэмэгдүүлдэг). Энэ асуудлыг шийдвэрлэхийн тулд 0 -ээс 90 градусын синусын утгыг 255 -ийн үржвэр болгон хадгална. Ингэснээр тоонуудыг float болгон ашиглах шаардлагагүй болж, бид үүнийг Arduino дээр 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}; 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, …

Out_r ба out_im гэсэн хоёр хөвөгч нь их хэмжээний санах ой авах болно. санах ой байхгүй тул Arduino нано нь 128 -аас дээш (зарим тохиолдолд 128) дээжинд ажиллахгүй.

гарын үсэггүй int өгөгдөл [13] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

int a, c1, f, o, x; a = N; for (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 Гц байна.

Түүхий гаралтаас харж болно, утга нь Scilab -ийн тооцоолсон FFT -тэй таарч байна. Гэсэн хэдий ч эдгээр утга нь нарийвчлал багатай боловч синус долгионы хурдтай ижил биш юм.

Гаралтын давтамжийн хувьд массивын давтамж 1.25 ба 3.75 байна. Тэр болгонд яг үнэ цэнийг нь авах шаардлагагүй. Ихэвчлэн эдгээр тоонуудыг давтамжийн сав гэж нэрлэдэг. Тиймээс гаралтын утга нь заасан савны аль ч хэсэгт байж болно.

Хурд:

Arduino наногийн хувьд танд дараахь зүйлс хэрэгтэй болно.

16 оноо: 4ms32 оноо: 10ms 64 оноо: 26ms 128 оноо: 53ms

Алхам 6: Дүгнэлт

Энэхүү FFT кодыг бодит цагийн програмд ашиглах боломжтой. Тооцооллыг дуусгахын тулд ойролцоогоор 30 мс шаардагдана. Гэсэн хэдий ч түүний нарийвчлал нь хэд хэдэн дээжээр хязгаарлагддаг. Дээжийн тоо нь Arduino санах ойгоор хязгаарлагддаг. Arduino Mega эсвэл бусад өндөр гүйцэтгэлийн самбарыг ашигласнаар самбарын нарийвчлалыг сайжруулах боломжтой.

хэрэв танд ямар нэгэн асуулт, санал, залруулга байвал сэтгэгдэл бичихээс бүү эргэлзээрэй.

Шинэчлэлт (2/5/21)

Шинэчлэлтүүд: // ---------------------------- FFT функц --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

Өгөгдлийн төрөл N нь 255 түүврийн хэмжээг дэмжихийн тулд бүхэл тоо (одоо байгаа байт) болж өөрчлөгдсөн. Хэрэв түүврийн хэмжээ <= 128 бол байтын өгөгдлийн төрлийг ашиглах ёстой.

Зөвлөмж болгож буй: