สารบัญ:
2025 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2025-01-23 15:12
ตะลึงพรึงเพริดเพื่อนและครอบครัวของคุณด้วยโปรเจ็กต์นี้ที่ตรวจจับโน้ตที่เล่นโดยเครื่องดนตรี โครงงานนี้จะแสดงความถี่โดยประมาณรวมถึงโน้ตดนตรีที่เล่นบนคีย์บอร์ดอิเล็กทรอนิกส์ แอพเปียโน หรือเครื่องดนตรีอื่นๆ
รายละเอียด
สำหรับโครงการนี้ เอาต์พุตแอนะล็อกจากเครื่องตรวจจับโมดูลเสียงจะถูกส่งไปยังอินพุตอนาล็อก A0 ของ Arduino Uno สัญญาณแอนะล็อกจะถูกสุ่มตัวอย่างและหาปริมาณ (ดิจิทัล) รหัสความสัมพันธ์อัตโนมัติ การถ่วงน้ำหนัก และการปรับใช้เพื่อค้นหาความถี่พื้นฐานโดยใช้ 3 ช่วงเวลาแรก จากนั้น ความถี่พื้นฐานโดยประมาณจะถูกเปรียบเทียบกับความถี่ในช่วงอ็อกเทฟ 3, 4 และ 5 เพื่อกำหนดความถี่โน้ตดนตรีที่ใกล้ที่สุด ในที่สุดโน้ตที่คาดเดาสำหรับความถี่ที่ใกล้เคียงที่สุดจะถูกพิมพ์ไปที่หน้าจอ
หมายเหตุ: คำแนะนำนี้เน้นเฉพาะวิธีการสร้างโครงการ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับรายละเอียดและเหตุผลในการออกแบบ โปรดไปที่ลิงก์นี้: ข้อมูลเพิ่มเติม
เสบียง
- (1) Arduino Uno (หรือ Genuino Uno)
- (1) DEVMO ไมโครโฟน เซนเซอร์ ความไวสูง โมดูลตรวจจับเสียง เข้ากันได้
- (1) เขียงหั่นขนม Solderless
- (1) สาย USB-A เป็น B
- สายจัมเปอร์
- แหล่งดนตรี (แอพเปียโน คีย์บอร์ด หรือแอพ paino พร้อมลำโพง)
- (1) คอมพิวเตอร์หรือแล็ปท็อป
ขั้นตอนที่ 1: สร้างฮาร์ดแวร์สำหรับตัวตรวจจับโน้ตดนตรี
การใช้ Arduino Uno, สายเชื่อมต่อ, เขียงหั่นขนมแบบไม่มีบัดกรี และ DEVMO Microphone Sensor โมดูลตรวจจับเสียงความไวสูง (หรือที่คล้ายกัน) สร้างวงจรที่แสดงในภาพนี้
ขั้นตอนที่ 2: ตั้งโปรแกรมตัวตรวจจับโน้ตดนตรี
ใน Arduino IDE ให้เพิ่มโค้ดต่อไปนี้
gistfile1.txt
| /* |
| ชื่อไฟล์/ร่าง: MusicalNoteDetector |
| หมายเลขเวอร์ชัน: v1.0 สร้างเมื่อ 7 มิถุนายน 2020 |
| ผู้เขียนต้นฉบับ: Clyde A. Lettsome, PhD, PE, MEM |
| คำอธิบาย: รหัส/ร่างนี้แสดงความถี่โดยประมาณรวมถึงโน้ตดนตรีที่เล่นบนคีย์บอร์ดอิเล็กทรอนิกส์หรือแอปเปียโน สำหรับโปรเจ็กต์นี้ เอาต์พุตแอนะล็อกจาก |
| เครื่องตรวจจับโมดูลเสียงจะถูกส่งไปยังอินพุตอนาล็อก A0 ของ Arduino Uno สัญญาณแอนะล็อกจะถูกสุ่มตัวอย่างและหาปริมาณ (ดิจิทัล) ใช้รหัส Autocorrelation, weighting และ tuning เพื่อ |
| หาความถี่พื้นฐานโดยใช้ 3 ช่วงเวลาแรก จากนั้น ความถี่พื้นฐานโดยประมาณจะถูกเปรียบเทียบกับความถี่ในช่วงอ็อกเทฟ 3, 4 และ 5 เพื่อกำหนดดนตรีที่ใกล้เคียงที่สุด |
| บันทึกความถี่ ในที่สุดโน้ตที่คาดเดาสำหรับความถี่ที่ใกล้เคียงที่สุดจะถูกพิมพ์ไปที่หน้าจอ |
| ใบอนุญาต: โปรแกรมนี้เป็นซอฟต์แวร์ฟรี คุณสามารถแจกจ่ายซ้ำและ/หรือแก้ไขได้ภายใต้เงื่อนไขของ GNU General Public License (GPL) เวอร์ชัน 3 หรือเวอร์ชันที่ใหม่กว่า |
| เวอร์ชันที่คุณเลือกตามที่เผยแพร่โดย Free Software Foundation |
| หมายเหตุ: ลิขสิทธิ์ (c) 2020 โดย C. A. Lettsome Services, LLC |
| สำหรับข้อมูลเพิ่มเติม โปรดไปที่ |
| */ |
| #define SAMPLES 128 // สูงสุด 128 สำหรับ Arduino Uno |
| #define SAMPLING_FREQUENCY 2048 //Fs = ขึ้นอยู่กับ Nyquist ต้องเป็น 2 เท่าของความถี่ที่คาดไว้สูงสุด |
| #define OFFSETSAMPLES 40 // ใช้เพื่อวัตถุประสงค์ในการสอบเทียบ |
| #define TUNER -3 //ปรับจนกระทั่ง C3 เป็น 130.50 |
| การสุ่มตัวอย่างลอยตัวระยะเวลา; |
| microSeconds แบบยาวที่ไม่ได้ลงนาม |
| int X[ตัวอย่าง]; //สร้างเวกเตอร์ขนาด SAMPLES เพื่อเก็บค่าจริง |
| float autoCorr[ตัวอย่าง]; //สร้างเวกเตอร์ขนาด SAMPLES เพื่อเก็บค่าจินตภาพ |
| float ที่เก็บไว้NoteFreq[12] = {130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94}; |
| int sumOffSet = 0; |
| int offSet[OFFSETSAMPLES]; //สร้าง offset vector |
| int avgOffSet; //สร้าง offset vector |
| int i, k, periodEnd, periodBegin, period, adjuster, noteLocation, octaveRange; |
| ลอย maxValue, minValue; |
| ผลรวมยาว; |
| int นวดข้าว = 0; |
| int numOfCycles = 0; |
| สัญญาณลอยความถี่, สัญญาณความถี่2, สัญญาณความถี่3, สัญญาณความถี่Guess, รวม; |
| ไบต์ state_machine = 0; |
| ตัวอย่าง int ช่วงเวลา = 0; |
| การตั้งค่าเป็นโมฆะ () |
| { |
| Serial.begin(115200); //115200 อัตราบอดสำหรับ Serial Monitor |
| } |
| วงเป็นโมฆะ () |
| { |
| //***************************************************************** |
| //ส่วนสอบเทียบ |
| //***************************************************************** |
| Serial.println("กำลังสอบเทียบ กรุณาอย่าเล่นโน้ตใดๆ ในระหว่างการสอบเทียบ"); |
| สำหรับ (i = 0; i < OFFSETSAMPLES; i++) |
| { |
| offSet = analogRead(0); // อ่านค่าจากพินอะนาล็อก 0 (A0) หาปริมาณและบันทึกเป็นเทอมจริง |
| //Serial.println(ออฟเซ็ต); // ใช้สิ่งนี้เพื่อปรับโมดูลการตรวจจับเสียงเป็นประมาณครึ่งหนึ่งหรือ 512 เมื่อไม่มีเสียงเล่น |
| sumOffSet = sumOffSet + offSet; |
| } |
| ตัวอย่างPerPeriod = 0; |
| ค่าสูงสุด = 0; |
| //***************************************************************** |
| //เตรียมรับข้อมูลจาก A0 |
| //***************************************************************** |
| avgOffSet = รอบ (sumOffSet / OFFSETSAMPLES); |
| Serial.println("นับถอยหลัง"); |
| ล่าช้า (1000); //หยุด 1 วินาที |
| Serial.println("3"); |
| ล่าช้า (1000); //หยุด 1 วินาที |
| Serial.println("2"); |
| ล่าช้า (1000); //หยุด 1 |
| Serial.println("1"); |
| ล่าช้า (1000); //หยุด 1 วินาที |
| Serial.println("เปิดโน้ตของคุณ!"); |
| ล่าช้า (250); // หยุดชั่วคราวเป็นเวลา 1/4 วินาทีสำหรับเวลาตอบสนอง |
| //***************************************************************** |
| // รวบรวมตัวอย่าง SAMPLES จาก A0 พร้อมช่วงตัวอย่างของแซมปลิ้ง |
| //***************************************************************** |
| ช่วงสุ่มตัวอย่าง = 1.0 / SAMPLING_FREQUENCY; //ระยะเวลาในหน่วยไมโครวินาที |
| สำหรับ (i = 0; i < ตัวอย่าง; i++) |
| { |
| ไมโครวินาที = ไมโคร (); //ส่งคืนจำนวนไมโครวินาทีตั้งแต่บอร์ด Arduino เริ่มรันสคริปต์ปัจจุบัน |
| X = analogRead(0); // อ่านค่าจากพินอะนาล็อก 0 (A0) หาปริมาณและบันทึกเป็นเทอมจริง |
| /*เวลารอที่เหลือระหว่างตัวอย่างถ้าจำเป็นเป็นวินาที */ |
| ในขณะที่ (micros() < (microSeconds + (samplingPeriod * 1000000))) |
| { |
| //ไม่ต้องทำอะไรรอก่อน |
| } |
| } |
| //***************************************************************** |
| //ฟังก์ชันสหสัมพันธ์อัตโนมัติ |
| //***************************************************************** |
| สำหรับ (i = 0; i < ตัวอย่าง; i++) //i=delay |
| { |
| ผลรวม = 0; |
| สำหรับ (k = 0; k < SAMPLES - i; k++) // จับคู่สัญญาณกับสัญญาณล่าช้า |
| { |
| ผลรวม = ผลรวม + (((X[k]) - avgOffSet) * ((X[k + i]) - avgOffSet)); //X[k] คือสัญญาณ และ X[k+i] คือเวอร์ชันที่ล่าช้า |
| } |
| autoCorr = ผลรวม / ตัวอย่าง; |
| // เครื่องตรวจสถานะ Peak Detect ครั้งแรก |
| ถ้า (state_machine==0 && i == 0) |
| { |
| thresh = autoCorr * 0.5; |
| state_machine = 1; |
| } |
| else if (state_machine == 1 && i>0 && thresh 0) //state_machine=1, หา 1 คาบสำหรับใช้รอบแรก |
| { |
| maxValue = autoCorr; |
| } |
| อื่น if (state_machine == 1&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0) |
| { |
| periodBegin = i-1; |
| state_machine = 2; |
| numOfCycles = 1; |
| ตัวอย่างPerPeriod = (periodBegin - 0); |
| ระยะเวลา = ตัวอย่างระยะเวลา; |
| ตัวปรับ = TUNER+(50.04 * exp(-0.102 * ตัวอย่างPerPeriod)); |
| signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPeriod)) - ตัวปรับ; // f = fs/N |
| } |
| else if (state_machine == 2 && i>0 && thresh 0) //state_machine=2, ค้นหา 2 ช่วงเวลาสำหรับรอบที่ 1 และ 2 |
| { |
| maxValue = autoCorr ; |
| } |
| อื่น if (state_machine == 2&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0) |
| { |
| periodEnd = i-1; |
| state_machine = 3; |
| numOfCycles = 2; |
| samplePerPeriod = (periodEnd - 0); |
| signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ตัวปรับ; // f = (2*fs)/(2*N) |
| ค่าสูงสุด = 0; |
| } |
| else if (state_machine == 3 && i>0 && thresh 0) //state_machine=3, ค้นหา 3 ช่วงเวลาสำหรับรอบที่ 1, 2 และ 3 |
| { |
| maxValue = autoCorr ; |
| } |
| อื่น if (state_machine == 3&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0) |
| { |
| periodEnd = i-1; |
| state_machine = 4; |
| numOfCycles = 3; |
| samplePerPeriod = (periodEnd - 0); |
| signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ตัวปรับ; // f = (3*fs)/(3*N) |
| } |
| } |
| //***************************************************************** |
| //การวิเคราะห์ผลลัพธ์ |
| //***************************************************************** |
| ถ้า (samplesPerPeriod == 0) |
| { |
| Serial.println("อืม….. ฉันไม่แน่ใจ คุณกำลังพยายามหลอกฉันอยู่หรือเปล่า?"); |
| } |
| อื่น |
| { |
| //เตรียมฟังก์ชั่นการถ่วงน้ำหนัก |
| รวม = 0; |
| ถ้า (สัญญาณความถี่ !=0) |
| { |
| รวม = 1; |
| } |
| ถ้า(สัญญาณความถี่2 !=0) |
| { |
| รวม = รวม + 2; |
| } |
| ถ้า (สัญญาณความถี่3 !=0) |
| { |
| รวม = รวม + 3; |
| } |
| //คำนวณความถี่โดยใช้ฟังก์ชันการถ่วงน้ำหนัก |
| signalFrequencyGuess = ((1/ทั้งหมด) * signalFrequency) + ((2/รวม) * signalFrequency2) + ((3/ทั้งหมด) * signalFrequency3); // ค้นหาความถี่ถ่วงน้ำหนัก |
| Serial.print("โน้ตที่คุณเล่นอยู่ประมาณ "); |
| Serial.print(สัญญาณความถี่Guess); //พิมพ์ความถี่เดา |
| Serial.println("Hz."); |
| // ค้นหาช่วงอ็อกเทฟตามการเดา |
| อ็อกเทฟเรนจ์=3; |
| ในขณะที่ (!(signalFrequencyGuess >= เก็บไว้NoteFreq[0]-7 && signalFrequencyGuess <= เก็บไว้NoteFreq[11]+7)) |
| { |
| สำหรับ(i = 0; i < 12; i++) |
| { |
| storeNoteFreq = 2 * ที่เก็บไว้NoteFreq; |
| } |
| อ็อกเทฟเรนจ์++; |
| } |
| // ค้นหาโน้ตที่ใกล้ที่สุด |
| ค่าต่ำสุด = 10000000; |
| noteLocation = 0; |
| สำหรับ (i = 0; i < 12; i++) |
| { |
| if(minValue> abs(signalFrequencyGuess-storedNoteFreq)) |
| { |
| minValue = เอบีเอส (signalFrequencyGuess-storedNoteFreq); |
| noteLocation = ผม; |
| } |
| } |
| //พิมพ์โน้ต |
| Serial.print("ฉันคิดว่าคุณเล่น"); |
| ถ้า(noteLocation==0) |
| { |
| Serial.print ("C"); |
| } |
| อื่น if(noteLocation==1) |
| { |
| Serial.print("C#"); |
| } |
| อื่น if(noteLocation==2) |
| { |
| Serial.print ("D"); |
| } |
| อื่น ๆ ถ้า (noteLocation==3) |
| { |
| Serial.print("D#"); |
| } |
| อื่น ๆ ถ้า (noteLocation==4) |
| { |
| Serial.print("E"); |
| } |
| อื่น ๆ ถ้า (noteLocation==5) |
| { |
| Serial.print ("F"); |
| } |
| อื่น if(noteLocation==6) |
| { |
| Serial.print("F#"); |
| } |
| อื่น ๆ ถ้า (noteLocation==7) |
| { |
| Serial.print ("G"); |
| } |
| อื่น ๆ ถ้า (noteLocation==8) |
| { |
| Serial.print("G#"); |
| } |
| อื่น if(noteLocation==9) |
| { |
| Serial.print ("A"); |
| } |
| อื่น if(noteLocation==10) |
| { |
| Serial.print("A#"); |
| } |
| อื่น if(noteLocation==11) |
| { |
| Serial.print ("B"); |
| } |
| Serial.println (ช่วงแปดเสียง); |
| } |
| //***************************************************************** |
| //หยุดตรงนี้. กดปุ่มรีเซ็ตบน Arduino เพื่อรีสตาร์ท |
| //***************************************************************** |
| ในขณะที่ (1); |
| } |
ดู rawgistfile1.txt ที่โฮสต์ด้วย ❤ โดย GitHub
ขั้นตอนที่ 3: ตั้งค่าตัวตรวจจับโน้ตดนตรี
เชื่อมต่อ Arduino Uno กับพีซีด้วยรหัสที่เขียนหรือโหลดใน Arduino IDE รวบรวมและอัปโหลดรหัสไปยัง Arduino วางวงจรไว้ใกล้กับแหล่งดนตรี หมายเหตุ: ในวิดีโอแนะนำ ฉันใช้แอพที่ติดตั้งบนแท็บเล็ตร่วมกับลำโพง PC เป็นแหล่งเพลงของฉัน กดปุ่มรีเซ็ตบนบอร์ด Arduino แล้วเล่นโน้ตบนแหล่งเพลง หลังจากนั้นไม่กี่วินาที Musical Note Detector จะแสดงโน้ตที่เล่นและความถี่
แนะนำ:
การออกแบบเกมในการสะบัดใน 5 ขั้นตอน: 5 ขั้นตอน
การออกแบบเกมในการสะบัดใน 5 ขั้นตอน: การตวัดเป็นวิธีง่ายๆ ในการสร้างเกม โดยเฉพาะอย่างยิ่งเกมปริศนา นิยายภาพ หรือเกมผจญภัย
การตรวจจับใบหน้าบน Raspberry Pi 4B ใน 3 ขั้นตอน: 3 ขั้นตอน
การตรวจจับใบหน้าบน Raspberry Pi 4B ใน 3 ขั้นตอน: ในคำแนะนำนี้ เราจะทำการตรวจจับใบหน้าบน Raspberry Pi 4 ด้วย Shunya O/S โดยใช้ Shunyaface Library Shunyaface เป็นห้องสมุดจดจำใบหน้า/ตรวจจับใบหน้า โปรเจ็กต์นี้มีจุดมุ่งหมายเพื่อให้เกิดความเร็วในการตรวจจับและจดจำได้เร็วที่สุดด้วย
วิธีการติดตั้งปลั๊กอินใน WordPress ใน 3 ขั้นตอน: 3 ขั้นตอน
วิธีการติดตั้งปลั๊กอินใน WordPress ใน 3 ขั้นตอน: ในบทช่วยสอนนี้ ฉันจะแสดงขั้นตอนสำคัญในการติดตั้งปลั๊กอิน WordPress ให้กับเว็บไซต์ของคุณ โดยทั่วไป คุณสามารถติดตั้งปลั๊กอินได้สองวิธี วิธีแรกคือผ่าน ftp หรือผ่าน cpanel แต่ฉันจะไม่แสดงมันเพราะมันสอดคล้องกับ
การลอยแบบอะคูสติกด้วย Arduino Uno ทีละขั้นตอน (8 ขั้นตอน): 8 ขั้นตอน
การลอยแบบอะคูสติกด้วย Arduino Uno ทีละขั้นตอน (8 ขั้นตอน): ตัวแปลงสัญญาณเสียงล้ำเสียง L298N Dc ตัวเมียอะแดปเตอร์จ่ายไฟพร้อมขา DC ตัวผู้ Arduino UNOBreadboardวิธีการทำงาน: ก่อนอื่น คุณอัปโหลดรหัสไปยัง Arduino Uno (เป็นไมโครคอนโทรลเลอร์ที่ติดตั้งดิจิตอล และพอร์ตแอนะล็อกเพื่อแปลงรหัส (C++)
เครื่อง Rube Goldberg 11 ขั้นตอน: 8 ขั้นตอน
เครื่อง 11 Step Rube Goldberg: โครงการนี้เป็นเครื่อง 11 Step Rube Goldberg ซึ่งออกแบบมาเพื่อสร้างงานง่ายๆ ในรูปแบบที่ซับซ้อน งานของโครงการนี้คือการจับสบู่ก้อนหนึ่ง
