0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用Arduino构建一架小而有趣的钢琴

科技观察员 来源:circuitdigest 作者:里沙布·耆那教 2022-11-14 16:26 次阅读

Arduino对于不是电子背景的人来说是一个福音,可以轻松构建东西。这是一个很棒的原型工具,或者尝试一些很酷的东西,在这个项目中,我们将使用 Arduino 构建一架小而有趣的钢琴。这架钢琴非常简单,只有8个按钮和蜂鸣器。它使用Arduino的tone()函数在扬声器上创建各种类型的钢琴音符。为了给它增添趣味,我们在项目中添加了录音功能,这使我们能够播放一首曲子,并在需要时重复播放。听起来很有趣吧!!所以让我们开始建设吧。

所需材料:

Arduino Uno

16 * 2液晶显示器

蜂鸣器

修剪器 10k

单刀双掷开关

按钮 (8 否)

电阻器 (10k, 560R, 1.5k, 2.6k, 3.9, 5.6k, 6.8k, 8.2k, 10k)

面包板

连接线

电路图:

完整的Arduino钢琴项目可以构建在带有一些连接线的面包板上。使用弗里茨制作的电路图显示了项目的试验板视图,如下所示

pYYBAGNx-7OAG6aYAADjJqq2XPI691.png

只需按照电路图并相应地连接电线,按钮和蜂鸣器与PCB模块一起使用,但在实际硬件中,我们只使用了开关和蜂鸣器,它不应该让您感到困惑,因为它们具有相同类型的引脚输出。您还可以参考下面的硬件图像进行连接。

poYBAGNx-7WAH2seAAC10ag1V2A425.jpg

左起电阻值按以下顺序排列,10k、560R、1.5k、2.6k、3.9、5.6k、6.8k、8.2k 和 10k。如果您没有相同的DPST开关,则可以使用普通的拨动开关,如上面的电路图所示。现在让我们看看项目的原理图,以了解为什么我们进行了以下连接。

原理图和解释:

上面显示的电路图原理图如下,也是使用Fritzing制作的。

pYYBAGNx-7aAASi4AACd3j73el0607.png

我们必须了解的一个主要连接是我们如何通过模拟A8引脚将8个按钮连接到Arduino。基本上我们需要 8 个输入引脚,可以连接到 8 个输入按钮,但对于这样的项目,我们不能将微控制器的 8 个引脚仅用于按钮,因为我们可能需要它们供以后使用。在我们的例子中,我们有要接口的LCD显示器。

因此,我们使用Arduino的模拟引脚,并形成具有不同电阻值的电位分压器来完成电路。这样,当按下每个按钮时,将向模拟引脚提供不同的模拟电压。下面显示了仅具有两个电阻和两个按钮的示例电路。

poYBAGNx-7eANa9AAAAugOpHbIU301.jpg

在这种情况下,当按钮未按下时,ADC引脚将接收+5V,如果按下第一个按钮,则电位分压器通过560R电阻完成,如果按下第二个按钮,则使用1.5k电阻竞争电位分压器。这样,ADC引脚接收到的电压将根据分压器的公式而变化。如果您想了解更多关于分压器的工作原理以及如何计算ADC引脚接收到的电压值,则可以使用此电位分压器计算器页面。

除此之外,所有连接都是直截了当的,LCD 连接到引脚 8、9、10、11 和 12。蜂鸣器连接到引脚 7,SPDT 开关连接到 Arduino 的引脚 6。整个项目通过笔记本电脑USB端口供电。您还可以通过直流插孔将Arduino连接到9V或12V电源,项目仍将正常工作。

了解 Arduino 的Tone()函数:

Arduino有一个方便的tone()函数,可用于生成不同的频率信号,这些信号可用于使用蜂鸣器产生不同的声音。因此,让我们了解该功能的工作原理以及如何将其与Arduino一起使用。

在此之前,我们应该知道压电蜂鸣器的工作原理.我们可能在我们学校了解过压电晶体, 它只不过是一种将机械振动转化为电能的晶体,反之亦然.在这里,我们应用一个可变的电流(频率),晶体振动从而产生声音。因此,为了使压电蜂鸣器产生一些噪音,我们必须使压电晶体振动,噪声的音调和音调取决于晶体振动的速度.因此,可以通过改变电流频率来控制音调和音高。

好的,那么我们如何从Arduino获得可变频率呢?这就是音调()函数的用武之地。音调()可以在特定引脚上生成特定频率。如果需要,也可以提及持续时间。音调 () 的语法是

Syntax

tone(pin, frequency) tone(pin, frequency, duration)

Parameters

pin: the pin on which to generate the tone frequency: the frequency of the tone in hertz – unsigned int duration: the duration of the tone in milliseconds (optional1) – unsigned long

引脚的值可以是您的任何数字引脚。我在这里使用了引脚 8。可以生成的频率取决于Arduino板中计时器的大小。对于UNO和大多数其他常见板,可以产生的最小频率为31Hz,可以产生的最大频率为65535Hz。然而,我们人类只能听到2000Hz到5000Hz之间的频率。

在Arduino上弹奏钢琴音调:

好的,在我开始这个话题之前,让我明确一点,我是一个音符或钢琴的新手,所以如果这个标题下提到的任何内容都是胡言乱语,请原谅我。

我们现在知道我们可以使用 Arduino 中的音调功能来产生一些声音,但是我们如何使用相同的音调来播放特定音符的音调。幸运的是,有一个名为“pitches.h”的图书馆,由Brett Hagman编写。该库包含有关哪个频率等同于钢琴上哪个音符的所有信息。我很惊讶这个图书馆实际上可以很好地工作并演奏钢琴上的几乎每个音符,我用同样的东西来弹奏加勒比海盗、疯狂青蛙、马里奥甚至泰坦尼克号的钢琴音符,它们听起来很棒。哎呀!我们在这里有点偏离主题,所以如果你对此感兴趣,请查看使用Arduino项目播放旋律。您还可以在该项目中找到有关pitches.h库的更多解释。

我们的项目只有 8 个按钮,因此每个按钮只能播放一个特定的音符,因此我们总共只能播放 8 个音符。我选择了钢琴上最常用的音符,但是您可以选择任何8个,甚至可以使用更多按钮扩展项目并添加更多音符。

此项目中选择的音符是音符 C4、D4、E4、F4、G4、A4、B4 和 C5,可以分别使用按钮 1 到 8 演奏。

对 Arduino 进行编程

足够的理论让我们进入Arduino编程的有趣部分。完整的Arduino程序在本页末尾给出,如果您渴望或进一步阅读以了解代码的工作原理,您可以跳下来。

在我们的Arduino程序中,我们必须从引脚A0读取模拟电压,然后预测按下了哪个按钮并播放该按钮的相应音调。在执行此操作时,我们还应该记录用户按下了哪个按钮以及他/她按下了多长时间,以便我们可以重新创建用户稍后播放的音调。

在进入逻辑部分之前,我们必须声明我们将演奏哪 8 个音符。然后从 pitches.h 库中获取音符的相应频率,然后形成如下所示的数组。这里演奏音符C4的频率是262,依此类推。

int notes[] = {262, 294, 330, 349, 392, 440, 494, 523}; // Set frequency for C4, D4, E4, F4, G4, A4, B4,

接下来我们必须提到LCD显示器连接到哪些引脚。如果您遵循上面给出的完全相同的原理图,则无需在此处更改任何内容。

const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //Pins to which LCD is connected

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

接下来,在我们的设置功能中,我们只需初始化LCD模块和串行监视器以进行调试。我们还会显示介绍消息,以确保事情按计划进行。接下来,在主循环函数中,我们有两个 while 循环。

只要将SPDT开关放置在录制更多内容中,就会执行一个while循环。在录制模式下,用户可以支付所需的音调,同时正在播放的音调也将保存。所以 while 循环如下所示

while (digitalRead(6) == 0) //If the toggle switch is set in recording mode { lcd.setCursor(0, 0); lcd.print("Recording.."); lcd.setCursor(0, 1); Detect_button(); Play_tone(); }

您可能已经注意到,我们在 while 循环中有两个函数。第一个函数Detect_button() 用于查找用户按下的按钮,第二个函数Play_tone()用于播放相应的音调。除了这个函数之外,Detect_button() 函数还记录按下了哪个按钮,Play_tone() 函数记录按下了多长时间。

在Detect_button()函数中,我们从引脚 A0 读取模拟电压,并将其与一些预定义的值进行比较,以找出按下了哪个按钮。该值可以通过使用上面的分压器计算器或使用串行监视器检查每个按钮读取的模拟值来确定。

void Detect_button()

{

analogVal = analogRead(A0); //read the analog voltag on pin A0

pev_button = button; //remember the previous button pressed by the user

if (analogVal < 550)

button = 8;

if (analogVal < 500)

button = 7;

if (analogVal < 450)

button = 6;

if (analogVal < 400)

button = 5;

if (analogVal < 300)

button = 4;

if (analogVal < 250)

button = 3;

if (analogVal < 150)

button = 2;

if (analogVal < 100)

button = 1;

if (analogVal > 1000)

button = 0;

/****Rcord the pressed buttons in a array***/

if (button != pev_button && pev_button != 0)

{

recorded_button[button_index] = pev_button;

button_index++;

recorded_button[button_index] = 0;

button_index++;

}

/**End of Recording program**/

}

如前所述,在此功能中,我们还记录按下按钮的顺序。记录的值存储在名为 recorded_button[] 的数组中。我们首先检查是否按下了新按钮,如果按下,我们还检查它是否不是按钮 0。其中按钮 0 什么都没有,但没有按下按钮。在 if 循环中,我们将值存储在变量 button_index 给出的索引位置上,然后我们还增加此索引值,这样我们就不会在同一位置过度写入。

/****Rcord the pressed buttons in a array***/

if (button != pev_button && pev_button != 0)

{

recorded_button[button_index] = pev_button;

button_index++;

recorded_button[button_index] = 0;

button_index++;

}

/**End of Recording program**/

在Play_tone()函数中,我们将使用多个 if 条件播放按下按钮的相应音调。我们还将使用一个名为 recorded_time[] 的数组,在其中我们将保存按下按钮的持续时间。该操作类似于记录按钮序列,我们使用 millis() 函数来确定每个按钮被按下了多长时间,也是为了减小变量的大小,我们将值除以 10。对于按钮 0,这意味着用户没有按下任何内容,我们在相同的持续时间内没有播放任何音调。函数内的完整代码如下所示。

void Play_tone()

{

/****Rcord the time delay between each button press in a array***/

if (button != pev_button)

{

lcd.clear(); //Then clean it

note_time = (millis() - start_time) / 10;

recorded_time[time_index] = note_time;

time_index++;

start_time = millis();

}

/**End of Recording program**/

if (button == 0)

{

noTone(7);

lcd.print("0 -> Pause..");

}

if (button == 1)

{

tone(7, notes[0]);

lcd.print("1 -> NOTE_C4");

}

if (button == 2)

{

tone(7, notes[1]);

lcd.print("2 -> NOTE_D4");

}

if (button == 3)

{

tone(7, notes[2]);

lcd.print("3 -> NOTE_E4");

}

if (button == 4)

{

tone(7, notes[3]);

lcd.print("4 -> NOTE_F4");

}

if (button == 5)

{

tone(7, notes[4]);

lcd.print("5 -> NOTE_G4");

}

if (button == 6)

{

tone(7, notes[5]);

lcd.print("6 -> NOTE_A4");

}

if (button == 7)

{

tone(7, notes[6]);

lcd.print("7 -> NOTE_B4");

}

if (button == 8)

{

tone(7, notes[7]);

lcd.print("8 -> NOTE_C5");

}

}

最后,在录制后,用户必须将DPST切换到另一个方向才能播放录制的音调。完成此操作后,程序将脱离上一个 while 循环并进入第二个 while 循环,我们按照按下的按钮顺序播放音符,持续时间为先前录制的持续时间。执行相同操作的代码如下所示。

while (digitalRead(6) == 1) //If the toggle switch is set in Playing mode

{

lcd.clear();

lcd.setCursor(0, 0); lcd.print("Now Playing..");

for (int i = 0; i < sizeof(recorded_button) / 2; i++)

{

delay((recorded_time[i]) * 10); //Wait for before paying next tune

if (recorded_button[i] == 0)

noTone(7); //user dint touch any button

else

tone(7, notes[(recorded_button[i] - 1)]); //play the sound corresponding to the button touched by the user

}

}

}

播放,录制,重播和重复!:

按照所示电路图制作硬件,并将代码上传到Arduino板及其显示的时间。将SPDT置于录制模式并开始播放您选择的音调,按下每个按钮将产生不同的音调。在此模式下,LCD将显示“正在录制...”,在第二行,您将看到当前正在按下的笔记的名称,如下所示

pYYBAGNx-7qAEl9XAADGsC-AHi8256.jpg

播放完音调后,将SPDT开关切换到另一侧,液晶屏应显示“正在播放....”,然后开始播放刚刚播放的音调。只要拨动开关保持在下图所示的位置,就会一遍又一遍地播放相同的音调。

poYBAGNx-76AJ-cQAADbM82rzLE181.jpg

/*

Arduino based Piano and Record and play option

Code by: B. Aswinth Raj

Dated: 22-05-2017

*/


#include


int notes[] = {262, 294, 330, 349, 392, 440, 494, 523}; // Set frequency for C4, D4, E4, F4, G4, A4, B4, C5



const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //Pins to which LCD is connected

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


char button = 0;

int analogVal;

char REC = 0;


int recorded_button[200];

int pev_button;


int recorded_time [200];

char time_index;


char button_index = 0;


unsigned long start_time;

int note_time;



void setup() {


Serial.begin(9600);

pinMode (6, INPUT);


lcd.begin(16, 2); //We are using a 16*2 LCD display

lcd.print("Arduino Piano"); //Display a intro message

lcd.setCursor(0, 1); // set the cursor to column 0, line 1

lcd.print("-CircuitDigest"); //Display a intro message


delay(2000); //Wait for display to show info

lcd.clear(); //Then clean it


}





void loop()

{


while (digitalRead(6) == 0) //If the toggle switch is set in recording mode

{

lcd.setCursor(0, 0); lcd.print("Recording..");

lcd.setCursor(0, 1);


Detect_button();

Play_tone();

}




while (digitalRead(6) == 1) //If the toggle switch is set in Playing mode

{

lcd.clear();

lcd.setCursor(0, 0); lcd.print("Now Playing..");


for (int i = 0; i < sizeof(recorded_button) / 2; i++)

{

delay((recorded_time[i]) * 10); //Wait for before paying next tune


if (recorded_button[i] == 0)

noTone(7); //user dint touch any button

else

tone(7, notes[(recorded_button[i] - 1)]); //play the sound corresponding to the button touched by the user

}

}

}





void Detect_button()

{

analogVal = analogRead(A0); //read the analog voltag on pin A0


pev_button = button; //remember the previous button pressed by the user


if (analogVal < 550)

button = 8;


if (analogVal < 500)

button = 7;


if (analogVal < 450)

button = 6;


if (analogVal < 400)

button = 5;


if (analogVal < 300)

button = 4;


if (analogVal < 250)

button = 3;


if (analogVal < 150)

button = 2;


if (analogVal < 100)

button = 1;


if (analogVal > 1000)

button = 0;




/****Rcord the pressed buttons in a array***/

if (button != pev_button && pev_button != 0)

{

recorded_button[button_index] = pev_button;

button_index++;

recorded_button[button_index] = 0;

button_index++;

}

/**End of Recording program**/

}



void Play_tone()

{


/****Rcord the time delay between each button press in a array***/

if (button != pev_button)

{

lcd.clear(); //Then clean it

note_time = (millis() - start_time) / 10;


recorded_time[time_index] = note_time;

time_index++;


start_time = millis();

}

/**End of Recording program**/


if (button == 0)

{

noTone(7);

lcd.print("0 -> Pause..");

}


if (button == 1)

{

tone(7, notes[0]);

lcd.print("1 -> NOTE_C4");

}


if (button == 2)

{

tone(7, notes[1]);

lcd.print("2 -> NOTE_D4");

}


if (button == 3)

{

tone(7, notes[2]);

lcd.print("3 -> NOTE_E4");

}


if (button == 4)

{

tone(7, notes[3]);

lcd.print("4 -> NOTE_F4");

}


if (button == 5)

{

tone(7, notes[4]);

lcd.print("5 -> NOTE_G4");

}


if (button == 6)

{

tone(7, notes[5]);

lcd.print("6 -> NOTE_A4");

}


if (button == 7)

{

tone(7, notes[6]);

lcd.print("7 -> NOTE_B4");

}


if (button == 8)

{

tone(7, notes[7]);

lcd.print("8 -> NOTE_C5");

}

}


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 扬声器
    +关注

    关注

    29

    文章

    1214

    浏览量

    60174
  • 蜂鸣器
    +关注

    关注

    12

    文章

    850

    浏览量

    45298
  • Arduino
    +关注

    关注

    184

    文章

    6427

    浏览量

    184822
收藏 人收藏

    评论

    相关推荐

    如何使用Arduino构建基于触控的变色植物

    在本文中,我们将学习如何使用 Arduino 构建基于触控的变色植物。当您触摸植物时,植物花瓶的颜色会自动改变。这是一个不错的室内装饰项目,也是初学者构建和学习一些有趣东西的小爱好项目
    的头像 发表于 08-08 16:21 4452次阅读
    如何使用<b class='flag-5'>Arduino</b><b class='flag-5'>构建</b>基于触控的变色植物

    Arduino新玩法:在纸上画一架能弹的钢琴

    如果说你想过买一架钢琴,都是又被它高昂的价格吓退了。那么退而求其次,试试 Touch Board 吧。Touch Board 是种基于 Arduino 控制器的创意设备,它与电子墨水
    发表于 08-13 16:12

    请教个日版100V电钢琴电源问题

    一架钢琴,电源是100V的。想改成220V的,请教下应该怎么办呢?下面是电源板和电路图。我本来想直接换个变压器上去,但是没有找到合适的,接110V电源测量变压器次级输出是16V
    发表于 04-05 12:31

    一架四轴原理图共享

    经过两个月的调试,第一架四轴已经起飞,由于程序没有定高,在室外飞,然后遥控失控,然后就上天了,至今没见下来。教训啊。共享原理图,PCB,程序。取自原子哥的,还会给原子哥。谢谢12.4 四轴V3.0.zip (10.46 MB )梦V1.0.zip (6.6 MB )
    发表于 07-12 04:36

    有趣的激光竖琴制作 电子资料

    在上次的上海世博会的伊朗馆里,我看到了一架没有琴弦的竖琴,那是众多参观者公认的伊朗馆里最有趣的展品!参观者只要伸手穿过那架通体黑色的竖琴,音调就会被“奏响”。没有琴弦怎么奏响?工作人员为我们揭示了秘密——他按了...
    发表于 04-20 06:39

    基于NE555P的迷你钢琴

    描述(迷你钢琴) NE555P IC 管风琴![v1]您所需要的只是些电容器、电阻器和个微型 NE555P IC。当然还有这个PCB板。这只是
    发表于 08-08 06:26

    如何使用Arduino制作触控电容式钢琴

    本教程对于电子制造商来说将非常令人兴奋,因为我们将使用 Arduino Nano 设计我们自己的触控电容式钢琴。我们将在我们的钢琴上加入录音和回放功能。
    发表于 07-28 16:47 2697次阅读
    如何使用<b class='flag-5'>Arduino</b>制作触控电容式<b class='flag-5'>钢琴</b>

    Arduino DUE和电阻器制作钢琴

    电子发烧友网站提供《Arduino DUE和电阻器制作钢琴.zip》资料免费下载
    发表于 11-07 10:31 0次下载
    <b class='flag-5'>Arduino</b> DUE和电阻器制作<b class='flag-5'>钢琴</b>

    用键盘和Piezos构建Netduino复音钢琴

    电子发烧友网站提供《用键盘和Piezos构建Netduino复音钢琴.zip》资料免费下载
    发表于 11-08 15:23 0次下载
    用键盘和Piezos<b class='flag-5'>构建</b>Netduino复音<b class='flag-5'>钢琴</b>

    Arduino钢琴库发布

    电子发烧友网站提供《Arduino钢琴库发布.zip》资料免费下载
    发表于 11-16 10:56 0次下载
    <b class='flag-5'>Arduino</b><b class='flag-5'>钢琴</b>库发布

    Arduino Uno板控制88个螺线管弹钢琴

    用一块Arduino Uno板控制88个螺线管弹钢琴
    发表于 12-02 14:57 0次下载

    基于Arduino钢琴机器人

    用一块Arduino Uno板控制88个螺线管弹钢琴。多年前,雅马哈推出了自动钢琴。年轻天真的我看到了乐器店的玻璃窗后面那架正在弹奏音乐的钢琴
    发表于 12-05 17:20 0次下载

    基于Arduino UNO的迷你钢琴

    执行器来影响周围环境。我们项目关注的感官之一是声音。我们已经创建了一个微型版本的钢琴,它可以像普通钢琴一样产生音符。它是如何工作的?完成连接并将代码上传到电路板后,将 9v 电池作为电源连接到 Arduino。当您按下相应的按钮
    发表于 12-19 16:59 0次下载

    基于Arduino设计的简单小钢琴

    方案介绍一个简单的小型钢琴,不仅顾名思义,而且很小,但它源自Arduino Nano Every。硬件部件Arduino Nano Every×    1个    电阻1k欧姆    ×    4    蜂鸣器    ×    
    发表于 12-30 15:20 0次下载

    钢琴老师:Arduino+LEDs+MIDI键盘+MuseScore

    电子发烧友网站提供《钢琴老师:Arduino+LEDs+MIDI键盘+MuseScore .zip》资料免费下载
    发表于 06-15 11:01 0次下载
    <b class='flag-5'>钢琴</b>老师:<b class='flag-5'>Arduino</b>+LEDs+MIDI键盘+MuseScore