ความคิดที่นี่คือการสร้างกีต้าร์เสมือนจริงที่สวมใส่ได้ซึ่งจะถูกควบคุมด้วยสองมือเหมือนกับการเล่น Air Guitar มันถูกสร้างและสร้างต้นแบบในระหว่างโครงการสองสัปดาห์ที่
จุดมุ่งหมายคือการรับความรู้สึกในการเล่นกีตาร์จริง กีต้าร์ AIRduino ทำจากถุงมือหนึ่งอันและแท่งเดียวถุงมือถูกใช้เพื่อตั้งค่าเสียงและไม้เพื่อเรียกเสียง
เพื่อทำการหลอกลวงดังกล่าวเราใช้ accelerometer และเซ็นเซอร์อุลตร้าโซนิค (ดูขั้นตอนที่ 1 สำหรับคำอธิบายแนวคิด)
ดูวิดีโอสาธิตเพื่อรับแนวคิดที่แม่นยำยิ่งขึ้นเกี่ยวกับวิธีการทำงานและทำงานเพื่อสร้างของคุณเอง!
ทีม AIRduino:
David Fournier, Jean-Louis Giordano, Monireh Sanaei, Maziar Shelbaf และ Gustav Sohtell
วัสดุ:
ขั้นตอนที่ 1: คำอธิบายแนวคิด
Air Guitar ควรจะทำงานเป็นกีตาร์มือขวา
ตัวควบคุมกีตาร์แบ่งออกเป็นสองส่วนคือตัวควบคุมซ้ายและตัวควบคุมทางขวา
โดยผู้ควบคุมมือซ้ายผู้เล่นสามารถงอนิ้วของเขาและกดถุงมือเพื่อเปลี่ยนระดับเสียง
ตัวควบคุมด้านขวานั้นถูกแสดงด้วยแท่งไม้ซึ่งต้องเขย่าเพื่อกระตุ้นเสียงของกีตาร์อากาศ
ผู้เล่นยังสามารถเปลี่ยนระยะห่างระหว่างมือขวาและมือซ้ายเพื่อปรับโทนเสียงจำลองความวิตกกังวลต่าง ๆ ที่คอกีตาร์
เพื่อทำกลอุบายดังกล่าวส่วนประกอบหลักคือ accelerometer เพื่อ "รู้สึก" ติดสั่นเซ็นเซอร์อัลตร้าโซนิคที่ถูกแฮ็กเพื่อวัดระยะห่างระหว่างมือขวาและมือขวาและผ้าที่เป็นสื่อกระแสไฟฟ้าเพื่อสร้างถุงมือ
สรุปแล้วมันเป็นเรื่องง่ายที่จะสร้างของเล่น ส่วนที่ยุ่งยากเพียงอย่างเดียวคือการแฮ็กเซ็นเซอร์อัลตร้าโซนิคซึ่งต้องการความชำนาญ คุณจะต้องมีทักษะอิเล็กทรอนิกส์ขั้นพื้นฐานเพื่อทำความเข้าใจคำแนะนำและเพื่อค้นหาสิ่งที่คุณทำผิดเมื่อคุณทำบางสิ่งบางอย่างยุ่งเหยิงและกีตาร์ไม่ทำงานในที่สุด เราเคยไปที่นั่น :-)
ขั้นตอนที่ 2: รายการช็อปปิ้ง
นี่คือรายการของสิ่งที่คุณต้องการในการสร้าง AIRduino Guitar ของคุณเอง:
1. สาย: น่าเสียดายมากสำหรับรุ่นต้นแบบนี้ พวกมันถูกใช้เพื่อเชื่อมต่อถุงมือสองชิ้นและชิ้นส่วน Arduino เข้าด้วยกัน รู้สึกอิสระที่จะปรับปรุงส่วนนี้ของการออกแบบโดยการทำให้ไร้สาย!
2. มาตรวัดความเร่ง: ใช้ในแท่งในมือขวาของคุณเพื่อตรวจจับการสั่น เราใช้ Accellerometer แบบสามแกน แต่หนึ่งแกนก็เพียงพอแล้ว
3. เซ็นเซอร์อัลตราโซนิก: ใช้ในการวัดระยะห่างระหว่างมือทั้งสองของผู้เล่นเราใช้ Parallax # 28015
4. ผ้าเป็นสื่อกระแสไฟฟ้าและผ้ายืด: เพื่อสร้างถุงมือ
5. Arduino: แกนกลางของกีตาร์ที่จัดการทุกอย่าง Arduino Diecimila ทำงานได้ดี
6. โพเทนชิโอมิเตอร์: เพื่อปรับการตั้งค่าบางอย่างโพเทนชิออมิเตอร์ที่มีค่าสูงสุดตั้งแต่ 1KOhm-1MOhm ก็โอเค
7. กาวร้อนละลาย: วิธีที่สะดวกในการเก็บสิ่งต่าง ๆ ไว้ด้วยกัน
8. แจ็คหญิง 3.5 มม.: ใช้สำหรับเอาท์พุทเสียง
9. อุปกรณ์อิเล็กทรอนิกส์คลาสสิก: ตัวต้านทาน (10k) ตัวเก็บประจุ (10uF) ไฟ LED และแหล่งจ่ายไฟบางชนิดสำหรับอาร์ดิโน (แบตเตอรี่ขนาด 9 โวลต์ก็ใช้ได้)
ขั้นตอนที่ 3: แผนงาน
นี่คือแผนผังอิเล็กทรอนิกส์สำหรับกีตาร์อะแดปเตอร์ AIR
อย่างที่คุณเห็นมันค่อนข้างง่ายที่จะเข้าใจและดังนั้นจึงต้องสร้าง
ดูภาพถ้าคุณต้องการความคิดว่าองค์ประกอบไหนไป อย่างที่คุณอาจจะเข้าใจนี่ไม่ได้เป็นการขยายขนาด แต่อย่างใด สายเคเบิลมีความยาวมากกว่าที่แสดงในแผนผัง
คุณอาจสังเกตเห็นว่าตัวส่งสัญญาณของเซ็นเซอร์อุลตร้าโซนิคโซนิคติดกับตัวรับและตัวรับสัญญาณอยู่ทางซ้ายมือ นั่นคือส่วนที่ยุ่งยากที่ฉันได้กล่าวถึงก่อนหน้านี้: คุณต้องปลดอิมิเตอร์แบบคลื่นอุลตร้าโซนิคจากชุดเซ็นเซอร์อัลตร้าโซนิคเพื่อแยกมันออกจากบอร์ดเซ็นเซอร์
เพิ่มเติมเกี่ยวกับที่ในขั้นตอนภายหลัง ตอนนี้ไปทำงานกันเถอะ!
ขั้นตอนที่ 4: การสร้างถุงมือ
ถุงมือประกอบด้วยตัวรับคลื่นอัลตร้าโซนิคหนึ่งตัวและปุ่มสี่ปุ่ม แค่นั้นแหละ!
ตัวรับสัญญาณอัลตร้าโซนิคตั้งอยู่ในกล่องดำที่มองเห็นได้จากรูปภาพด้านล่าง
ถุงมือมีพื้นที่ขนาดใหญ่เพียงจุดเดียวที่เชื่อมต่อกับพื้นดินบนบอร์ด Arduino เมื่อกดนิ้วลงบนฝ่ามือจะมีการสร้างการเชื่อมต่อระหว่างผ้าที่เป็นสื่อกระแสไฟฟ้าบนนิ้วและฝ่ามือ
ด้านล่างเป็นภาพถุงมือสองรุ่นที่แตกต่างกัน หนึ่งมีนิ้วที่ถอดออกได้ซึ่งช่วยให้ผู้เล่นทั้งสองด้วยมือเล็กและใหญ่มาก อีกรุ่นถูกเย็บติดกับถุงมือมาตรฐาน ฉันอยากจะแนะนำรุ่นที่สองมันง่ายกว่าที่จะสร้างและง่ายต่อการใส่
ขั้นตอนที่ 5: รหัส
นี่คือรหัส Arduino ที่ต้องการ:
ส่วนการสร้างเสียงตามเวลาจริงนำมาจากบทช่วยสอนที่ยอดเยี่ยมนี้
------------------------------------------------------
// อาร์เรย์ที่มีรูปคลื่น
// ของเสียงกีตาร์
รูปคลื่นถ่าน =
{125, 148, 171, 194, 209, 230, 252, 255,
253, 244, 235, 223, 207, 184, 169, 167,
163, 158, 146, 131, 126, 129, 134, 127,
105, 80, 58, 51,38, 22, 12, 2, 10, 35,
58, 75, 89, 103, 120, 141, 150, 148, 145,
144, 140, 129, 116, 105, 95, 86, 75, 72,
73, 76, 88, 103, 117, 121, 120, 115, 120,
143, 159, 162, 156, 155, 163, 184, 202,
214, 215, 211, 213, 212, 205, 196, 182,
162, 142, 118, 99, 84, 68, 54, 40, 28,
19, 10, 7, 0, 0, 5, 9, 14, 21, 33,
49, 59, 65, 75, 92, 110};
// เราใช้รูปคลื่นนี้เพื่อเปลี่ยน
// ปริมาณการส่งออก
ถ่าน waveformVolume =
{125, 148, 171, 194, 209, 230, 252, 255,
253, 244, 235, 223, 207, 184, 169, 167,
163, 158, 146, 131, 126, 129, 134, 127,
105, 80, 58, 51,38, 22, 12, 2, 10, 35,
58, 75, 89, 103, 120, 141, 150, 148, 145,
144, 140, 129, 116, 105, 95, 86, 75, 72,
73, 76, 88, 103, 117, 121, 120, 115, 120,
143, 159, 162, 156, 155, 163, 184, 202,
214, 215, 211, 213, 212, 205, 196, 182,
162, 142, 118, 99, 84, 68, 54, 40, 28,
19, 10, 7, 0, 0, 5, 9, 14, 21, 33,
49, 59, 65, 75, 92, 110};
// อาร์เรย์ที่ใช้เป็นบัฟเฟอร์เพื่อหลีกเลี่ยง
// ระยะทางที่ผิดพลาด
// การวัด
int distance_buffer ไม่ได้ลงนาม = {16000,
16000, 16000, 16000, 16000, 16000, 16000,
16000, 16000, 16000, 16000, 16000, 16000,
16000, 16000, 16000};
const int distance_length = 3;
int distance_index = 0;
// ค่าโอเวอร์โฟลสำหรับ 2 อ็อกเตฟ
ความถี่ภายใน = {39, 42, 44, 47,
50, 52, 56, 59, 63, 66, 70, 74, 79,
84, 89, 94, 100, 105, 112, 118, 126,
133, 141, 149};
// ระดับเสียงเริ่มต้น
int pitch = 160;
// ปริมาณเริ่มต้นและการเร่งความเร็ว
// พารามิเตอร์
int lastAcc = 0;
ปริมาณลอย = 0;
// การเล่นเสียงที่ขา 3
byte speakerpin = 3;
// ตัวแปรดัชนีสำหรับตำแหน่งใน
// รูปแบบของคลื่น
ไบต์ระเหย waveindex = 0
ไบต์ปัจจุบันระเหยได้ = 0;
// พินที่ใช้สำหรับเซ็นเซอร์อุลตร้าโซนิค
const int pingPin = 7;
// พินสำหรับโพเทนชิโอมิเตอร์
const int sustPin = 1;
const int sensitivityPin = 2;
// พินสำหรับแต่ละนิ้วของซ้าย
// มือ
const int finger1 = 9;
const int finger2 = 10;
const int finger3 = 11;
const int finger4 = 12;
int fingerValue = 0;
ระยะเวลานาน, นิ้ว, ซม.;
การตั้งค่าเป็นโมฆะ () {
pinMode (3, OUTPUT); // ลำโพงที่ขา 3
pinMode (finger1, INPUT);
pinMode (finger2, INPUT);
pinMode (finger3, INPUT);
pinMode (finger4, INPUT);
/**************************
การกำหนดค่าเสียง PWM
****************************/
// ตั้งค่า Timer2 เป็นโหมด PWM ที่รวดเร็ว
// (ความถี่ PWM สองเท่า)
bitSet (TCCR2A, WGM21);
bitSet (TCCR2B, CS20);
bitClear (TCCR2B, CS21);
bitClear (TCCR2B, CS22);
// เปิดใช้งานการขัดจังหวะในขณะนี้ที่ลงทะเบียน
// ได้รับการตั้งค่าแล้ว
เซอิ ();
/*************************
ตัวจับเวลาขัดจังหวะการกำหนดค่า 1
*************************/
// ปิดการใช้งานอินเตอร์รัปต์ขณะที่
// การกำหนดค่ารีจิสเตอร์
CLI ();
/ * การทำงานของพอร์ตปกติ, หมุดหลุด
จากการทำงานของตัวจับเวลา (ตัวแบ่ง pwm) * /
bitClear (TCCR1A, COM1A1);
bitClear (TCCR1A, COM1A1);
bitClear (TCCR1A, COM1A1);
bitClear (TCCR1A, COM1A1);
/ * โหมด 4, CTC พร้อมชุด TOP โดยการลงทะเบียน
OCR1A ช่วยให้เราสามารถตั้งเวลาตัวแปรสำหรับ
ขัดจังหวะโดยการเขียนค่าใหม่ให้กับ
OCR1A * /
bitClear (TCCR1A, WGM10);
bitClear (TCCR1A, WGM11);
bitSet (TCCR1B, WGM12);
bitClear (TCCR1B, WGM13);
/ * ตั้งค่านาฬิกาล่วงหน้าเป็น / 8 * /
bitClear (TCCR1B, CS10);
bitSet (TCCR1B, CS11);
bitClear (TCCR1B, CS12);
/ * ปิดใช้งานการเปรียบเทียบแรงส่งออกสำหรับ
แชแนล A และ B * /
bitClear (TCCR1C, FOC1A);
bitClear (TCCR1C, FOC1B);
/ * เริ่มต้นเปรียบเทียบผลลัพธ์
ลงทะเบียน A ที่ 160 เพื่อตั้งค่า
ระยะห่างเริ่มต้น * /
OCR1A = 160;
// ปิดการใช้งานการดักจับสัญญาณเข้าขัดจังหวะ
bitClear (TIMSK1, ICIE1);
// ปิดการใช้งานเอาต์พุต
// เปรียบเทียบ B Match Interrupt
bitClear (TIMSK1, OCIE1B);
// เปิดใช้งานเอาต์พุต
// เปรียบเทียบการขัดจังหวะการแข่งขัน
bitSet (TIMSK1, OCIE1A);
// ปิดการใช้งาน Overflow Interrupt
bitClear (TIMSK1, TOIE1);
// เปิดใช้งานการขัดจังหวะในตอนนี้
// ลงทะเบียนเรียบร้อยแล้ว
เซอิ ();
}
// Timer ตัวจัดการล้น
ISR (TIMER1_COMPA_vect) {
/ * timer1 ISR ทุกครั้งนะค่ะ
เรียกว่าตั้งค่าสปีกเกอร์โฟนเป็น
ค่าถัดไปในรูปแบบของคลื่น ความถี่
การปรับจะทำโดยการเปลี่ยน
เวลาระหว่างการโทรติดต่อกันของ
ฟังก์ชั่นนี้เช่น สำหรับเสียง 1KHz
กำหนดเวลาเพื่อให้มันทำงาน
ผ่านรูปคลื่น 1,000 ครั้ง
วินาที. * /
// รีเซ็ต waveindex หากถึงแล้ว
// จุดสิ้นสุดของอาร์เรย์
if (waveindex> 102) {
waveindex = 0;
}
// ตั้งค่าเอาต์พุต
ถ้า (ปริมาณ> 0.03) {
analogWrite (speakerpin,
waveformVolume waveindex);
}
waveindex ++;
// อัปเดตสนาม
OCR1A = ระดับเสียง;
}
เป็นโมฆะห่วง ()
{
// ปิดใช้งาน interputs ส่ง ping
// ข้อความและรอคำตอบ
CLI ();
pinMode (pingPin, OUTPUT);
digitalWrite (pingPin, LOW);
delayMicroseconds (2);
digitalWrite (pingPin, HIGH);
delayMicroseconds (5)
digitalWrite (pingPin, LOW);
duration = pulseIn (pingPin, HIGH, 2000);
เซอิ ();
// แปลงเวลาเป็นระยะทาง
// ในหน่วยเซนติเมตร
// และเก็บไว้ในบัฟเฟอร์
distance_buffer distance_index ++
% distance_length = ระยะเวลา / 20;
// ค้นหาในบัฟเฟอร์ที่สั้นที่สุด
// ระยะทางวัด
cm = 16000;
สำหรับ (int i = 0; i <distance_length; i ++) {
cm = min (cm, distance_buffer i);
}
// ตรวจสอบนิ้วมือที่กด
fingerValue = 5;
ถ้า (! digitalRead (finger4)) {
fingerValue = 4;
}
ถ้า (! digitalRead (finger3)) {
fingerValue = 3;
}
ถ้า (! digitalRead (finger2)) {
fingerValue = 2;
}
ถ้า (! digitalRead (finger1)) {
fingerValue = 1;
}
// อัพเดทความยั่งยืนและ
// ค่าความไว
ทุ่นลอยน้ำ =
แผนที่ (อะนาล็อกอ่าน (SustainPin), 0,
1024, 101, 130) / 100.0;
ความไว int =
แผนที่ (analogRead (sensitivityPin)
0, 1024, 100, 200);
// อัปเดตโวลุ่ม
ปริมาณ = ปริมาณ / การสนับสนุน;
if (ปริมาณ <0) {
ปริมาณ = 0;
}
// ตรวจสอบมาตรความเร่ง
int acc = analogRead (0);
int accDiff = lastAcc - acc;
// อัปเดตค่าระดับเสียง
if (accDiff> 5 * (200 - ความไว)) {
ปริมาณ + = (ลอย)
ธาร (accDiff,
ความไว / 100.0) / 50000;
}
lastAcc = acc;
// ตรวจสอบปริมาณที่ไม่สูงกว่า 1
ถ้า (ปริมาณ> .95) {
ปริมาณ = .95;
}
// อัพเดตระดับเสียงในรูปคลื่น
สำหรับ (int i = 0; i <= 102; i ++) {
waveformVolume i =
((รูปแบบของคลื่น i - 127) * ระดับเสียง) + 127;
}
// ตั้งค่าระยะห่างตามระยะทาง
// ระหว่างมือทั้งสองและ
// นิ้วกด
ถ้า (cm <102 && cm> 0) {
ถ้า (ซม.> 30) {
pitch = ความถี่ 7 +
(((ซม. - 30) / 24) * 4 + fingerValue - 1);
}อื่น{
pitch = map (cm, 0, 30, 39, 79);
}
}อื่น{
pitch = ความถี่ 7 +
(((102 - 30) / 24) * 4 + fingerValue - 1);
}
// ล่าช้าเพื่อหลีกเลี่ยงการสะท้อนสัญญาณ
ล่าช้า (50);
}
------------------------------------------------------