蜂鸣器
根据发声原理不同分为电压式蜂鸣器和电磁式蜂鸣器。我们使用的是电磁式蜂鸣器,接通电源后,振动膜片周期性的振动发声。需要注意的一点是,发声是在内部有电流产生磁场,使得膜片振动的一瞬间。 如果内部一直是直流电的话我们只能听到很小的一下的声音,如果需要持续的声音(就像我萌以前过生日的那种唱生日快乐歌的小玩意)应该怎么办呢?需要一个交流的驱动电路就行。最简单的方波就可以驱动。 这里我们使用的是无源蜂鸣器, 这里的源指的是振荡源,自带BUFF的就是有源,也就是直接同直流电就可以发声,无源则需要外部送入方波信号用于驱动才行。

接线
arduino 蜂鸣器
5V VCC
GND GND
8 S
第一步 蜂鸣器响起来
前面我们已经把数字IO连接到了蜂鸣器的正极,让蜂鸣器响起来只需要在数字IO上放入方波即可。

digitalWrite(buzzerPin,HIGH); //高电平
delay(100);
digitalWrite(buzzerPin,LOW); //低电平
delay(100);
1
2
3
4
其中的100指的是100ms,这样算来通电(高电平)占空比就是50%,周期200ms,那么频率就是500Hz,这个频率实际上已经比较高了。

不同的旋律
不同的乐音有着不同的频率,下面是一张乐音频率图。
Arduino 蜂鸣器播放音乐 - 图1

我们知道了音调的频率后,下一步就是控制音符的演奏时间。每个音符都会播放一定的时间,这样才能构成一首优美的曲子,而不是生硬的一个调的把所有的音符一股脑的都播放出来。音符节奏分为一拍、半拍、1/4拍、1/8拍,我们规定一拍音符的时间为1;半拍为0.5;1/4拍为0.25;1/8拍为0.125……,所以我们可以为每个音符赋予这样的拍子播放出来,音乐就成了。

音符

  1. #define Do 262
  2. #define Re 294
  3. #define Mi 330
  4. #define Fa 349
  5. #define Sol 392
  6. #define La 440
  7. #define Si 494

以《欢乐颂》为例
Arduino 蜂鸣器播放音乐 - 图2
从简谱看,该音乐是D调的,这里的各音符对应的频率对应的是上表中D调的部分。另外,该音乐为四分之四拍,每个对应为1拍。几个特殊音符说明如下:
第一,普通音符。如第一个音符3,对应频率350,占1拍。
第二,带下划线音符,表示0.5拍。
第三,有的音符后带一个点,表示多加0.5拍,即1+0.5
第四,有的音符后带一个—,表示多加1拍,即1+1
第五,有的两个连续的音符上面带弧线,表示连音,可以稍微改下连音后面那个音的频率,比如减少或增加一些数值(需自己调试),这样表现会更流畅,其实不做处理,影响也不大。

程序

  1. #define NTD0 -1
  2. #define NTD1 294
  3. #define NTD2 330
  4. #define NTD3 350
  5. #define NTD4 393
  6. #define NTD5 441
  7. #define NTD6 495
  8. #define NTD7 556
  9. #define NTDL1 147
  10. #define NTDL2 165
  11. #define NTDL3 175
  12. #define NTDL4 196
  13. #define NTDL5 221
  14. #define NTDL6 248
  15. #define NTDL7 278
  16. #define NTDH1 589
  17. #define NTDH2 661
  18. #define NTDH3 700
  19. #define NTDH4 786
  20. #define NTDH5 882
  21. #define NTDH6 990
  22. #define NTDH7 112
  23. //列出全部D调的频率
  24. #define WHOLE 1
  25. #define HALF 0.5
  26. #define QUARTER 0.25
  27. #define EIGHTH 0.25
  28. #define SIXTEENTH 0.625
  29. //列出所有节拍
  30. int tune[]= //根据简谱列出各频率
  31. {
  32. NTD3,NTD3,NTD4,NTD5,
  33. NTD5,NTD4,NTD3,NTD2,
  34. NTD1,NTD1,NTD2,NTD3,
  35. NTD3,NTD2,NTD2,
  36. NTD3,NTD3,NTD4,NTD5,
  37. NTD5,NTD4,NTD3,NTD2,
  38. NTD1,NTD1,NTD2,NTD3,
  39. NTD2,NTD1,NTD1,
  40. NTD2,NTD2,NTD3,NTD1,
  41. NTD2,NTD3,NTD4,NTD3,NTD1,
  42. NTD2,NTD3,NTD4,NTD3,NTD2,
  43. NTD1,NTD2,NTDL5,NTD0,
  44. NTD3,NTD3,NTD4,NTD5,
  45. NTD5,NTD4,NTD3,NTD4,NTD2,
  46. NTD1,NTD1,NTD2,NTD3,
  47. NTD2,NTD1,NTD1
  48. };
  49. float durt[]= //根据简谱列出各节拍
  50. {
  51. 1,1,1,1,
  52. 1,1,1,1,
  53. 1,1,1,1,
  54. 1+0.5,0.5,1+1,
  55. 1,1,1,1,
  56. 1,1,1,1,
  57. 1,1,1,1,
  58. 1+0.5,0.5,1+1,
  59. 1,1,1,1,
  60. 1,0.5,0.5,1,1,
  61. 1,0.5,0.5,1,1,
  62. 1,1,1,1,
  63. 1,1,1,1,
  64. 1,1,1,0.5,0.5,
  65. 1,1,1,1,
  66. 1+0.5,0.5,1+1,
  67. };
  68. int length;
  69. int tonepin=8; //得用6号接口
  70. void setup()
  71. {
  72. pinMode(tonepin,OUTPUT);
  73. length=sizeof(tune)/sizeof(tune[0]); //计算长度
  74. }
  75. void loop()
  76. {
  77. for(int x=0;x<length;x++)
  78. {
  79. tone(tonepin,tune[x]);
  80. delay(500*durt[x]); //这里用来根据节拍调节延时,500这个指数可以自己调整,在该音乐中,我发现用500比较合适。
  81. noTone(tonepin);
  82. }
  83. delay(2000);
  84. }