电路

如何用Arduino制作空气吉他,Aka the AIRduino吉他:5个步骤

目录:

Anonim

  • 这里的想法是建立一个可穿戴的虚拟吉他,用双手控制,就像播放Air Guitar一样。它是在为期两周的项目中创建和制作原型的 查默斯大学 (瑞典)用于物理计算类。

    目的是获得演奏真正吉他的感觉。 AIRduino吉他由一个手套和一根棍子组成。手套用于设置音调和手柄以触发声音。

    为了执行这样的技巧,我们使用了加速度计和超声波传感器(参见步骤1的概念描述)。

    看看视频演示,以更准确地了解它的工作原理,并开始构建自己的视频演示!


    AIRduino团队:

    David Fournier,Jean-Louis Giordano,Monireh Sanaei,Maziar Shelbaf和Gustav Sohtell。

    供应:

    第1步:概念描述

    Air Guitar应该是一把右手吉他。
    吉他控制器分为左手控制器和右手控制器两部分。
    通过左手控制器,玩家可以弯曲手指并按下手套以改变音调的音高。
    右手控制器由一根杆子代表,该杆子必须被摇动以触发空气吉他的声音。
    玩家还可以改变右手和左手之间的距离,以便调整音调,模拟吉他琴颈上的不同音品。
    为了执行这样的技巧,主要部件是用于“感觉”摇杆的加速度计,用于测量右手和杆之间距离的黑客超声波传感器,以及用于构建手套的导电织物。
    总而言之,制作玩具相当容易。唯一棘手的部分是超声波传感器黑客需要一定的灵活性。你需要一些基本的电子技能来理解指令,并且当你搞砸了什么并且吉他最终无法工作时,你还要找出你做错了什么。我们一直在那里。 :-)

    第2步:购物清单

    以下列出了构建自己的AIRduino吉他所需的内容:
    1.电线:不幸的是这个原型版本很多。它们被用来将两个手套和Arduino部件连接在一起。通过无线化,随意改进这部分设计!
    2.加速度计:用右手握杆检测摇动。我们使用了三轴accellerometer,但单轴就足够了
    3.超声波传感器:用于测量玩家双手之间的距离,我们使用Parallax#28015
    4.导电和弹力面料:打造手套,
    5. Arduino:吉他的核心,处理一切。 Arduino Diecimila工作得很好。
    6.电位计:调整一些设置,最大值为1KOhm-1MOhm的电位计是可以的。
    7.热熔胶:将物品放在一起的便捷方式,
    8. 3.5毫米母插孔:用于音频输出,
    9.经典电子产品:电阻器(10k),电容器(10uF),LED和arduino的某种电源。 (9V电池就好了)。

    第3步:原理图

    以下是AIRduino Guitar的电子原理图。
    正如您所看到的,它很容易理解,因此也很容易构建。
    如果您想知道哪个组件在哪里,请查看图像。正如您可能理解的那样,这无论如何都无法扩展。电缆比原理图中显示的长得多。
    您可能还注意到超声波传感器的发射器位于杆上,接收器位于左侧。这是我之前提到的棘手部分:你必须从超声波传感器单元拆下超声波发射器,以便将它与传感器板分开。
    更多关于后续步骤的内容。现在让我们开始工作吧!

    第4步:构建手套

    手套包含一个超声波接收器和四个按钮。而已!
    超声波接收器位于下面某些图片中可见的黑匣子中。
    手套有一个大面积,刚刚连接到Arduino板上的地面。当手指压在手掌上时,手指上的导电织物与手掌之间产生连接。
    下面是两种不同手套型号的图片。一个可拆卸的手指,允许双手非常小和非常大的手。另一种型号缝制在标准手套上。我推荐第二个版本,它更容易构建,更容易穿上。

    第5步:代码

    这是所需的Arduino代码:
    实时声音生成部分取自这个伟大的教程。
    ------------------------------------------------------
    //包含波形的数组
    //吉他声
    char波形 =
    {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};
    //我们使用这个波形来改变
    //输出的音量
    char 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};
    //一个用作缓冲区的数组
    //错误的准时距离
    // 测量
    unsigned 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个八度音程的溢出值
    int频率 = {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;
    float volume = 0;
    //针脚3上的音频播放
    byte speakerpin = 3;
    //位置的索引变量
    //波形
    volatile byteinindex = 0
    volatile byte currentvalue = 0;
    //用于超声波传感器的引脚
    const int pingPin = 7;
    //电位器的针脚
    const int sustainPin = 1;
    const int sensitivityPin = 2;
    //左手每个手指的针脚
    //手
    const int finger1 = 9;
    const int finger2 = 10;
    const int finger3 = 11;
    const int finger4 = 12;
    int fingerValue = 0;
    持续时间长,英寸,厘米;
    void setup(){
    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);
    //现在启用中断寄存器
    //已经设定好了
    SEI();

    /*************************
    定时器1中断配置
    *************************/
    //禁用中断
    //寄存器已配置
    CLI();
    / *正常端口操作,引脚断开
    来自计时器操作(打破pwm)* /
    bitClear(TCCR1A,COM1A1);
    bitClear(TCCR1A,COM1A1);
    bitClear(TCCR1A,COM1A1);
    bitClear(TCCR1A,COM1A1);
    / *模式4,通过寄存器设置TOP的CTC
    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);
    / *初始化输出比较
    在160处注册A以设置
    初始音高* /
    OCR1A = 160;
    //禁用输入捕获中断
    bitClear(TIMSK1,ICIE1);
    //禁用输出
    //比较B匹配中断
    bitClear(TIMSK1,OCIE1B);
    //启用输出
    //比较匹配中断
    bitSet(TIMSK1,OCIE1A);
    //禁用溢出中断
    bitClear(TIMSK1,TOIE1);
    //现在启用中断
    //寄存器已设置
    SEI();
    }
    //定时器溢出处理程序
    ISR(TIMER1_COMPA_vect){
    / * timer1 ISR。每一次
    被称为它设置扬声器
    波形中的下一个值。频率
    通过改变来完成调制
    连续呼叫之间的时间间隔
    这个功能,例如对于1KHz音调,
    设定时间以使其运行
    通过波形 1000次
    一秒。 * /
    //重置waveindex(如果已达到)
    //数组的结尾
    if(waveindex> 102){
    waveindex = 0;
    }
    //设置输出值
    if(volume> 0.03){
    analogWrite(speakerpin,
    waveformVolume waveindex);
    }
    waveindex ++;
    //更新音高
    OCR1A =音高;
    }

    void loop()
    {
    //停用输入,发送ping
    //消息并等待答案。
    CLI();
    pinMode(pingPin,OUTPUT);
    digitalWrite(pingPin,LOW);
    delayMicroseconds(2);
    digitalWrite(pingPin,HIGH);
    delayMicroseconds(5);
    digitalWrite(pingPin,LOW);
    duration = pulseIn(pingPin,HIGH,2000);
    SEI();
    //将时间转换为距离
    //以厘米为单位
    //并存储在缓冲区中
    distance_buffer distance_index ++
    %distance_length =持续时间/ 20;
    //在缓冲区中查找最短的
    //测量距离
    cm = 16000;
    for(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;
    }
    //更新延音和
    //敏感度值
    浮动维持=
    map(analogRead(sustainPin),0,
    1024, 101, 130) / 100.0;
    int sensitivity =
    地图(analogRead(sensitivityPin),
    0, 1024, 100, 200);
    //更新音量
    音量=音量/维持;
    if(volume <0){
    体积= 0;
    }

    //检查加速度计
    int acc = analogRead(0);
    int accDiff = lastAcc - acc;
    //更新音量值
    if(accDiff> 5 *(200 - sensitivity)){
    体积+ =(浮动)
    POW(accDiff,
    灵敏度/ 100.0)/ 50000;
    }
    lastAcc = acc;
    //检查音量是否不高于1
    if(volume> .95){
    体积= .95;
    }
    //更新波形中的音量
    for(int i = 0; i <= 102; i ++){
    waveformVolume i =
    ((波形i - 127)*音量)+ 127;
    }
    //根据距离设置音高
    //在两只手之间和
    //手指按下
    if(cm <102 && cm> 0){
    if(cm> 30){
    pitch =频率7 +
    (((cm - 30)/ 24)* 4 + fingerValue - 1);
    }其他{
    pitch = map(cm,0,30,39,79);
    }
    }其他{
    pitch =频率7 +
    (((102 - 30)/ 24)* 4 + fingerValue - 1);
    }
    //延迟避免反弹信号
    延迟(50);
    }
    ------------------------------------------------------