极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 34293|回复: 15

用Arduino播放“生日快乐”

[复制链接]
发表于 2013-11-11 22:43:37 | 显示全部楼层 |阅读模式
本帖最后由 tahoroom 于 2013-11-12 16:35 编辑

这是我博客的文章,贴过来给大家分享,源地址:http://www.tahoroom.com/archives/7030.html 多捧场啊,顺便点个广告什么的支持一下博主哦!

Arduino 播放音乐的原理
需要用到的材料:adruino uno一块(其他Arduino板子也可,注意引脚就行),面保线若干条,蜂鸣器或小喇叭一个。

首先讲下简单的乐理知识,知道音乐是怎么演奏出来的自然就可以通过代码来进行编排了。

1.演奏单音符

一首乐曲有若干音符组成,一个音符对应一个频率。我们知道到相对应的频率让 Arduino 输出到蜂鸣器,蜂鸣器就会发出相应频率下的声音。Arduino官方网站给出了不同音符对应的不同频率的头文件,具体请见下文介绍。

2.音符的演奏时间

每个音符都会播放一定的时间,这样才能构成一首优美的曲子,而不是每个音符都播放一样长的时间。如何确定每个音符演奏的单位时间呢?我们知道,音符节奏分为1拍、1/2拍、1/4拍、1/8拍,我们规定一拍音符的时间为1;半拍为0.5;1/4拍为0.25;1/8拍为0.125……,所以我们可以为每个音符赋予这样的拍子播放出来,音乐就成了。Arduino已经给出了像样的程序,即 Arduino 的 Tone 库。

我们用它可以帮助我们快速制作音乐。

这是ArduinoTone函数的官方介绍地址:http://arduino.cc/en/Tutorial/Tone,使用函数为Tone():http://arduino.cc/en/Reference/Tone

如果要查看Tone的完整维护记录和使用说明请访问:http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation

制作方法

所需硬件:Arduino板子一块,小型扬声器一个,导线两根。如果扬声器声音太大,也可适当配置220欧姆电阻一个与扬声器串联。

首先看看官方的例子。



该例子里,我们将扬声器一端串联电阻后接到数字8(D8)接口,另一端接地(GND)。接线原理图如下:



接好线之后,将以下代码粘贴到Arduino IDE中。代码如下:

  1. /*
  2.   Melody

  3. Plays a melody

  4. circuit:
  5. * 8-ohm speaker on digital pin 8

  6. created 21 Jan 2010
  7. modified 30 Aug 2011
  8. by Tom Igoe

  9. This example code is in the public domain.

  10. http://arduino.cc/en/Tutorial/Tone

  11. */
  12. #include "pitches.h"

  13. // notes in the melody:
  14. int melody[] = {
  15.   NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};

  16. // note durations: 4 = quarter note, 8 = eighth note, etc.:
  17. int noteDurations[] = {
  18.   4, 8, 8, 4,4,4,4,4 };

  19. void setup() {
  20.   // iterate over the notes of the melody:
  21.   for (int thisNote = 0; thisNote < 8; thisNote++) {

  22.     // to calculate the note duration, take one second
  23.     // divided by the note type.
  24.     //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
  25.     int noteDuration = 1000/noteDurations[thisNote];
  26.     tone(8, melody[thisNote],noteDuration);

  27.     // to distinguish the notes, set a minimum time between them.
  28.     // the note's duration + 30% seems to work well:
  29.     int pauseBetweenNotes = noteDuration * 1.30;
  30.     delay(pauseBetweenNotes);
  31.     // stop the tone playing:
  32.     noTone(8);
  33.   }
  34. }

  35. void loop() {
  36.   // no need to repeat the melody.
  37. }
复制代码

该程序中使用了这两个函数:

  1. tone(pin, frequency)

  2. tone(pin, frequency, duration)
复制代码


函数的参数说明:

pin: 你要接扬声器的接口,是整数(int 型)

frequency:频率,是一个整数(int 型)

duration: 音符持续的时间,是毫秒值,无符号长整型( unsigned long 型)

无返回值

我们还注意到上面代码中调用了头文件“pitches.h”。这个文件是什么呢?这个头文件正式上面提到的不同音符对应的不同频率的头文件。该pitches.h文件内容如下:

  1. /*************************************************
  2. * Public Constants
  3. *************************************************/

  4. #define NOTE_B0  31
  5. #define NOTE_C1  33
  6. #define NOTE_CS1 35
  7. #define NOTE_D1  37
  8. #define NOTE_DS1 39
  9. #define NOTE_E1  41
  10. #define NOTE_F1  44
  11. #define NOTE_FS1 46
  12. #define NOTE_G1  49
  13. #define NOTE_GS1 52
  14. #define NOTE_A1  55
  15. #define NOTE_AS1 58
  16. #define NOTE_B1  62
  17. #define NOTE_C2  65
  18. #define NOTE_CS2 69
  19. #define NOTE_D2  73
  20. #define NOTE_DS2 78
  21. #define NOTE_E2  82
  22. #define NOTE_F2  87
  23. #define NOTE_FS2 93
  24. #define NOTE_G2  98
  25. #define NOTE_GS2 104
  26. #define NOTE_A2  110
  27. #define NOTE_AS2 117
  28. #define NOTE_B2  123
  29. #define NOTE_C3  131
  30. #define NOTE_CS3 139
  31. #define NOTE_D3  147
  32. #define NOTE_DS3 156
  33. #define NOTE_E3  165
  34. #define NOTE_F3  175
  35. #define NOTE_FS3 185
  36. #define NOTE_G3  196
  37. #define NOTE_GS3 208
  38. #define NOTE_A3  220
  39. #define NOTE_AS3 233
  40. #define NOTE_B3  247
  41. #define NOTE_C4  262
  42. #define NOTE_CS4 277
  43. #define NOTE_D4  294
  44. #define NOTE_DS4 311
  45. #define NOTE_E4  330
  46. #define NOTE_F4  349
  47. #define NOTE_FS4 370
  48. #define NOTE_G4  392
  49. #define NOTE_GS4 415
  50. #define NOTE_A4  440
  51. #define NOTE_AS4 466
  52. #define NOTE_B4  494
  53. #define NOTE_C5  523
  54. #define NOTE_CS5 554
  55. #define NOTE_D5  587
  56. #define NOTE_DS5 622
  57. #define NOTE_E5  659
  58. #define NOTE_F5  698
  59. #define NOTE_FS5 740
  60. #define NOTE_G5  784
  61. #define NOTE_GS5 831
  62. #define NOTE_A5  880
  63. #define NOTE_AS5 932
  64. #define NOTE_B5  988
  65. #define NOTE_C6  1047
  66. #define NOTE_CS6 1109
  67. #define NOTE_D6  1175
  68. #define NOTE_DS6 1245
  69. #define NOTE_E6  1319
  70. #define NOTE_F6  1397
  71. #define NOTE_FS6 1480
  72. #define NOTE_G6  1568
  73. #define NOTE_GS6 1661
  74. #define NOTE_A6  1760
  75. #define NOTE_AS6 1865
  76. #define NOTE_B6  1976
  77. #define NOTE_C7  2093
  78. #define NOTE_CS7 2217
  79. #define NOTE_D7  2349
  80. #define NOTE_DS7 2489
  81. #define NOTE_E7  2637
  82. #define NOTE_F7  2794
  83. #define NOTE_FS7 2960
  84. #define NOTE_G7  3136
  85. #define NOTE_GS7 3322
  86. #define NOTE_A7  3520
  87. #define NOTE_AS7 3729
  88. #define NOTE_B7  3951
  89. #define NOTE_C8  4186
  90. #define NOTE_CS8 4435
  91. #define NOTE_D8  4699
  92. #define NOTE_DS8 4978
复制代码

可以看到,这是一张类似表格的东西,里面是定义的大量的宏,即用宏名代替了频率名,对应到键盘的各个按键上。可是,不懂音乐的我们如何能够取出我们所要的音符对应的宏名呢?

首先看看钢琴大谱表与钢琴琴键的对照表:



从上图我们可以将各音符的音名直观的看出来,但是,我又只会简谱,如何看呢?为了方便我自己,也希望能方便大家,我将其制作为了直观的表格,见下图:(如需要Excel格式文件的请留言联系我)



上图辛苦的制作过程:



对照上面的表格,我们就能制作自己的音乐了。

自己的作品——播放生日快乐歌

最近老婆要过生日,我打算用Arduino为她做一首生日快乐送给她。(发布这篇文章的时候生日已经过了,不想早发布是怕她看见了,惊喜就没那么大了,嘿嘿!)

首先找到生日快乐的简谱:



可以看到其节拍是3/4,但是我按照其节拍做下来之后觉得唱的太慢了,就没按照它的来。(灵活处理嘛)

再对照上表,制作其旋律函数为:

  1. int melody[] = {
  2. NOTE_G4,//5  
  3. NOTE_G4,//5
  4. NOTE_A4,//6
  5. NOTE_G4,//5
  6. NOTE_C5,//1.
  7. NOTE_B4,//7
  8. 0,
  9. NOTE_G4,//5
  10. NOTE_G4,//5
  11. NOTE_A4,//6
  12. NOTE_G4,//5
  13. NOTE_D5,//2.
  14. NOTE_C5,//1.
  15. 0,
  16. NOTE_G4,//5
  17. NOTE_G4,//5
  18. NOTE_G5,//5.
  19. NOTE_E5,//3.
  20. NOTE_C5,//1.
  21. NOTE_B4,//7
  22. NOTE_A4,//6
  23. 0,
  24. NOTE_F5,//4.
  25. NOTE_F5,//4.
  26. NOTE_E5,//3.
  27. NOTE_C5,//1.
  28. NOTE_D5,//2.
  29. NOTE_C5,//1.
  30. 0,
  31. };
复制代码

持续时间函数为:(注意休止符也需要时间的)

  1. int noteDurations[] = {
  2.   8,8,4,4,4,4,
  3.   4,
  4.   8,8,4,4,4,4,
  5.   4,
  6.   8,8,4,4,4,4,2,
  7.   8,
  8.   8,8,4,4,4,2,
  9.   4,
  10. };
复制代码

可以直接把上面的两个函数覆盖官方的例子,写入Arduino就行了,可以灵活的修改修改接口。不过,为了更好看起见,我添加了3个彩色自闪LED灯,一闪一闪的很好看,我想老婆会更喜欢的。所以,稍微添加了几行代码:

  1. /*
  2. Happy Birthday Tone for Daner.
  3. Made by TAHO on 6th,Nov. 2013
  4. www.tahoroom.com
  5. [email]tahoroom@163.com[/email]
  6. version 1.0
  7. */
  8. #include "pitches.h"

  9. void setup() {
  10.   // iterate over the notes of the melody:
  11.   pinMode(9,OUTPUT);//for light
  12.   pinMode(10,OUTPUT);//for light
  13.   pinMode(11,OUTPUT);//for light
  14. }

  15. void loop() {
  16.   // no need to repeat the melody.
  17.   ColorLight();//Turn on the lights
  18.   play();//Play the music.
  19.   delay(300);//Pause for a while.
  20. }

  21. // notes in the melody:
  22. int melody[] = {
  23. NOTE_G4,//5  
  24. NOTE_G4,//5
  25. NOTE_A4,//6
  26. NOTE_G4,//5
  27. NOTE_C5,//1.
  28. NOTE_B4,//7
  29. 0,
  30. NOTE_G4,//5
  31. NOTE_G4,//5
  32. NOTE_A4,//6
  33. NOTE_G4,//5
  34. NOTE_D5,//2.
  35. NOTE_C5,//1.
  36. 0,
  37. NOTE_G4,//5
  38. NOTE_G4,//5
  39. NOTE_G5,//5.
  40. NOTE_E5,//3.
  41. NOTE_C5,//1.
  42. NOTE_B4,//7
  43. NOTE_A4,//6
  44. 0,
  45. NOTE_F5,//4.
  46. NOTE_F5,//4.
  47. NOTE_E5,//3.
  48. NOTE_C5,//1.
  49. NOTE_D5,//2.
  50. NOTE_C5,//1.
  51. 0,
  52. };


  53. int noteDurations[] = {
  54.   8,8,4,4,4,4,
  55.   4,
  56.   8,8,4,4,4,4,
  57.   4,
  58.   8,8,4,4,4,4,2,
  59.   8,
  60.   8,8,4,4,4,2,
  61.   4,
  62. };


  63. void play()
  64. {
  65.     for (int thisNote = 0; thisNote < 29; thisNote++) {

  66.     // to calculate the note duration, take one second
  67.     // divided by the note type.
  68.     //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
  69.     int noteDuration = 1000/noteDurations[thisNote];
  70.     tone(5, melody[thisNote],noteDuration);

  71.     // to distinguish the notes, set a minimum time between them.
  72.     // the note's duration + 30% seems to work well:
  73.     int pauseBetweenNotes = noteDuration * 1.30;
  74.     delay(pauseBetweenNotes);
  75.     // stop the tone playing:
  76.     noTone(8);
  77.   }
  78. }

  79. void ColorLight()
  80. {
  81.   digitalWrite(9, HIGH);
  82.   digitalWrite(10, HIGH);
  83.   digitalWrite(11, HIGH);
  84. }
复制代码


pitches.h 文件不用修改,直接使用。

成品出来了!看图!(为了她好拿,我用了拓展盾板,底下再粘上了一块 9V 电池,其实很简单的。本打算做个最小电路给她,由于一些原因没有及时买到晶振材料,因此作罢。)



看视频!



更多图:




老婆好高兴,她非常满意!拿去给朋友炫耀了,哈哈!

评分

参与人数 1 +3 收起 理由
幻生幻灭 + 3 赞一个!

查看全部评分

回复

使用道具 举报

发表于 2013-11-12 08:07:16 | 显示全部楼层
太感谢了 找了好久 这个帖子对大家的帮助太大了 特别是钢琴的部分
回复 支持 反对

使用道具 举报

发表于 2013-11-12 10:26:12 | 显示全部楼层
讲的很好啊,支持!!
回复 支持 反对

使用道具 举报

发表于 2013-11-12 10:29:31 | 显示全部楼层
有意思啊!
回复 支持 反对

使用道具 举报

发表于 2013-11-12 11:02:48 | 显示全部楼层
牛奔的泪啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-12 16:34:21 | 显示全部楼层
爱因你而生 发表于 2013-11-12 08:07
太感谢了 找了好久 这个帖子对大家的帮助太大了 特别是钢琴的部分

嘿嘿!多谢捧场!
回复 支持 反对

使用道具 举报

发表于 2013-11-12 21:09:57 | 显示全部楼层
tahoroom 发表于 2013-11-12 16:34
嘿嘿!多谢捧场!

LZ好厉害。。膜拜下。。
视频里面,,你是把Arduino板和一个面包板还有个貌似是电池一样的东西用胶布粘在一起的么?我是个新人,也想做一个练练手,,不知道具体你用的是哪些板子和电池?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-12 22:47:26 | 显示全部楼层
qmy777 发表于 2013-11-12 21:09
LZ好厉害。。膜拜下。。
视频里面,,你是把Arduino板和一个面包板还有个貌似是电池一样的东西用胶布粘在 ...

是的,粘在一起的。使用了9V电池一块,一块Arduino Uno,一块扩展盾板(附带小面包版)。电池用的就是9V电池,你在淘宝搜一下就知道啦。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-12 23:10:26 | 显示全部楼层
爱因你而生 发表于 2013-11-12 08:07
太感谢了 找了好久 这个帖子对大家的帮助太大了 特别是钢琴的部分

多谢啊!钢琴的部分花了些时间,有了做出来的那个对照表,写起音乐代码来就一目了然了~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-12 23:10:58 | 显示全部楼层
软件-蹄飞 发表于 2013-11-12 10:26
讲的很好啊,支持!!

多谢捧场!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-12 23:11:41 | 显示全部楼层
nust_奔跑 发表于 2013-11-12 10:29
有意思啊!

嘿嘿!也做个玩玩呗~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-11-12 23:12:05 | 显示全部楼层
jgwang1001 发表于 2013-11-12 11:02
牛奔的泪啊

高看我啦!做起来其实很简单的。
回复 支持 反对

使用道具 举报

发表于 2013-11-14 10:10:46 | 显示全部楼层
tahoroom 发表于 2013-11-12 22:47
是的,粘在一起的。使用了9V电池一块,一块Arduino Uno,一块扩展盾板(附带小面包版)。电池用的就是9V电 ...

谢谢LZ了!
回复 支持 反对

使用道具 举报

发表于 2015-3-21 20:45:21 | 显示全部楼层
怎么调用这个pitches.h库啊,我编译的时候总是调用不了这个库的文件
回复 支持 反对

使用道具 举报

发表于 2015-8-23 19:34:12 | 显示全部楼层
站在时光最中央 发表于 2015-3-21 20:45
怎么调用这个pitches.h库啊,我编译的时候总是调用不了这个库的文件

可以的啊。你不用库函数,直接用这个:一样的
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号-2 )

GMT+8, 2021-6-24 20:24 , Processed in 0.057358 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表