在过去的几周里,我一直在努力重新与我对吉他的热爱联系起来。弹奏箱式吉他是我在萨克斯管接管之前的几年前放松的方式。回到吉他,在3年很少弹奏和弦之后,我发现我不再知道每根弦应该如何发声,用我朋友的话来说,“我的听力不再调谐”,因此,如果没有键盘或移动应用程序的帮助,我无法调吉他后来下载。几周过去了,直到几天前,我的制造商变得有动力,我决定建立一个基于Arduino的吉他调音器。在今天的教程中,我将分享如何构建自己的DIY Arduino吉他调音器。
吉他调谐器的工作原理
在我们转向电子产品之前,了解构建背后的原理很重要。有 7 个主要音符由字母表示;A,B,C,D,E,F,G,通常以另一个A结尾,该A始终比第一个A高一个八度。在音乐中,这些音符存在几个版本,如第一个A和最后一个A。这些音符分别与它们的变化区分开来,并通过称为音高的声音特征之一来区分彼此。音高被定义为声音的响度或低度,并由该声音的频率表示。由于这些音符的频率是已知的,因此要确定吉他是否调音,我们只需要将特定弦的音符频率与弦所代表的音符的实际频率进行比较即可。
7个音符的频率是:
A = 27.50Hz
B = 30.87Hz
C = 16.35Hz
D = 18.35Hz
E = 20.60Hz
F = 21.83Hz
G = 24.50 Hz
这些音符的每个变化总是在等于 FxM 的音高,其中 F 是频率,M 是非零整数。因此,对于如前所述比第一个 A 高一个八度的最后一个 A,频率是;
27.50 x 2 = 55Hz。
吉他(主音/盒式吉他)通常有 6 根弦,由开弦上的音符 E、A、D、G、B、E 表示。像往常一样,最后一个 E 将比第一个 E 高一个八度。我们将设计我们的吉他调音器,以帮助使用这些音符的频率调整吉他。
根据标准的吉他调音,每根弦的音符和相应的频率如下表所示。
字符串 | 频率 | 表示法 |
1 (E) | 329.63赫兹 | E4 |
2 (B) | 246.94赫兹 | B3 |
3 (G) | 196.00赫兹 | G3 |
4 (D) | 146.83赫兹 | D3 |
5 (一) | 110.00赫兹 | 答2 |
6 (E) | 82.41赫兹 | E2 |
项目流程非常简单;我们将吉他产生的声音信号转换为频率,然后与被调谐琴弦的确切频率值进行比较。当值相关时,使用 LED 通知吉他手。
频率检测/转换涉及 3 个主要阶段;
放大
抵消
模数转换(采样)
产生的声音信号太弱,Arduino的ADC无法识别,因此我们需要放大信号。放大后,为了将信号保持在Arduino的ADC可识别的范围内以防止信号削波,我们偏移了信号的电压。偏移后,信号被传递到Arduino ADC,在那里对其进行采样并获得该声音的频率。
必需组件
生成此项目需要以下组件;
阿杜伊诺乌诺 x1
LM386 x1
电容麦克风 x1
麦克风/音频插孔 x1
10k 电位器 x1
O.1uf 电容器 x2
100欧姆电阻 x4
10欧姆电阻 x1
10uF 电容器 x3
5毫米黄色发光二极管 x2
5毫米绿色发光二极管 x1
常开按钮 x6
跳线
面包板
图表
连接组件,如下面的吉他调谐器电路图所示。
按钮连接时没有上拉/下拉电阻,因为将使用Arduino内置的上拉电阻。这是为了确保电路尽可能简单。
吉他调谐器的Arduino代码
这个吉他调音器项目代码背后的算法很简单。为了调音特定的琴弦,吉他手通过按下相应的按钮来选择琴弦,然后弹奏一根开放的琴弦。声音由放大级收集并传递到Arduino ADC。对频率进行解码和比较。当串的输入频率小于指定频率时,对于该串,其中一个黄色 LED 亮起,指示应拧紧串。当测量的频率大于该串的规定频率时,另一个 LED 亮起。当频率在该弦的规定范围内时,绿色 LED 亮起以引导吉他手。
最后给出了完整的Arduino代码,这里我们简要解释了代码的重要部分。
我们首先创建一个数组来容纳开关。
int buttonarray[] = {13, 12, 11, 10, 9, 8}; // [E2, A2, D3, G3, B3, E4]
接下来,我们创建一个数组来保存每个字符串的相应频率。
float freqarray[] = {82.41, 110.00, 146.83, 196.00, 246.94, 329.63};//all in Hz
完成此操作后,我们声明LED连接的引脚以及将用于从ADC获取频率的其他变量。
int lowerLed = 7;
int higherLed = 6;
int justRight = 5;
#define LENGTH 512
byte rawData[LENGTH];
int count;
接下来是 void setup() 函数。
在这里,我们首先为开关连接到的每个引脚启用Arduino上的内部上拉。之后,我们将LED连接的引脚设置为输出,并启动串行监视器以显示数据。
void setup()
{
for (int i=0; i<=5; i++)
{
pinMode(buttonarray[i], INPUT_PULLUP);
}
pinMode(lowerLed, OUTPUT);
pinMode(higherLed, OUTPUT);
pinMode(justRight, OUTPUT);
Serial.begin(115200);
}
接下来,就是空隙环路功能,我们实现频率检测和比较。
void loop(){
if (count < LENGTH)
{
count++;
rawData[count] = analogRead(A0)>>2;
}
else {
sum = 0;
pd_state = 0;
int period = 0;
for(i=0; i < len; i++)
{
// Autocorrelation
sum_old = sum;
sum = 0;
for(k=0; k < len-i; k++) sum += (rawData[k]-128)*(rawData[k+i]-128)/256;
// Serial.println(sum);
// Peak Detect State Machine
if (pd_state == 2 && (sum-sum_old) <=0)
{
period = i;
pd_state = 3;
}
if (pd_state == 1 && (sum > thresh) && (sum-sum_old) > 0) pd_state = 2;
if (!i) {
thresh = sum * 0.5;
pd_state = 1;
}
}
// Frequency identified in Hz
if (thresh >100) {
freq_per = sample_freq/period;
Serial.println(freq_per);
for (int s=0; s<=5; s++)
{
if (digitalRead(buttonarray[i])== HIGH)
{
if (freq_per - freqarray[i] < 0)
{
digitalWrite(lowerLed, HIGH);
}
else if(freq_per - freqarray[i] > 10)
{
digitalWrite(higherLed, HIGH);
}
else
{
digitalWrite(justRight, HIGH);
}
}
}
}
count = 0;
}
}
全部0条评论
快来发表一下你的评论吧 !