这里的想法是建立一个可穿戴的虚拟吉他,用双手控制,就像播放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);
}
------------------------------------------------------