วงจร

วิธีการสร้างกีตาร์อากาศด้วย Arduino, Aka the AIRduino Guitar: 5 ขั้นตอน

Arduino basics#1!!

Arduino basics#1!!

สารบัญ:

Anonim

  • ความคิดที่นี่คือการสร้างกีต้าร์เสมือนจริงที่สวมใส่ได้ซึ่งจะถูกควบคุมด้วยสองมือเหมือนกับการเล่น 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);
    }
    ------------------------------------------------------