Arduino红外遥控无源蜂鸣器播放音乐
简介
蜂鸣器,按驱动形式来分一般分为两类,一种是有源蜂鸣器,另外一种是无源蜂鸣器。有源蜂鸣器上电就会响,可玩性不高,但无源蜂鸣器是一个很有意思的东西,可以通过改变输入的频率可以使它发出不同音调的声音,利用Arduino Uno和无源蜂鸣器实现播放音乐。
关于频谱
下图是C调中音符所对应的频率,用里面的频率我们就可以让无源蜂鸣器发出 Do、Re、Mi、Fa、Sol、La、Si。以此类推利用蜂鸣器播放音乐就简单了很多。
除了Do、Re、Mi…外,用无源蜂鸣器播放音乐还需要注意节拍,如果节拍处理不好的话,听起来就不是那首歌了,由于每一首歌的速度都不同,所以在节拍处理上每一首歌都不一样,最好就找4/4拍的儿歌来练练手,比如《小蜜蜂》。
实验材料
- Arduino Uno板
- 无源蜂鸣器
- 红外遥控一套
- 杜邦线
接线
Uno | 红外接收 | 蜂鸣器 |
---|---|---|
5v | VCC | VCC |
GND | GND | GND |
D9 | I/O | |
D10 | I/O |
实验代码
无源蜂鸣器播放
《小蜜蜂》和
《有酒今朝醉》----->>>>我爱您,你爱我,啦啦啦啦甜蜜蜜
-------------------------->>>>童年就八岁,多欢趣,见到狗仔起势追。
#include <IRremote.h>
/********C调*********/
#define L1 262
#define L2 294
#define L3 330
#define L4 349 //低
#define L5 392
#define L6 440
#define L7 494
#define M1 523
#define M2 587
#define M3 659
#define M4 698 //中
#define M5 784
#define M6 880
#define M7 988
#define H1 1046
#define H2 1109
#define H3 1318
#define H4 1397 //高
#define H5 1568
#define H6 1760
#define H7 1976
#define none 0 //空
/**********************/
const int RECV = 10; //定义红外遥控接收器的数据接口
IRrecv irrecv(RECV);
decode_results results; //创建红外遥控对象
const int Buzzer = 11; //定义蜂鸣器接口
int arrLength; //定义一个变量用于计算数组的长度
/*******有酒今朝醉*******/
void music1()
{
//频谱
int music1[] = {
L5, M1, M2,
M3, M5, M5, M6, M5, M3, M2, M1, M1, M2,
M3, M3, M2, M1, M2, none, M2, M1,
M3, M5, M5, M6, M5, M3, M2, M1, M1, M2,
M3, M3, M2, M2, M1, none,
M4, M4, M5, M6, M6,
M5, M5, M3, M1, M2, none, M1, M2,
M3, M5, M5, M6, M5, M3, M2, M1, M1, M2,
M3, M3, M2, M2, M1, M1
};
//节拍
float music1_delay[] = {
0.5, 0.25, 0.25,
0.5, 0.5, 0.75, 0.25, 0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.25, 0.25,
0.5, 0.5, 0.75, 0.25, 0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.5, 1, 1,
1, 0.5, 0.5, 1, 1,
0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.25, 0.25, 1
};
for (int i = 0; i < (sizeof(music1) / sizeof(music1[0])); i++)
{
tone(Buzzer, music1[i]); //驱动蜂鸣器
delay(music1_delay[i] * 500); //节拍实现
noTone(Buzzer); //停止蜂鸣器
}
}
/*******小蜜蜂*******/
void little_Bee()
{
//频谱
int little_Bee[] = {
M5, M3, M3, none,
M4, M2, M2, none,
M1, M2, M3, M4,
M5, M5, M5, none,
M5, M3, M3, M3,
M4, M2, M2, M2,
M1, M3, M5, M5,
M3, M3, M1, none,
M2, M2, M2, M2,
M2, M3, M4, none,
M3, M3, M3, M3,
M3, M4, M5, none,
M5, M3, M3, M3,
M4, M2, M2, M2,
M1, M3, M5, M5,
M3, M3, M1, none
};
/*由于是四四拍,所以节拍简单*/
int Bee_delay[] = {
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1
};
for (int i = 0; i < (sizeof(little_Bee) / sizeof(little_Bee[0])); i++)
{
tone(Buzzer, little_Bee[i]); //驱动蜂鸣器
delay(500); //节拍实现
noTone(Buzzer); //关闭蜂鸣器
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); //初始化
irrecv.enableIRIn(); //初始化
}
void loop() {
// put your main code here, to run repeatedly:
/******用于查看遥控器按键的编码,在串口输出*******
String a = ''; //定义一个空的字符串,用于接收红外遥控器返回的值
if (irrecv.decode(&results))
{
a=results.value;
Serial.println(a);
}
*/
if (irrecv.decode(&results)) //判断红外接收器是否收到遥控器发来的命令
{
long int a = 0;
a=results.value;
Serial.println(a);
switch(a)
{
case 16753245 : little_Bee();break;
case 16736925 : music1(); break;
default: irrecv.resume(); break;
}
}
}
其中IRremote.h
红外的库需要注意一下,如何接收和处理遥控器发过来的值。
这个程序是首先通过把遥控器发过来的值在串口打印出来,利用Switch…case语句把红外遥控接收到的值和实际键值做比对。
case 16753245 : little_Bee();break;
这一句就是把Switch语句中传进来的形参和红外接收器接收到的值与按键1的值做对比
case 16736925 : music1(); break;
这一句就是把Switch语句中传进来的形参和红外接收器接收到的值与按键1的值做对比
从而达到按下按键1,播放《小蜜蜂》,按下按键2,播放《有酒今朝醉》
模拟电子琴
在上面程序的基础上加上一个简单的电子琴功能,分别用7个按钮控制音节,然后把C调分为3个部分,低、中、高(非音乐专用,勿喷!)。
上面做红外遥控播放《小蜜蜂》时,用到了遥控器的1、2两颗按键,现在根据上面的代码继续拓展。
接线
按钮采用共阴的接法
代码
#include <IRremote.h>
/********C调*********/
#define L1 262
#define L2 294
#define L3 330
#define L4 349 //低
#define L5 392
#define L6 440
#define L7 494
#define M1 523
#define M2 587
#define M3 659
#define M4 698 //中
#define M5 784
#define M6 880
#define M7 988
#define H1 1046
#define H2 1109
#define H3 1318
#define H4 1397 //高
#define H5 1568
#define H6 1760
#define H7 1976
#define none 0 //空
/**********************/
const int RECV = 10; //定义红外遥控接收器的数据接口
IRrecv irrecv(RECV);
decode_results results; //创建红外遥控对象
const int Buzzer = 11; //定义蜂鸣器接口
int arrLength; //定义一个变量用于计算数组的长度
/*****定义模拟电子琴按键******/
const int KEY_1 = 2;
const int KEY_2 = 3;
const int KEY_3 = 4;
const int KEY_4 = 5;
const int KEY_5 = 6;
const int KEY_6 = 7;
const int KEY_7 = 8;
const int KEY_8 = 9; //用于跳出电子琴循环
/*******有酒今朝醉*******/
void music1()
{
//频谱
int music1[] = {
L5, M1, M2,
M3, M5, M5, M6, M5, M3, M2, M1, M1, M2,
M3, M3, M2, M1, M2, none, M2, M1,
M3, M5, M5, M6, M5, M3, M2, M1, M1, M2,
M3, M3, M2, M2, M1, none,
M4, M4, M5, M6, M6,
M5, M5, M3, M1, M2, none, M1, M2,
M3, M5, M5, M6, M5, M3, M2, M1, M1, M2,
M3, M3, M2, M2, M1, M1
};
//节拍
float music1_delay[] = {
0.5, 0.25, 0.25,
0.5, 0.5, 0.75, 0.25, 0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.25, 0.25,
0.5, 0.5, 0.75, 0.25, 0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.5, 1, 1,
1, 0.5, 0.5, 1, 1,
0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
0.5, 0.5, 0.5, 0.25, 0.25, 1
};
for (int i = 0; i < (sizeof(music1) / sizeof(music1[0])); i++)
{
tone(Buzzer, music1[i]); //驱动蜂鸣器
delay(music1_delay[i] * 500); //节拍实现
noTone(Buzzer); //停止蜂鸣器
}
}
/*******小蜜蜂*******/
void little_Bee()
{
//频谱
int little_Bee[] = {
M5, M3, M3, none,
M4, M2, M2, none,
M1, M2, M3, M4,
M5, M5, M5, none,
M5, M3, M3, M3,
M4, M2, M2, M2,
M1, M3, M5, M5,
M3, M3, M1, none,
M2, M2, M2, M2,
M2, M3, M4, none,
M3, M3, M3, M3,
M3, M4, M5, none,
M5, M3, M3, M3,
M4, M2, M2, M2,
M1, M3, M5, M5,
M3, M3, M1, none
};
/*由于是四四拍,所以节拍简单*/
int Bee_delay[] = {
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1
};
for (int i = 0; i < (sizeof(little_Bee) / sizeof(little_Bee[0])); i++)
{
tone(Buzzer, little_Bee[i]); //驱动蜂鸣器
delay(500); //节拍实现
noTone(Buzzer); //关闭蜂鸣器
}
}
void setup() {
// put your setup code here, to run once:
pinMode(KEY_1, INPUT_PULLUP); //定义IO口模式
pinMode(KEY_2, INPUT_PULLUP);
pinMode(KEY_3, INPUT_PULLUP);
pinMode(KEY_4, INPUT_PULLUP);
pinMode(KEY_5, INPUT_PULLUP);
pinMode(KEY_6, INPUT_PULLUP);
pinMode(KEY_7, INPUT_PULLUP);
pinMode(KEY_8, INPUT);
Serial.begin(9600); //初始化
irrecv.enableIRIn(); //初始化
}
void loop() {
// put your main code here, to run repeatedly:
/******用于查看遥控器按键的编码,在串口输出*******
String a = ''; //定义一个空的字符串,用于接收红外遥控器返回的值
if (irrecv.decode(&results))
{
a=results.value;
Serial.println(a);
}
*/
if (irrecv.decode(&results)) //判断红外接收器是否收到遥控器发来的命令
{
long int a = 0;
a = results.value;
Serial.println(a);
switch (a)
{
case 16753245 : little_Bee(); break;
case 16736925 : music1(); break;
case 16769565 : piano_L(); break;
case 16720605 : piano_M(); break;
case 16712445 : piano_H(); break;
default: irrecv.resume(); break;
}
}
}
/*******C调低电子琴***********/
void piano_L()
{
while (1) //死循环
{
if (digitalRead(KEY_1) == LOW) //判断按键是否被按下
{
tone(Buzzer, L1); //按下了,播放L1这个音节
delay(100);
noTone(Buzzer); //停止播放
}
else if (digitalRead(KEY_2) == LOW)
{
tone(Buzzer, L2);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_3) == LOW)
{
tone(Buzzer, L3);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_4) == LOW)
{
tone(Buzzer, L4);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_5) == LOW)
{
tone(Buzzer, L5);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_6) == LOW)
{
tone(Buzzer, L6);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_7) == LOW)
{
tone(Buzzer, L7);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_8) == HIGH) //如果按下的时KEY_8
{
break;
} //跳出循环
}
}
/*******C调中电子琴***********/
void piano_M()
{
while (1)
{
if (digitalRead(KEY_1) == LOW)
{
tone(Buzzer, M1);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_2) == LOW)
{
tone(Buzzer, M2);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_3) == LOW)
{
tone(Buzzer, M3);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_4) == LOW)
{
tone(Buzzer, M4);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_5) == LOW)
{
tone(Buzzer, M5);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_6) == LOW)
{
tone(Buzzer, M6);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_7) == LOW)
{
tone(Buzzer, M7);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_8) == HIGH)
{
break;
}
}
}
/*******C调高电子琴***********/
void piano_H()
{
while (1)
{
if (digitalRead(KEY_1) == LOW)
{
tone(Buzzer, H1);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_2) == LOW)
{
tone(Buzzer, H2);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_3) == LOW)
{
tone(Buzzer, H3);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_4) == LOW)
{
tone(Buzzer, H4);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_5) == LOW)
{
tone(Buzzer, H5);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_6) == LOW)
{
tone(Buzzer, H6);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_7) == LOW)
{
tone(Buzzer, H7);
delay(100);
noTone(Buzzer);
}
else if (digitalRead(KEY_8) == HIGH)
{
break;
}
}
}
通过按下红外遥控的3、4、5号按钮,实现三个C调不同音调的选择切换。
上电后,通过红外遥控器选择低、中、高声调的电子琴,按下按键即可实现蜂鸣器发出“Do、Re、Mi、Fa、Sol、La、Si”,可以试着弹奏自己喜欢的音乐。
总结
无源蜂鸣器,可以通过给它输入不同的频率,发出不同的声音,本次实验就是利用它的这个工作特性实现了简单的歌曲播放,和简易的电子琴,欢迎留言交流,大家相互学习进步。