2014-5-27 16:15:37 [显示全部楼层]
82929浏览
查看: 82929|回复: 40

[入门教程] Arduino教程 07 报警器「DFR0100」

[复制链接]
【本篇课程内容于 2024年9月20日更新】


这里我们要接触一个新的电子元件——蜂鸣器,从字面意思就可以知道,这是一个会发声的元件。这次做一个报警器,通过连接蜂鸣器到Arduino数字输出引脚,并配合相应的程序就可以产生报警器的声音。其原理是利用正弦波产生不同频率的声音。如果再结合一个LED,配合同样的正弦波产生灯光的话,就是一个完整的声光报警器了。

元件清单

Arduino教程 07 报警器「DFR0100」图1

硬件连接

按下图连接图连接,注意本项目蜂鸣器为无源蜂鸣器无正负之分。蜂鸣器的两个引脚分别接到GND和数字口8。

Arduino教程 07 报警器「DFR0100」图2

示例代码

输入下面的样例代码,这段代码引自《beginning-arduino》一书。

样例代码6-1:


//项目 - 报警器
float sinVal;
int toneVal;
void setup(){
     pinMode(8, OUTPUT);
}
void loop(){
     for(int x=0; x<180; x++){
          //将sin函数角度转化为弧度
            sinVal = (sin(x*(3.1412/180)));
            //将sin函数角度转化为弧度
            toneVal = 2000+(int(sinVal*1000));
            //用sin函数值产生声音的频率
            tone(8, toneVal);
            //将toneVal给引脚8
            delay(2);
     }   
}
```

下载程序完成后,你会听到平滑的一高一低的报警声,如同汽车报警器。

代码回顾

首先,定义两个变量:

float sinVal;

int toneVal;

浮点型变量sinVal用来存储正弦值,正弦波呈现一个波浪形的变化,变化比较均匀,所以我们选用正弦波的变化来作为我们声音频率的变换,toneVal从sinVal变量中获得数值,并把它转换为所需要的频率。

这里用的是sin()函数,一个数学函数,可以算出一个角度的正弦值,这个函数采用弧度单位。如图2,当弧度位于区间0~π,也就是角度位于区间0~180度时,sin()值为正。因为我们不想让函数值出现负数,所以设置for循环在0~179之间,也就是0≤x<180。

Arduino教程 07 报警器「DFR0100」图3

for(int x=0; x<180; x++)

函数sin()用的弧度单位,不是角度单位。要通过公式(3.1412/180)将角度转为弧度:

sinVal = (sin(x*(3.1412/180)));

这样sinVal的值将会根据角度的变化产生像波浪一样的起伏,之后,将这个值转变成相应的报警声音的频率:

toneVal = 2000+(int(sinVal*1000));

这里有个知识点——浮点型值转换为整型。
sinVal是个浮点型变量,也就是含小数点的值,而我们不希望频率出现小数点的,所以需要有一个浮点值转换为整型值得过程,也就是下面这句语句就完成了这件事:

int toneVal;

把sinVal乘以1000,转换为整型后再加上2000赋值给变量toneVal,现在toneVal就是一个适合声音频率了。
之后,我们用tone()函数把生成的这个频率给我们的蜂鸣器。

tone(8, toneVal);

下面我们来介绍一下tone相关的三个函数

  1. tone(pin,frequency)
    Pin都是指连接到蜂鸣器的数字引脚,frequency是以Hz为单位的频率值。
  2. tone(pin,frequency,duration)
    第二个函数,有个duration参数,它是以毫秒为单位,表示声音长度的参数。像第一个函数,如果没有指定duration,声音将一直持续直到输出一个不同频率的声音产生。
  3. noTone(pin)
    noTone(pin)函数,结束该指定引脚上产生的声音。

硬件回顾

蜂鸣器

蜂鸣器其实就是一种会发声的电子元件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。

压电式蜂鸣器和电磁式蜂鸣器区别

压电式蜂鸣器是以压电陶瓷的压电效应,来带动金属片的振动而发声。当受到外力导致压电材料发生形变时压电材料会产生电荷。电磁式的蜂鸣器,则是利用通电导体会产生磁场的特性,通电时将金属振动膜吸下,不通电时依振动膜的弹力弹回。不太明白也没太大关系,不影响我们使用。压电式蜂鸣器需要比较高的电压才能有足够的音压,一般建议为9V以上。电磁式蜂鸣器用1.5V就可以发出85dB以上的音压了,但消耗电流会大大的高于压电式蜂鸣器。所以还是建议初学者使用电磁式蜂鸣器。

有源蜂鸣器和无源蜂鸣器区别

无论是压电式蜂鸣器还是电磁式蜂鸣器,都有有源蜂鸣器和无源蜂鸣器两种区分。
有源蜂鸣器和无源蜂鸣器的根本区别是输入信号的要求不一样。这里的“源”不是指电源,而是指振荡源,有源蜂鸣器内部带振荡源,说白了就是只要一通电就会响。而无源内部不带震荡源,所以如果仅用直流信号无法使其响,必须用2K-5K的方波去驱动它。
从外观上看,有源无源的区别在于,有源蜂鸣器有长短脚,也就是所谓正负极,长脚为正极,短脚为负极。而无源蜂鸣器则没有正负极,两个引脚长度相同。

在套件中,我们为初学者选用的蜂鸣器类型是无源蜂鸣器,可以演奏出不同的音乐效果。
蜂鸣器的应用有很多,我们也可以就蜂鸣器做一些好玩的东西,比如常见的会结合蜂鸣器的有,红外传感器,超声波传感器,用于监测物体靠近报警。温度传感器,测到温度过高报警。气体传感器,有气体泄漏报警等等。除了报警,还可以用来作为乐器,通过不同频率,调成乐谱的不同调式,是不是很amazing?

课后练习

  1. 结合红色LED灯做一个完整的报警器。
    提示:可以让LED也随着sin函数变化,使声音与灯光节奏保持一致。

  2. 结合【交通信号灯】中介绍的按钮,做个简易门铃的效果,每次按下按钮,蜂鸣器发出提示音。

DF创客社区版权所有,欢迎转载。
转载请务必标注来源: DF创客社区+作者姓名+原文网址。



下载附件示例代码.rar

undercoldwater  见习技师

发表于 2017-3-14 16:00:27

第二个小作业:
结合项目4我做出来了按一下按键后报警同时亮灯,但是我有两个小问题想请教一下
1. 报警完之后我想要buzzer静音,所以设置了tone(8,0),可是蜂鸣器还是会响。
2.代码要怎么改才能实现灯还有buzzer触发n轮? 具体点就是从报警器从最小声到最大到最小声响三遍。
附我改写的代码:
  1. float sinVal;
  2. int toneVal;
  3. int ledVal;
  4. int button=10;//pin for button
  5. int presstime=5000;
  6. unsigned long changeTime;//time after press the button
  7. void setup(){
  8.     pinMode(8,OUTPUT);//buzzer引脚
  9.     pinMode(9, OUTPUT);//Led引脚
  10.     pinMode(button,INPUT);//按键引脚
  11. }
  12. void loop(){
  13.     int state = digitalRead(button);
  14.      //检测按钮是否被按下,并且是否距上次按下后有3秒的等待时间
  15.      if(state == HIGH && (millis() - changeTime)> 3000){
  16.                 //调用变灯函数
  17.                changeLights();
  18.        }
  19. }
  20. void changeLights(){
  21.     for (int x=0;x<180;x++){
  22.         sinVal=(sin(x*(3.14/180)));
  23.         toneVal=2000+(int(sinVal*1000));
  24.         tone(8, toneVal);
  25.         ledVal=int(sinVal*200);
  26.         analogWrite(9, ledVal);
  27.         delay(20);
  28.     }
  29.     changeTime = millis();
  30.     tone(8,1);
  31.     analogWrite(9,0);
  32. }
复制代码

回复

使用道具 举报

Cherry_island  学徒

发表于 2017-4-14 16:30:15

  1. /*1、结合红色LED灯做一个完整的报警器。
  2. 提示:可以让LED也随着sin函数变化,使声音与灯光节奏保持一致。
  3. */
  4. int ledPin=10;
  5. int buzze=8;
  6. void setup() {
  7.   // put your setup code here, to run once:
  8.   pinMode(ledPin,OUTPUT);
  9.   pinMode(buzze,OUTPUT);
  10. }
  11. void loop() {
  12.   // put your main code here, to run repeatedly:
  13. float sinVal;
  14. int toneVal;
  15. int ledVal;
  16.      for(int x=0; x<180; x++){
  17.             //将sin函数角度转化为弧度
  18.             sinVal = (sin(x*(3.1412/180)));
  19.             //用sin函数值产生声音的频率
  20.             toneVal = 2000+(int(sinVal*1000));
  21.             //led输出值
  22.             ledVal = 55+(int(sinVal*200));
  23.             //给引脚8一个
  24.             tone(buzze, toneVal);
  25.             analogWrite(ledPin,ledVal);
  26.             delay(2);
  27.      }   
  28. }
复制代码

回复

使用道具 举报

Kaiii  学徒

发表于 2023-2-22 20:51:24

课后第一题  红灯和蜂鸣器
  1. int node = 8;
  2. int led = 7;
  3. float sinVal;
  4. int toneVal;
  5. void setup() {
  6.   // put your setup code here, to run once:
  7.   pinMode(node,OUTPUT);
  8.   pinMode(led,OUTPUT);
  9. }
  10. void loop() {
  11.   for(int i = 0; i < 180; i++){
  12.     sinVal = (sin(i*(3.14/180)));
  13.     toneVal = 1000 + (int(sinVal*(1000)));
  14.     tone(node,toneVal);
  15.     if(i <= 90){
  16.       digitalWrite(led,HIGH);
  17.     }else{
  18.       digitalWrite(led,LOW);
  19.     }
  20.     delay(2);
  21.   }
  22. }
复制代码
回复

使用道具 举报

snakeqx  学徒

发表于 2014-6-26 19:27:09

步骤6第一个我已经完成,代码如下:

  1. float sinVal;
  2. int toneVal;
  3. int ledVal;
  4. void setup(){
  5.     pinMode(8,OUTPUT);
  6.     pinMode(9, OUTPUT);
  7. }
  8. void loop(){
  9.     for (int x=0;x<180;x++){
  10.         sinVal=(sin(x*(3.14/180)));
  11.         toneVal=2000+(int(sinVal*1000));
  12.         tone(8, toneVal);
  13.         ledVal=int(sinVal*200);
  14.         analogWrite(9, ledVal);
  15.         delay(20);
  16.     }
  17. }
复制代码

但是联线的时候发现一个问题, LED的ground必须接在arduino uno上方的GND,如果使用prototyping shield也必须接在那里。如果接在prototyping 右边红色部分的GND,灯是不会亮的。
请问一下这是怎么回事啊?
谢谢 !
回复

使用道具 举报

snakeqx  学徒

发表于 2014-6-26 19:31:13

snakeqx 发表于 2014-6-26 19:27
步骤6第一个我已经完成,代码如下:

晕,我看错了,prototyping shield右边红色部分是5V输出,黑色部分才是GND.。。。
抱歉。
回复

使用道具 举报

Jane  高级技匠
 楼主|

发表于 2014-6-27 15:24:45

snakeqx 发表于 2014-6-26 19:31
晕,我看错了,prototyping shield右边红色部分是5V输出,黑色部分才是GND.。。。
抱歉。 ...

解决问题就好~
回复

使用道具 举报

半水  见习技师

发表于 2015-1-30 20:38:31

买的配件里的是无源蜂鸣器。。。
回复

使用道具 举报

Tommy  见习技师

发表于 2015-6-30 14:52:21

顶一个,好好学习
回复

使用道具 举报

Jane  高级技匠
 楼主|

发表于 2015-7-1 14:15:01

半水 发表于 2015-1-30 20:38
买的配件里的是无源蜂鸣器。。。

是的 蜂鸣器有变动,不过不影响使用的
回复

使用道具 举报

1522631876  见习技师

发表于 2015-8-2 10:50:39

snakeqx 发表于 2014-6-26 19:27
步骤6第一个我已经完成,代码如下:

我想问一下  ledVal=int(sinVal*200) 怎么保证ledVal的值在0到255之间  
回复

使用道具 举报

powermaster  见习技师

发表于 2016-1-5 11:10:43

snakeqx 发表于 2014-6-26 19:27
步骤6第一个我已经完成,代码如下:

看了您的代码才明白基于过程的实现方法。我一直在想LED和蜂鸣器同时工作需要多线程来处理呢。
回复

使用道具 举报

xuexideyang  见习技师

发表于 2016-1-30 12:10:25

pinmode 9也输出了,是不是要在硬件电路接一个灯?还是?
回复

使用道具 举报

Jane  高级技匠
 楼主|

发表于 2016-2-2 15:34:13

xuexideyang 发表于 2016-1-30 12:10
pinmode 9也输出了,是不是要在硬件电路接一个灯?还是?

样例代码没有用到9,只用了Pin 8
回复

使用道具 举报

木龙小驴  见习技师

发表于 2016-2-23 21:25:10

警报真的好难听,弄个小曲儿

本帖最后由 木龙小驴 于 2016-2-23 21:31 编辑

警报真的好难听,弄个小曲儿
  1. float sinVal;
  2. int toneVal;
  3. static int times = 0;
  4. int diaodiao[9] = {262,294,330,349,392,440,494,523,478};  //网上能搜到音律的赫兹数,用数组保存
  5. char SUNANA[128]="123556531233212.123556531233221.44466655312.123556531233221";   //随便搜个曲子,用字符数组保存
  6. void setup() {
  7.   // put your setup code here, to run once:
  8.   pinMode(10, OUTPUT);
  9. }
  10. void loop() {
  11.   // put your main code here, to run repeatedly:
  12.   goSing(SUNANA);
  13. }
  14. void goSing(char *music){
  15.   for(int i=0;i<128;i++){
  16.     int index = music[i]-48;     //ascii码里字符 '1'= 49,所以需要减去48
  17.     if(index >0 && index <10){
  18.       tone(10, diaodiao[index],200);    //发出声音,200毫秒持续时间
  19.     }else{
  20.       delay(500);
  21.     }
  22.    
  23.     if(music[i] == 0){       //由于C语言数组默认是0,所以遇到0就break(跳出循环)
  24.       break;
  25.     }
  26.     delay(200);
  27.   }
  28.      
  29. }
  30. //整体还有些问题,就是tone这个函数,只有赫兹数变化才会发声,比如do ri,如果是dodo,就会发一个,希望哪位大神能指导小弟。
复制代码
回复

使用道具 举报

xxlll66  见习技师

发表于 2017-2-22 18:15:15

怎么看不到图啊
回复

使用道具 举报

undercoldwater  见习技师

发表于 2017-3-14 16:15:03

还有一个问题想要请教下我该怎么操作才能插入代码框==我弄了好一会儿还是弄不出来,发出来的代码看起来丑丑的
回复

使用道具 举报

颖丸子  学徒

发表于 2017-3-21 14:43:11

看不见图怎么办?
回复

使用道具 举报

Jane  高级技匠
 楼主|

发表于 2017-3-24 23:31:22

回复

使用道具 举报

Cherry_island  学徒

发表于 2017-4-14 16:35:17

undercoldwater 发表于 2017-3-14 16:00
第二个小作业:
结合项目4我做出来了按一下按键后报警同时亮灯,但是我有两个小问题想请教一下
1. 报警完之 ...

关闭蜂鸣器声音,noTone(pin)
回复

使用道具 举报

zhuceyoujue  见习技师

发表于 2017-4-24 09:50:03

请问硬件搭建的电路图怎么没有显示?
回复

使用道具 举报

白先森  见习技师

发表于 2017-6-17 15:06:02

xxlll66 发表于 2017-2-22 18:15
怎么看不到图啊

恢复得创造力?
回复

使用道具 举报

12下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

硬件清单

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

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

mail