81浏览
查看: 81|回复: 0

[入门教程] Arduino入门教程16--音乐蜂鸣器「DFR0100」

[复制链接]
本帖最后由 zoey不种土豆 于 2024-11-19 17:36 编辑

在之前的课程中,我们学会了如何控制蜂鸣器发出不同的声音。那么,我们是否可以通过调整声音的频率和节拍,来组合出一段完整的旋律呢?在这个项目中,我们将使用蜂鸣器演奏音乐,并学习如何创建头文件(.h文件),以导入别人已经编写好的“曲谱”。
在使用Arduino IDE编程时,每创建一个项目文件被称为一个“Sketch”。一个Sketch中可以包含多个代码文件。为了避免程序代码过长且不易阅读,可以在主文件中编写程序的主要逻辑部分,而将程序的独立功能模块存放在其他文件中,以便于管理和维护。这种做法不仅提高了代码的可读性,还便于功能的复用和扩展。

元件清单
Arduino入门教程16--音乐蜂鸣器「DFR0100」图1

硬件连接
按如下连线图连接,注意蜂鸣器引脚正(+),负(-)。标有+的引脚接到数字口8,另一个接GND。蜂鸣器的正负极通过盖子上的+符号查看。
Arduino入门教程16--音乐蜂鸣器「DFR0100」图2
图 1 音乐蜂鸣器连线图

示例代码样例代码 - Main Sketch:
  1. //项目 - 音乐蜂鸣器
  2. #include "pitches.h"  // 包含一个头文件  
  3. int melody[] = {  
  4.   NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4  
  5. };  // 旋律中的音符序列  
  6.   
  7. int noteTypes[] = {  
  8.   4, 8, 8, 4, 4, 4, 4, 4  
  9. };  // 每个音符的类型:4 = 四分音符,8 = 八分音符  
  10.   
  11. void setup() {  
  12.   
  13.   for (int thisNote = 0; thisNote < 8; thisNote++) {  
  14. int noteDuration = 1000 / noteTypes[thisNote];  
  15. // 计算音符的持续时间:1秒 / 音符类型  
  16. tone(8, melody[thisNote], noteDuration);  
  17. // 在引脚8上播放音符  
  18. int pauseBetweenNotes = noteDuration * 1.30;  
  19. // 根据音符持续时间计算暂停时间,使旋律听起来更自然  
  20.     delay(pauseBetweenNotes);  // 音符之间的暂停  
  21.     noTone(8);  // 停止在引脚8上播放的音调  
  22.   }  
  23. }  
  24.   
  25. void loop() {  
  26.   // 不需要重复播放旋律  
  27. }
复制代码
要创建一个新的头文件,点击串口监视器下方的按钮,选择新建标签页,输入文件名pitches.h
Arduino入门教程16--音乐蜂鸣器「DFR0100」图3
Arduino入门教程16--音乐蜂鸣器「DFR0100」图6
Pitches.h:
  1. #define NOTE_B0  31
  2. #define NOTE_C1  33
  3. #define NOTE_CS1 35
  4. #define NOTE_D1  37
  5. #define NOTE_DS1 39
  6. #define NOTE_E1  41
  7. #define NOTE_F1  44
  8. #define NOTE_FS1 46
  9. #define NOTE_G1  49
  10. #define NOTE_GS1 52
  11. #define NOTE_A1  55
  12. #define NOTE_AS1 58
  13. #define NOTE_B1  62
  14. #define NOTE_C2  65
  15. #define NOTE_CS2 69
  16. #define NOTE_D2  73
  17. #define NOTE_DS2 78
  18. #define NOTE_E2  82
  19. #define NOTE_F2  87
  20. #define NOTE_FS2 93
  21. #define NOTE_G2  98
  22. #define NOTE_GS2 104
  23. #define NOTE_A2  110
  24. #define NOTE_AS2 117
  25. #define NOTE_B2  123
  26. #define NOTE_C3  131
  27. #define NOTE_CS3 139
  28. #define NOTE_D3  147
  29. #define NOTE_DS3 156
  30. #define NOTE_E3  165
  31. #define NOTE_F3  175
  32. #define NOTE_FS3 185
  33. #define NOTE_G3  196
  34. #define NOTE_GS3 208
  35. #define NOTE_A3  220
  36. #define NOTE_AS3 233
  37. #define NOTE_B3  247
  38. #define NOTE_C4  262
  39. #define NOTE_CS4 277
  40. #define NOTE_D4  294
  41. #define NOTE_DS4 311
  42. #define NOTE_E4  330
  43. #define NOTE_F4  349
  44. #define NOTE_FS4 370
  45. #define NOTE_G4  392
  46. #define NOTE_GS4 415
  47. #define NOTE_A4  440
  48. #define NOTE_AS4 466
  49. #define NOTE_B4  494
  50. #define NOTE_C5  523
  51. #define NOTE_CS5 554
  52. #define NOTE_D5  587
  53. #define NOTE_DS5 622
  54. #define NOTE_E5  659
  55. #define NOTE_F5  698
  56. #define NOTE_FS5 740
  57. #define NOTE_G5  784
  58. #define NOTE_GS5 831
  59. #define NOTE_A5  880
  60. #define NOTE_AS5 932
  61. #define NOTE_B5  988
  62. #define NOTE_C6  1047
  63. #define NOTE_CS6 1109
  64. #define NOTE_D6  1175
  65. #define NOTE_DS6 1245
  66. #define NOTE_E6  1319
  67. #define NOTE_F6  1397
  68. #define NOTE_FS6 1480
  69. #define NOTE_G6  1568
  70. #define NOTE_GS6 1661
  71. #define NOTE_A6  1760
  72. #define NOTE_AS6 1865
  73. #define NOTE_B6  1976
  74. #define NOTE_C7  2093
  75. #define NOTE_CS7 2217
  76. #define NOTE_D7  2349
  77. #define NOTE_DS7 2489
  78. #define NOTE_E7  2637
  79. #define NOTE_F7  2794
  80. #define NOTE_FS7 2960
  81. #define NOTE_G7  3136
  82. #define NOTE_GS7 3322
  83. #define NOTE_A7  3520
  84. #define NOTE_AS7 3729
  85. #define NOTE_B7  3951
  86. #define NOTE_C8  4186
  87. #define NOTE_CS8 4435
  88. #define NOTE_D8  4699
  89. #define NOTE_DS8 4978
复制代码

代码回顾
在这个项目中,我们新建了pitches.h文件,并复制了一段代码。从项目【温度报警器】中我们了解到,不同的频率会产生不同的音调。而我们复制的这段代码是最初由 Brett Hagman 编写的音符表,包含了所有典型音符所对应的频率。比如,NOTE_C4 是中央C音,对应的频率是262。有了这张音符表,我们就可以通过输入音符的名称来编写旋律了。
在Main Sketch中使用了#include语法来导入了新建的文件或外部库,将不同的文件关联起来。
在程序中,我们首先创建了两个数组来按顺序储存音调与节奏。
  1. int melody[] = {
  2.   NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
  3. };
  4. int noteTypes[] = {
  5.   4, 8, 8, 4, 4, 4, 4, 4
  6. };
复制代码
上面这个数组noteTypes[] 定义了每个音符的持续时间。这里使用的是一种简化的表示方法,其中数字代表音符的“类型”,而不是确切的毫秒数。例如,4代表四分音符,8代表八分音符。实际的持续时间将在setup()函数中计算得出。
数组是一个变量的集合,可以通过索引号来找到数组中的元素。可以看出我们创建的数组中分别有8个元素。数组是从0开始索引的,因此数组中的8个元素的索引号是0~7。
在本程序中旋律只会播放一次,因此我们在setup里编写播放音符的程序。
通过一个for循环,来遍历数组中的每一个元素,通过变量thisNote表示目前的元素索引号。

  1.   for (int thisNote = 0; thisNote < 8; thisNote++) {  
  2. int noteDuration = 1000 / noteTypes[thisNote];  
  3. // 计算音符的持续时间:1秒 / 音符类型  
  4. tone(8, melody[thisNote], noteDuration);  
  5. // 在引脚8上播放音符  
  6. int pauseBetweenNotes = noteDuration * 1.30;  
  7. // 根据音符持续时间计算暂停时间,使旋律听起来更自然  
  8.   
  9.     delay(pauseBetweenNotes);  // 音符之间的暂停  
  10.     noTone(8);  // 停止在引脚8上播放的音调  
  11.   }  
复制代码
在循环中,首先计算了音符的持续时间。在音乐的定义中,四分音符占一个小节的1/4,因此可以通过小节时间(这里设置的是1秒)除以4来计算每个音符的持续时间。
然后使用tone()函数设置引脚,frequency和duration,来播放音符。
每个音符中间需要有一定的间隔才能够让我们方便区分,因此需要在音符之间设置延迟。间隔时间根据音符持续时间调整会让旋律更加流畅,用noteDuration * 1.30会得到不错的效果,你也可以试试设置delay(200) 的固定时间,来看看效果会有什么不一样。
在音符播放完,使用noTone让声音停止。

硬件回顾
Arduino开发板通常都配备了一个复位键(Reset Button),这个按键在多个方面都非常有用,特别是在编程、调试和重新启动Arduino时。复位键的主要功能是使Arduino板上的微控制器(如ATmega系列)重置其状态,类似于计算机上的重启操作,但针对的是微控制器本身。
Arduino UNO的复位键通常位于开发板的左上角(如图2),靠近USB接口或其他I/O接口。它是一个小按钮,旁边标有“RESET”字样。同样,你也可以使用扩展板上的复位按键来重启Arduino里面的程序。
Arduino入门教程16--音乐蜂鸣器「DFR0100」图4
图 2 Arduino UNO 复位键位置

Arduino入门教程16--音乐蜂鸣器「DFR0100」图5
图 3 扩展板复位键位置

示例代码

课后练习
你有没有熟悉的旋律想要通过蜂鸣器来播放呢?比如小星星或者玛丽有只小羊羔?来试试改变数组中的音符和节奏吧。别忘了改变for循环中的数量哦。

下一课Arduino入门教程17--DJ调音台
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail