สารบัญ:
- ขั้นตอนที่ 1: การติดตั้งไลบรารี
- ขั้นตอนที่ 2: การแปลงฟูริเยร์และแนวคิด FFT
- ขั้นตอนที่ 3: จำลองสัญญาณ
- ขั้นตอนที่ 4: การวิเคราะห์สัญญาณจำลอง - การเข้ารหัส
- ขั้นตอนที่ 5: การวิเคราะห์สัญญาณจำลอง - ผลลัพธ์
- ขั้นตอนที่ 6: การวิเคราะห์สัญญาณจริง - การเดินสาย ADC
- ขั้นตอนที่ 7: การวิเคราะห์สัญญาณจริง - การเข้ารหัส
- ขั้นตอนที่ 8: การวิเคราะห์สัญญาณจริง - ผลลัพธ์
- ขั้นตอนที่ 9: แล้วสัญญาณไซน์ที่ถูกตัดแล้วล่ะ
วีดีโอ: 1024 ตัวอย่าง FFT Spectrum Analyzer โดยใช้ Atmega1284: 9 ขั้นตอน
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:04
บทช่วยสอนที่ค่อนข้างง่ายนี้ (โดยพิจารณาถึงความซับซ้อนของหัวข้อนี้) จะแสดงให้คุณเห็นว่าคุณสามารถสร้างเครื่องวิเคราะห์สเปกตรัมตัวอย่าง 1024 ตัวอย่างที่ง่ายมากโดยใช้บอร์ดประเภท Arduino (1284 Narrow) และพล็อตเตอร์แบบอนุกรมได้อย่างไร บอร์ดที่เข้ากันได้กับ Arduino ชนิดใดก็ได้ แต่ยิ่งมี RAM มาก ความละเอียดความถี่ที่ดีที่สุดที่คุณจะได้รับ มันจะต้องมี RAM มากกว่า 8 KB เพื่อคำนวณ FFT ด้วยตัวอย่าง 1024
การวิเคราะห์สเปกตรัมใช้เพื่อกำหนดส่วนประกอบความถี่หลักของสัญญาณ หลายเสียง (เช่นเสียงที่ผลิตโดยเครื่องดนตรี) ประกอบด้วยความถี่พื้นฐานและฮาร์โมนิกบางตัวที่มีความถี่ที่เป็นทวีคูณของจำนวนเต็มของความถี่พื้นฐาน เครื่องวิเคราะห์สเปกตรัมจะแสดงองค์ประกอบสเปกตรัมเหล่านี้ทั้งหมด
คุณอาจต้องการใช้การตั้งค่านี้เป็นตัวนับความถี่หรือเพื่อตรวจสอบสัญญาณใดๆ ที่คุณสงสัยว่ามีเสียงรบกวนในวงจรอิเล็กทรอนิกส์ของคุณ
เราจะเน้นที่นี่ในส่วนซอฟต์แวร์ หากคุณต้องการสร้างวงจรถาวรสำหรับแอปพลิเคชันเฉพาะ คุณจะต้องขยายและกรองสัญญาณ การปรับสภาพล่วงหน้านี้ขึ้นอยู่กับสัญญาณที่คุณต้องการศึกษาโดยสิ้นเชิง ขึ้นอยู่กับแอมพลิจูด อิมพีแดนซ์ ความถี่สูงสุด ฯลฯ… คุณสามารถตรวจสอบ
ขั้นตอนที่ 1: การติดตั้งไลบรารี
เราจะใช้ห้องสมุด ArduinoFFT ที่เขียนโดย Enrique Condes เนื่องจากเราต้องการสำรอง RAM ให้มากที่สุด เราจะใช้สาขาการพัฒนาของที่เก็บนี้ ซึ่งอนุญาตให้ใช้ประเภทข้อมูล float (แทนที่จะเป็นสองเท่า) เพื่อเก็บข้อมูลตัวอย่างและข้อมูลที่คำนวณได้ ดังนั้นเราต้องติดตั้งด้วยตนเอง ไม่ต้องกังวล เพียงดาวน์โหลดไฟล์เก็บถาวรและคลายการบีบอัดในโฟลเดอร์ไลบรารี Arduino ของคุณ (เช่น ในการกำหนดค่าเริ่มต้นของ Windows 10: C:\Users\_your_user_name_\Documents\Arduino\libraries)
คุณสามารถตรวจสอบว่าไลบรารีได้รับการติดตั้งอย่างถูกต้องโดยรวบรวมหนึ่งในตัวอย่างที่มีให้ เช่น "FFT_01.ino"
ขั้นตอนที่ 2: การแปลงฟูริเยร์และแนวคิด FFT
คำเตือน: หากคุณไม่สามารถทนเห็นสัญกรณ์ทางคณิตศาสตร์ใดๆ ได้ คุณอาจต้องการข้ามไปยังขั้นตอนที่ 3 อย่างไรก็ตาม หากคุณไม่เข้าใจทั้งหมด ให้พิจารณาข้อสรุปที่ส่วนท้ายของส่วน
สเปกตรัมความถี่ได้มาจากอัลกอริธึม Fast Fourier Transform FFT คือการใช้งานดิจิทัลที่ใกล้เคียงกับแนวคิดทางคณิตศาสตร์ของการแปลงฟูริเยร์ ภายใต้แนวคิดนี้ เมื่อคุณได้รับวิวัฒนาการของสัญญาณตามแกนเวลา คุณจะทราบการแทนค่าในโดเมนความถี่ ซึ่งประกอบด้วยค่าที่ซับซ้อน (จริง + จินตภาพ) แนวคิดเป็นแบบส่วนกลับกัน ดังนั้นเมื่อคุณทราบการแสดงโดเมนความถี่ คุณสามารถเปลี่ยนกลับเป็นโดเมนเวลาและรับสัญญาณกลับมาเหมือนกับก่อนการแปลง
แต่เราจะทำอย่างไรกับชุดของค่าที่ซับซ้อนที่คำนวณได้นี้ในโดเมนเวลา ส่วนใหญ่จะปล่อยให้วิศวกร สำหรับเรา เราจะเรียกอัลกอริทึมอื่นที่จะแปลงค่าที่ซับซ้อนเหล่านี้เป็นข้อมูลความหนาแน่นของสเปกตรัม นั่นคือค่าขนาด (= ความเข้ม) ที่เกี่ยวข้องกับแต่ละแถบความถี่ จำนวนแถบความถี่จะเท่ากับจำนวนตัวอย่าง
คุณคุ้นเคยกับแนวคิดอีควอไลเซอร์อย่างแน่นอน ย้อนกลับไปในปี 1980 ด้วย Graphic EQ เราจะได้ผลลัพธ์แบบเดียวกัน แต่ด้วย 1024 แบนด์แทนที่จะเป็น 16 และความละเอียดที่เข้มกว่ามาก เมื่ออีควอไลเซอร์ให้มุมมองเพลงทั่วโลก การวิเคราะห์สเปกตรัมแบบละเอียดจะช่วยให้คำนวณความเข้มของแต่ละแบนด์ 1024 ได้อย่างแม่นยำ
แนวคิดที่สมบูรณ์แบบ แต่:
- เนื่องจาก FFT เป็นเวอร์ชันดิจิทัลของการแปลงฟูริเยร์ จึงใกล้เคียงกับสัญญาณดิจิทัลและทำให้ข้อมูลบางส่วนหายไป ดังนั้น พูดอย่างเคร่งครัด ผลลัพธ์ของ FFT หากแปลงกลับด้วยอัลกอริธึม FFT กลับหัว จะไม่ให้สัญญาณดั้งเดิมอย่างแน่นอน
- ทฤษฎียังพิจารณาสัญญาณที่ไม่จำกัด แต่นั่นเป็นสัญญาณที่คงอยู่ตลอดไป เนื่องจากเราจะแปลงเป็นดิจิทัลในช่วงระยะเวลาหนึ่งเท่านั้น (เช่น ตัวอย่าง) เราจะแนะนำข้อผิดพลาดเพิ่มเติมบางอย่าง
- ในที่สุดความละเอียดของการแปลงแอนะล็อกเป็นดิจิทัลจะส่งผลต่อคุณภาพของค่าที่คำนวณได้
ในทางปฏิบัติ
1) ความถี่ในการสุ่มตัวอย่าง (สังเกต fs)
เราจะสุ่มตัวอย่างสัญญาณ นั่นคือ วัดแอมพลิจูดทุกๆ 1/fs วินาที fs คือความถี่ในการสุ่มตัวอย่าง ตัวอย่างเช่น หากเราสุ่มตัวอย่างที่ 8 KHz ตัวแปลง ADC (ตัวแปลงอนาล็อกเป็นดิจิตอล) ที่อยู่บนชิปจะให้การวัดทุกๆ 1/8000 วินาที
2) จำนวนตัวอย่าง (หมายเหตุ N หรือตัวอย่างในรหัส)
เนื่องจากเราจำเป็นต้องรับค่าทั้งหมดก่อนที่จะเรียกใช้ FFT เราจึงต้องเก็บค่าเหล่านี้ไว้ ดังนั้นเราจะจำกัดจำนวนตัวอย่าง อัลกอริธึม FFT ต้องการตัวอย่างจำนวนหนึ่งซึ่งเป็นกำลัง 2 ยิ่งเรามีตัวอย่างมากเท่าไหร่ก็ยิ่งดีเท่านั้น แต่ต้องใช้หน่วยความจำมาก ยิ่งเราจะต้องจัดเก็บข้อมูลที่แปลงแล้วซึ่งเป็นค่าที่ซับซ้อนมากเท่านั้น ไลบรารี Arduino FFT ช่วยประหยัดพื้นที่บางส่วนโดยใช้
- หนึ่งอาร์เรย์ชื่อ "vReal" เพื่อจัดเก็บข้อมูลตัวอย่างแล้วจึงเป็นส่วนจริงของข้อมูลที่แปลงแล้ว
- อาร์เรย์หนึ่งชื่อ "vImag" เพื่อจัดเก็บส่วนจินตภาพของข้อมูลที่แปลงแล้ว
จำนวน RAM ที่ต้องการเท่ากับ 2 (อาร์เรย์) * 32 (บิต) * N (ตัวอย่าง)
ดังนั้นใน Atmega1284 ของเราที่มี RAM ขนาด 16 KB ที่ดี เราจะจัดเก็บค่าสูงสุด N = 16000*8/64 = 2000 ค่า เนื่องจากจำนวนค่าต้องเป็นกำลัง 2 เราจะเก็บค่าได้สูงสุด 1024 ค่า
3) ความละเอียดความถี่
FFT จะคำนวณค่าสำหรับแถบความถี่มากเท่ากับจำนวนตัวอย่าง แบนด์เหล่านี้จะครอบคลุมตั้งแต่ 0 HZ ถึงความถี่สุ่มตัวอย่าง (fs) ดังนั้น ความละเอียดความถี่คือ:
ความละเอียด = fs / N
ความละเอียดจะดีกว่าเมื่อต่ำกว่า ดังนั้นเพื่อความละเอียดที่ดีกว่า (ต่ำกว่า) เราต้องการ:
- ตัวอย่างเพิ่มเติม และ/หรือ
- fs ที่ต่ำกว่า
แต่…
4) fs ขั้นต่ำ
เนื่องจากเราต้องการเห็นความถี่จำนวนมาก บางความถี่สูงกว่า "ความถี่พื้นฐาน" มาก เราจึงตั้งค่า fs ให้ต่ำเกินไปไม่ได้ อันที่จริงมีทฤษฎีบทการสุ่มตัวอย่าง Nyquist–Shannon ที่บังคับให้เรามีความถี่การสุ่มตัวอย่างสูงกว่าความถี่สูงสุดสองเท่าที่เราต้องการทดสอบ
ตัวอย่างเช่น หากเราต้องการวิเคราะห์คลื่นความถี่ทั้งหมดตั้งแต่ 0 Hz จนถึง 15 KHz ซึ่งเป็นความถี่สูงสุดโดยประมาณที่มนุษย์ส่วนใหญ่ได้ยินอย่างชัดเจน เราต้องตั้งค่าความถี่สุ่มตัวอย่างที่ 30 KHz ที่จริงแล้ว ช่างอิเล็กทรอนิกส์มักจะตั้งไว้ที่ 2.5 (หรือ 2.52) * ความถี่สูงสุด ในตัวอย่างนี้ จะเป็น 2.5 * 15 KHz = 37.5 KHz ความถี่สุ่มตัวอย่างปกติในเสียงระดับมืออาชีพคือ 44.1 KHz (การบันทึกเสียงซีดี) 48 KHz และอื่นๆ
บทสรุป:
จุดที่ 1 ถึง 4 นำไปสู่: เราต้องการใช้ตัวอย่างให้ได้มากที่สุด ในกรณีของเราที่มีอุปกรณ์ RAM ขนาด 16 KB เราจะพิจารณาตัวอย่าง 1024 ตัวอย่าง เราต้องการสุ่มตัวอย่างที่ความถี่การสุ่มตัวอย่างต่ำที่สุดเท่าที่จะทำได้ ตราบใดที่สูงพอที่จะวิเคราะห์ความถี่สูงสุดที่เราคาดหวังในสัญญาณของเรา (อย่างน้อย 2.5 * ความถี่นี้)
ขั้นตอนที่ 3: จำลองสัญญาณ
สำหรับการลองครั้งแรก เราจะปรับเปลี่ยนตัวอย่าง TFT_01.ino เล็กน้อยที่ให้ไว้ในคลัง เพื่อวิเคราะห์สัญญาณที่ประกอบด้วย
- ความถี่พื้นฐานตั้งไว้ที่ 440 Hz (ดนตรี A)
- ฮาร์โมนิกที่ 3 ที่ครึ่งหนึ่งของกำลังของปัจจัยพื้นฐาน ("-3 dB")
- ฮาร์โมนิกที่ 5 ที่ 1/4 ของกำลังของพื้นฐาน ("-6 dB)
คุณสามารถเห็นในภาพด้านบนสัญญาณผลลัพธ์ ดูเหมือนสัญญาณจริงมากซึ่งบางครั้งสามารถเห็นได้บนออสซิลโลสโคป (ฉันจะเรียกมันว่า "แบทแมน") ในสถานการณ์ที่มีการตัดสัญญาณไซน์
ขั้นตอนที่ 4: การวิเคราะห์สัญญาณจำลอง - การเข้ารหัส
0) รวมห้องสมุด
#รวม "arduinoFFT.h"
1) คำจำกัดความ
ในส่วนการประกาศ เรามี
const ไบต์ adcPin = 0; // A0
const uint16_t ตัวอย่าง = 1024; // ค่านี้ต้องเป็นกำลังสองเสมอ uint16_t samplingFrequency = 8000; // จะส่งผลต่อค่าสูงสุดของตัวจับเวลาใน timer_setup() SYSCLOCK/8/samplingFrequency ควรเป็นจำนวนเต็ม
เนื่องจากสัญญาณมีฮาร์โมนิกที่ 5 (ความถี่ของฮาร์มอนิกนี้ = 5 * 440 = 2200 Hz) เราจึงต้องตั้งค่าความถี่สุ่มตัวอย่างให้สูงกว่า 2.5*2200 = 5500 Hz ที่นี่ฉันเลือก 8000 Hz
นอกจากนี้เรายังประกาศอาร์เรย์ที่เราจะเก็บข้อมูลดิบและคำนวณ
float vReal[ตัวอย่าง];
float vImag[ตัวอย่าง];
2) การสร้างอินสแตนซ์
เราสร้างวัตถุ ArduinoFFT ArduinoFFT เวอร์ชัน dev ใช้เทมเพลตเพื่อให้เราสามารถใช้ float หรือประเภทข้อมูลคู่ Float (32 บิต) ก็เพียงพอแล้วสำหรับความแม่นยำโดยรวมของโปรแกรมของเรา
ArduinoFFT FFT = ArduinoFFT (vReal, vImag, ตัวอย่าง, ความถี่สุ่มตัวอย่าง);
3) จำลองสัญญาณโดยการเติมอาร์เรย์ vReal แทนที่จะเติมด้วยค่า ADC
ที่จุดเริ่มต้นของลูป เราเติมอาร์เรย์ vReal ด้วย:
float cycles = (((ตัวอย่าง) * signalFrequency) / samplingFrequency); //จำนวนรอบสัญญาณที่สุ่มตัวอย่างจะอ่าน
สำหรับ (uint16_t i = 0; i < ตัวอย่าง; i++) { vReal = float((amplitude * (sin((i * (TWO_PI * cycles)) / ตัวอย่าง))));/* สร้างข้อมูลด้วยค่าบวกและ ค่าลบ*/ vReal += float((แอมพลิจูด * (sin((3 * i * (TWO_PI * รอบ)) / ตัวอย่าง))) / 2.0);/* สร้างข้อมูลด้วยค่าบวกและค่าลบ*/ vReal += float((แอมพลิจูด * (sin((5 * i * (TWO_PI * รอบ)) / ตัวอย่าง))) / 4.0);/* สร้างข้อมูลด้วยค่าบวกและค่าลบ*/ vImag = 0.0; //ส่วนจินตภาพจะต้องเป็นศูนย์ในกรณีที่มีการวนซ้ำเพื่อหลีกเลี่ยงการคำนวณที่ไม่ถูกต้องและการโอเวอร์โฟลว์ }
เราเพิ่มการแปลงคลื่นพื้นฐานให้เป็นดิจิทัลและฮาร์โมนิกทั้งสองแบบที่มีแอมพลิจูดน้อยกว่า กว่าที่เราจะเริ่มต้นอาร์เรย์จินตภาพด้วยศูนย์ เนื่องจากอาร์เรย์นี้ถูกเติมโดยอัลกอริทึม FFT เราจึงต้องล้างข้อมูลอีกครั้งก่อนการคำนวณใหม่แต่ละครั้ง
4) การคำนวณ FFT
จากนั้นเราคำนวณ FFT และความหนาแน่นของสเปกตรัม
FFT.windowing(FFTWindow::Hamming, FFTDirection::ไปข้างหน้า);
FFT.compute(FFTDirection::Forward); /* คำนวณ FFT */ FFT.complexToMagnitude(); /* ขนาดคำนวณ */
การดำเนินการ FFT.windowing(…) จะแก้ไขข้อมูลดิบเนื่องจากเราเรียกใช้ FFT ในจำนวนตัวอย่างที่จำกัด ตัวอย่างแรกและตัวอย่างสุดท้ายแสดงความไม่ต่อเนื่อง (ด้านใดด้านหนึ่ง "ไม่มีอะไร") นี่คือที่มาของข้อผิดพลาด การดำเนินการ "windowing" มีแนวโน้มที่จะลดข้อผิดพลาดนี้
FFT.compute(…) โดยมีทิศทาง "ไปข้างหน้า" คำนวณการเปลี่ยนแปลงจากโดเมนเวลาเป็นโดเมนความถี่
จากนั้นเราจะคำนวณค่าขนาด (เช่น ความเข้ม) สำหรับแต่ละแถบความถี่ ตอนนี้อาร์เรย์ vReal เต็มไปด้วยค่าขนาด
5) การวาดภาพพล็อตเตอร์แบบอนุกรม
มาพิมพ์ค่าบนพล็อตเตอร์แบบอนุกรมโดยเรียกใช้ฟังก์ชัน printVector(…)
PrintVector(vReal, (ตัวอย่าง >> 1), SCL_FREQUENCY);
นี่เป็นฟังก์ชันทั่วไปที่ช่วยให้สามารถพิมพ์ข้อมูลด้วยแกนเวลาหรือแกนความถี่ได้
นอกจากนี้เรายังพิมพ์ความถี่ของแถบที่มีขนาดสูงสุด
ลอย x = FFT.majorPeak();
Serial.print("f0="); Serial.print(x, 6); Serial.println("Hz");
ขั้นตอนที่ 5: การวิเคราะห์สัญญาณจำลอง - ผลลัพธ์
เราเห็นเดือยแหลม 3 อันที่สอดคล้องกับความถี่พื้นฐาน (f0) ฮาร์โมนิกที่ 3 และ 5 โดยมีขนาดครึ่งหนึ่งและ 1/4 ของขนาด f0 ตามที่คาดไว้ เราสามารถอ่านได้ที่ด้านบนของหน้าต่าง f0= 440.430114 Hz ค่านี้ไม่ใช่ 440 Hz อย่างแน่นอน เนื่องจากเหตุผลทั้งหมดที่อธิบายไว้ข้างต้น แต่ใกล้เคียงกับค่าจริงมาก ไม่จำเป็นต้องแสดงทศนิยมที่ไม่มีนัยสำคัญมากนัก
ขั้นตอนที่ 6: การวิเคราะห์สัญญาณจริง - การเดินสาย ADC
เนื่องจากเรารู้วิธีดำเนินการในทางทฤษฎี เราจึงต้องการวิเคราะห์สัญญาณจริง
การเดินสายไฟนั้นง่ายมาก เชื่อมต่อกราวด์เข้าด้วยกันและสายสัญญาณเข้ากับพิน A0 ของบอร์ดของคุณผ่านตัวต้านทานแบบอนุกรมที่มีค่า 1 KOhm ถึง 10 KOhm
ตัวต้านทานซีรีย์นี้จะปกป้องอินพุตแบบอะนาล็อกและหลีกเลี่ยงการส่งเสียงกริ่ง ต้องสูงที่สุดเท่าที่เป็นไปได้เพื่อหลีกเลี่ยงเสียงเรียกเข้า และให้ต่ำที่สุดเท่าที่จะเป็นไปได้เพื่อให้กระแสไฟเพียงพอสำหรับการชาร์จ ADC อย่างรวดเร็ว อ้างถึงแผ่นข้อมูล MCU เพื่อทราบอิมพีแดนซ์ที่คาดไว้ของสัญญาณที่เชื่อมต่อที่อินพุต ADC
สำหรับการสาธิตนี้ ฉันใช้ตัวสร้างฟังก์ชันเพื่อป้อนสัญญาณไซน์ที่มีความถี่ 440 Hz และแอมพลิจูดประมาณ 5 โวลต์ (จะดีที่สุดถ้าแอมพลิจูดอยู่ระหว่าง 3 ถึง 5 โวลต์ ดังนั้น ADC จะใช้ใกล้เต็มสเกล) ผ่านตัวต้านทาน 1.2 KOhm.
ขั้นตอนที่ 7: การวิเคราะห์สัญญาณจริง - การเข้ารหัส
0) รวมห้องสมุด
#รวม "arduinoFFT.h"
1) คำประกาศและการแสดงตัวอย่าง
ในส่วนการประกาศ เราจะกำหนดอินพุต ADC (A0) จำนวนตัวอย่างและความถี่ในการสุ่มตัวอย่าง เช่นเดียวกับในตัวอย่างก่อนหน้า
const ไบต์ adcPin = 0; // A0
const uint16_t ตัวอย่าง = 1024; // ค่านี้ต้องเป็นกำลังสองเสมอ uint16_t samplingFrequency = 8000; // จะส่งผลต่อค่าสูงสุดของตัวจับเวลาใน timer_setup() SYSCLOCK/8/samplingFrequency ควรเป็นจำนวนเต็ม
เราสร้างวัตถุ ArduinoFFT
ArduinoFFT FFT = ArduinoFFT (vReal, vImag, ตัวอย่าง, ความถี่สุ่มตัวอย่าง);
2) ตั้งเวลาและการตั้งค่า ADC
เราตั้งเวลา 1 เพื่อให้หมุนรอบที่ความถี่สุ่มตัวอย่าง (8 KHz) และเพิ่มการขัดจังหวะในการเปรียบเทียบเอาต์พุต
โมฆะ timer_setup(){
// รีเซ็ตตัวจับเวลา 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = บิต (CS11) | บิต (WGM12); // CTC, prescaler ของ 8 TIMSK1 = บิต (OCIE1B); OCR1A = ((16000000 / 8) / ความถี่สุ่มตัวอย่าง) -1; }
และตั้ง ADC ไว้อย่างนั้น
- ใช้ A0 เป็นอินพุต
- ทริกเกอร์โดยอัตโนมัติในแต่ละเอาต์พุตของตัวจับเวลา 1 ตัวเปรียบเทียบการจับคู่B
- สร้างการขัดจังหวะเมื่อการแปลงเสร็จสิ้น
นาฬิกา ADC ถูกตั้งค่าไว้ที่ 1 MHz โดยการปรับสัญญาณนาฬิกาของระบบ (16 MHz) ล่วงหน้าเป็น 16 เนื่องจากทุกการแปลงใช้เวลาประมาณ 13 นาฬิกาที่เต็มสเกล การแปลงสามารถทำได้ที่ความถี่ 1/13 = 0.076 MHz = 76 KHz ความถี่ในการสุ่มตัวอย่างควรต่ำกว่า 76 KHz อย่างมาก เพื่อให้ ADC มีเวลาสุ่มตัวอย่างข้อมูล (เราเลือก fs = 8 KHz)
เป็นโมฆะ adc_setup () {
ADCSRA = บิต (ADEN) | บิต (ADIE) | บิต (ADIF); // เปิด ADC ต้องการขัดจังหวะเมื่อเสร็จสิ้น ADCSRA |= bit (ADPS2); // Prescaler ของ 16 ADMUX = บิต (REFS0) | (adcPin & 7); // การตั้งค่าอินพุต ADC ADCSRB = บิต (ADTS0) | บิต (ADTS2); // ตัวจับเวลา/ตัวนับ1 เปรียบเทียบการจับคู่ B ทริกเกอร์ต้นทาง ADCSRA |= บิต (ADATE); // เปิดการทริกเกอร์อัตโนมัติ }
เราประกาศตัวจัดการขัดจังหวะที่จะเรียกหลังจากการแปลง ADC แต่ละครั้งเพื่อเก็บข้อมูลที่แปลงแล้วในอาร์เรย์ vReal และการล้างการขัดจังหวะ
// ADC กรอก ISR
ISR (ADC_vect) { vReal [resultNumber ++] = ADC; ถ้า (จำนวนผลลัพธ์ == ตัวอย่าง) { ADCSRA = 0; // ปิด ADC } } EMPTY_INTERRUPT (TIMER1_COMPB_vect);
คุณสามารถมีคำอธิบายโดยละเอียดเกี่ยวกับการแปลง ADC บน Arduino (analogRead)
3) ตั้งค่า
ในฟังก์ชันการตั้งค่า เราจะล้างตารางข้อมูลจินตภาพและเรียกใช้ฟังก์ชันการตั้งค่าตัวจับเวลาและ ADC
ศูนย์ฉัน(); // ฟังก์ชั่นที่ตั้งค่าเป็น 0 ของข้อมูลจินตภาพทั้งหมด - อธิบายไว้ในส่วนก่อนหน้า
timer_setup(); adc_setup();
3) วนรอบ
FFT.dcRemoval(); // ลบองค์ประกอบ DC ของสัญญาณนี้เนื่องจาก ADC อ้างอิงถึงกราวด์
FFT.windowing(FFTWindow::Hamming, FFTDirection::ไปข้างหน้า); // ชั่งน้ำหนักข้อมูล FFT.compute(FFTDirection::Forward); // คำนวณ FFT FFT.complexToMagnitude(); // ขนาดการคำนวณ // การพิมพ์สเปกตรัมและความถี่พื้นฐาน f0 PrintVector(vReal, (ตัวอย่าง >> 1), SCL_FREQUENCY); ลอย x = FFT.majorPeak(); Serial.print("f0="); Serial.print(x, 6); Serial.println("Hz");
เรานำส่วนประกอบ DC ออกเนื่องจาก ADC อ้างอิงถึงกราวด์และสัญญาณอยู่กึ่งกลางประมาณ 2.5 โวลต์โดยประมาณ
จากนั้นเราคำนวณข้อมูลตามที่อธิบายไว้ในตัวอย่างก่อนหน้านี้
ขั้นตอนที่ 8: การวิเคราะห์สัญญาณจริง - ผลลัพธ์
อันที่จริงเราเห็นความถี่เดียวในสัญญาณง่ายๆ นี้ ความถี่พื้นฐานที่คำนวณได้คือ 440.118194 Hz ค่านี้เป็นค่าประมาณที่ใกล้เคียงมากของความถี่จริง
ขั้นตอนที่ 9: แล้วสัญญาณไซน์ที่ถูกตัดแล้วล่ะ
ตอนนี้ให้โอเวอร์ไดรฟ์ ADC เล็กน้อยโดยการเพิ่มแอมพลิจูดของสัญญาณที่สูงกว่า 5 โวลต์ดังนั้นจึงถูกตัดออก อย่าผลักดันมากเกินไปที่จะไม่ทำลายอินพุต ADC!
เราสามารถเห็นฮาร์โมนิกบางอย่างปรากฏขึ้น การตัดสัญญาณจะสร้างส่วนประกอบที่มีความถี่สูง
คุณได้เห็นพื้นฐานของการวิเคราะห์ FFT บนบอร์ด Arduino แล้ว ตอนนี้คุณสามารถลองเปลี่ยนความถี่ในการสุ่มตัวอย่าง จำนวนตัวอย่าง และพารามิเตอร์หน้าต่าง ไลบรารียังเพิ่มพารามิเตอร์บางอย่างเพื่อคำนวณ FFT ได้เร็วขึ้นด้วยความแม่นยำน้อยลง คุณจะสังเกตเห็นว่าหากคุณตั้งค่าความถี่การสุ่มตัวอย่างต่ำเกินไป ขนาดที่คำนวณได้จะดูผิดพลาดโดยสิ้นเชิงเนื่องจากการพับสเปกตรัม
แนะนำ:
วิธีทำ DIY 32 Band LED Audio Music Spectrum Analyzer โดยใช้ Arduino Nano ที่บ้าน #arduinoproject: 8 ขั้นตอน
วิธีทำ DIY 32 Band LED Audio Music Spectrum Analyzer โดยใช้ Arduino Nano ที่บ้าน #arduinoproject: วันนี้เราจะสร้างเครื่องวิเคราะห์สเปกตรัมเพลงเสียง LED 32 แบนด์ที่บ้านโดยใช้ Arduino มันสามารถแสดงสเปกตรัมความถี่และเล่นเพลงได้ในเวลาเดียวกันหมายเหตุ max7219LED ต้องต่อที่หน้าตัวต้านทาน 100k ไม่เช่นนั้นเสียงของสปี
ตัวอย่าง De Circuito Representado Mediante Parametros T: 3 ขั้นตอน
ตัวอย่าง De Circuito Representado Mediante Parametros T: Las redes de dos puertos son topolog"puerto de entrada" y un par de terminales como "เปอร์โต เดอ ซาลิดา" Las redes de dos puertos, แทม
DIY FFT Audio Spectrum Analyzer: 3 ขั้นตอน
DIY FFT Audio Spectrum Analyzer: เครื่องวิเคราะห์สเปกตรัม FFT เป็นอุปกรณ์ทดสอบที่ใช้การวิเคราะห์ฟูริเยร์และเทคนิคการประมวลผลสัญญาณดิจิทัลเพื่อให้การวิเคราะห์สเปกตรัม การใช้การวิเคราะห์ฟูริเยร์ทำให้สามารถแปลงค่าหนึ่งค่าใน ตัวอย่างเช่น โดเมนเวลาต่อเนื่องที่แปลง
(ตัวอย่าง) Arduino เรดาร์ตรวจจับศัตรู: 3 ขั้นตอน
(EX) Arduino Enemy-Detecting Radar: ในโครงการนี้ ฉันจะแสดงให้คุณเห็นถึงวิธีสร้างเรดาร์ตรวจจับศัตรูเพื่อป้องกันฐานบ้านของคุณ กระบวนการนี้ง่ายมาก เพียงทำตามขั้นตอนของฉัน และเพื่อนบ้านของคุณจะไม่ขโมยผลไม้ของคุณอีกเมื่อคุณติดตั้งอุปกรณ์นี้! โครงการนี้กำเนิด
ตัวอย่าง Pad Controller โดยใช้ Pure Data: 4 ขั้นตอน
ตัวควบคุมแผ่นตัวอย่างที่ใช้ Pure Data: ในคำแนะนำนี้ ฉันจะสร้างตัวควบคุมเพื่อให้แผ่นกลองชุดอิเล็กทรอนิกส์ Roland แบบเก่าสามารถเรียกเสียงได้โดยไม่ต้องใช้โมดูลดรัมดั้งเดิมที่มาพร้อมกับชุดอุปกรณ์ ฉันจะใช้ Pure Data เพื่อสร้างแพตช์เพื่อโหลด wav บางไฟล์แล้ว p