สารบัญ:
- ขั้นตอนที่ 1: รู้เบื้องต้นเกี่ยวกับการแปลงความถี่
- ขั้นตอนที่ 2: การแปลงฟูริเยร์อย่างรวดเร็ว
- ขั้นตอนที่ 3: คำอธิบายของรหัส
- ขั้นตอนที่ 4: คำอธิบายของรหัส: ฟังก์ชัน FFT
- ขั้นตอนที่ 5: การทดสอบรหัส
- ขั้นตอนที่ 6: บทสรุป
วีดีโอ: EasyFFT: Fast Fourier Transform (FFT) สำหรับ Arduino: 6 ขั้นตอน
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:03
การวัดความถี่จากสัญญาณที่จับได้อาจเป็นงานที่ยาก โดยเฉพาะอย่างยิ่งใน 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 ได้รับการพัฒนาโดย James Cooley และ John Tukey อัลกอริธึมนี้ถือเป็นหนึ่งในอัลกอริธึมที่สำคัญที่สุดในศตวรรษที่ 20 มันแบ่งสัญญาณออกเป็นส่วนคี่และลำดับคู่ซึ่งทำให้การคำนวณที่จำเป็นลดลง โดยใช้การคูณที่ซับซ้อนที่จำเป็นทั้งหมดสามารถลดลงเป็น NlogN ซึ่งเป็นการปรับปรุงที่สำคัญ
คุณอาจอ้างอิงข้อมูลอ้างอิงที่ฉันอ้างถึงขณะเขียนโค้ดด้านล่างเพื่อความเข้าใจโดยละเอียดเกี่ยวกับคณิตศาสตร์ที่อยู่เบื้องหลัง FFT:
1.
2.
3.
4.
ขั้นตอนที่ 3: คำอธิบายของรหัส
1. ไซน์เร็วและโคไซน์:
การคำนวณ FFT ใช้ค่าของไซน์และโคไซน์ต่างๆ หลายครั้ง ฟังก์ชัน inbuilt ของ Arduino ไม่เร็วพอและต้องใช้เวลาพอสมควรในการให้ค่าที่ต้องการ ซึ่งทำให้โค้ดช้าลงอย่างมาก (เพิ่มเวลาเป็นสองเท่าสำหรับ 64 ตัวอย่าง) เพื่อแก้ปัญหานี้ ค่าไซน์ 0 ถึง 90 องศาจะถูกเก็บไว้เป็นทวีคูณของ 255 การทำเช่นนี้จะขจัดความจำเป็นในการจัดเก็บตัวเลขเป็นทศนิยมและเราสามารถจัดเก็บเป็นไบต์ซึ่งใช้พื้นที่ 1/4 บน Arduino sine_data ต้องวางที่ด้านบนของโค้ดเพื่อประกาศเป็นตัวแปรส่วนกลาง
นอกเหนือจาก sine_data แล้ว อาร์เรย์ที่เรียกว่า f_peaks ถูกประกาศเป็นตัวแปรส่วนกลาง หลังจากรันฟังก์ชัน FFT ทุกครั้งอาร์เรย์นี้จะอัปเดต โดยที่ f_peaks[0] เป็นความถี่ที่โดดเด่นที่สุดและมีค่าเพิ่มเติมในลำดับจากมากไปน้อย
ไบต์ 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 ทวีคูณ) แต่มันกินหน่วยความจำสูงบน 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, …
สอง floats out_r และ out_im จะใช้หน่วยความจำจำนวนมาก สำหรับ Arduino nano จะไม่ทำงานกับตัวอย่างที่สูงกว่า 128 (และในบางกรณี 128) เนื่องจากหน่วยความจำไม่เพียงพอ
ข้อมูล int ที่ไม่ได้ลงนาม[13]={1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};
int a, c1, f, o, x; เป็น=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 Hz และความถี่ของคลื่นเองคือ 1.25 Hz
ดังที่แสดงจากผลลัพธ์ดิบ ค่าจะตรงกับ FFT ที่คำนวณโดย Scilab อย่างไรก็ตาม ค่าเหล่านี้ไม่ได้เหมือนกันทุกประการกับความแม่นยำต่ำแต่เป็นคลื่นไซน์ที่เร็วกว่า
ในความถี่อาร์เรย์ความถี่เอาต์พุตคือ 1.25 และ 3.75 ไม่จำเป็นต้องได้รับค่าที่แน่นอนทุกครั้ง โดยปกติตัวเลขเหล่านี้เรียกว่าช่องเก็บความถี่ ดังนั้นค่าเอาต์พุตอาจอยู่ที่ใดก็ได้ภายในช่องเก็บที่ระบุ
ความเร็ว:
สำหรับ Arduino nano ต้องใช้:
16 คะแนน: 4ms32 คะแนน: 10ms 64 คะแนน: 26ms 128 คะแนน: 53ms
ขั้นตอนที่ 6: บทสรุป
รหัส FFT นี้สามารถใช้ในแอปพลิเคชันแบบเรียลไทม์ เนื่องจากใช้เวลาประมาณ 30 ms ในการคำนวณให้เสร็จสมบูรณ์ อย่างไรก็ตาม ความละเอียดของมันจำกัดด้วยตัวอย่างจำนวนหนึ่ง จำนวนตัวอย่างถูกจำกัดโดยหน่วยความจำ Arduino โดยการใช้ Arduino Mega หรือความแม่นยำของบอร์ดประสิทธิภาพสูงอื่น ๆ สามารถปรับปรุงได้
หากคุณมีคำถาม ข้อเสนอแนะ หรือการแก้ไขใดๆ โปรดแสดงความคิดเห็น
อัปเดต (2/5/21)
อัปเดต://----------------------------------- ฟังก์ชัน FFT --------------- ----------------------------------------------//float FFT(int in, int N, float Frequency)
ชนิดข้อมูลของ N เปลี่ยนเป็นจำนวนเต็ม (ไบต์ที่มีอยู่) เพื่อรองรับขนาดตัวอย่าง >255 หากขนาดตัวอย่างคือ <=128 ควรใช้ชนิดข้อมูลไบต์
แนะนำ:
Fast Hartley Transform Spectral Stethoscope: 22 ขั้นตอน
Fast Hartley Transform Spectral Stethoscope: ในคำแนะนำนี้ คุณจะได้เรียนรู้วิธีสร้างเครื่องตรวจฟังเสียงแบบสเปกตรัมโดยใช้เครื่องแปลงความถี่ Hartley Transform แบบเร็ว สามารถใช้แสดงภาพเสียงของหัวใจและปอดได้
Transform-a-Car: ควบคุมจากระยะไกลเป็นระบบควบคุมตนเอง: 4 ขั้นตอน
Transform-a-Car: รีโมทควบคุมเป็นระบบควบคุมตัวเอง: นี่คือการแฮ็กบนรถ RC ที่มีรีโมทเสีย คุณสามารถหามากมายที่การขายโรงรถ
การเขียนโปรแกรม Arduino ผ่านมือถือ -- Arduinodroid -- Arduino Ide สำหรับ Android -- กะพริบตา: 4 ขั้นตอน
การเขียนโปรแกรม Arduino ผ่านมือถือ || Arduinodroid || Arduino Ide สำหรับ Android || กะพริบตา: โปรดสมัครสมาชิกช่อง youtube ของฉันสำหรับวิดีโอเพิ่มเติม…… Arduino เป็นบอร์ดซึ่งสามารถตั้งโปรแกรมได้โดยตรงผ่าน USB มันง่ายมากและราคาถูกสำหรับโครงการของวิทยาลัยและโรงเรียน หรือแม้แต่ในผลิตภัณฑ์ต้นแบบ ผลิตภัณฑ์จำนวนมากเริ่มแรกสร้างขึ้นเพื่อฉัน
Flipperkonsole สำหรับ PC Flipper / Pinball Console สำหรับ PC Pinballs: 9 ขั้นตอน
Flipperkonsole สำหรับ PC Flipper / Pinball Console สำหรับ PC Pinballs: ใช้งานได้กับ USB พื้นฐาน เกมสำหรับ PC-Flipperkästen Die Spannungsversorgung erfolgt über das USB Kabel. Implementiert sind die beiden Flipper Buttons และ ein Startbutton Zusätzlich ist ein stossen von unten, von links และ von rechts implem
3.3V Mod สำหรับ Ultrasonic Sensors (เตรียม HC-SR04 สำหรับ 3.3V Logic บน ESP32/ESP8266, Particle Photon ฯลฯ): 4 ขั้นตอน
3.3V Mod สำหรับ Ultrasonic Sensors (เตรียม HC-SR04 สำหรับ 3.3V Logic บน ESP32/ESP8266, Particle Photon, ฯลฯ.): TL;DR: บนเซนเซอร์ ตัดร่องรอยไปที่ Echo pin จากนั้นเชื่อมต่อใหม่โดยใช้ a ตัวแบ่งแรงดันไฟฟ้า (Echo trace -> 2.7kΩ -> Echo pin -> 4.7kΩ -> GND) แก้ไข: มีการถกเถียงกันว่า ESP8266 นั้นทนทานต่อ GPIO 5V จริงหรือไม่ใน