สารบัญ:
- เสบียง
- ขั้นตอนที่ 1: สร้างฮาร์ดแวร์สำหรับตัวตรวจจับโน้ตดนตรี
- ขั้นตอนที่ 2: ตั้งโปรแกรมตัวตรวจจับโน้ตดนตรี
- ขั้นตอนที่ 3: ตั้งค่าตัวตรวจจับโน้ตดนตรี
วีดีโอ: เครื่องตรวจจับโน้ตดนตรี: 3 ขั้นตอน
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:03
ตะลึงพรึงเพริดเพื่อนและครอบครัวของคุณด้วยโปรเจ็กต์นี้ที่ตรวจจับโน้ตที่เล่นโดยเครื่องดนตรี โครงงานนี้จะแสดงความถี่โดยประมาณรวมถึงโน้ตดนตรีที่เล่นบนคีย์บอร์ดอิเล็กทรอนิกส์ แอพเปียโน หรือเครื่องดนตรีอื่นๆ
รายละเอียด
สำหรับโครงการนี้ เอาต์พุตแอนะล็อกจากเครื่องตรวจจับโมดูลเสียงจะถูกส่งไปยังอินพุตอนาล็อก 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 ซึ่งออกแบบมาเพื่อสร้างงานง่ายๆ ในรูปแบบที่ซับซ้อน งานของโครงการนี้คือการจับสบู่ก้อนหนึ่ง