首页
社区
课程
招聘
[原创]初玩树莓派B 5控制蜂鸣器演奏乐曲
发表于: 2016-9-23 21:50 15622

[原创]初玩树莓派B 5控制蜂鸣器演奏乐曲

2016-9-23 21:50
15622
初玩树莓派 B   5控制蜂鸣器演奏乐曲

bbs.pediy.com

步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这次尝试用GPIO的PWM接口驱动无源蜂鸣器弹奏一曲《一闪一闪亮晶晶》。

1无源蜂鸣器和有源蜂鸣器

主要是当初我自己也没有意识到蜂鸣器还区分有源和无源的,买到手接上电源,就是不出声,这才发现我买的蜂鸣器是无源的蜂鸣器。

无源蜂鸣器:
1无源内部没有震荡源,直流信号无法让它鸣叫。必须用去震荡的电流驱动它,2K-5KHZ的方波PWM (Pulse Width Modulation脉冲宽度调制)。 5KHZ的电流方波是啥意思?那就是每秒震动5K次,每一个完整的周期占用200us的时间,高点平占一部分时间,低电平占一部分时间。

2 声音频率可控,可以做出不同的音效。

有源蜂鸣器:
1内部带震荡电路,一通电就鸣叫,所以可以跟前面LED一样,给个高电平就能响,编程比无源的方便。

无源的比有源的便宜,无源的2毛,有源的4毛。我买的无源蜂鸣器,该蜂鸣器阻抗42欧姆 ,可以用3V 和5V的来驱动。树莓派高电平恰好是3.3V。

在这之前我根本不懂还区分有源和无源蜂鸣器,才有后续的曲折和摸索。



这种蜂鸣器正负极有很明显的标记 + -。

2 PWM和输出模式

单纯和上次一样操作设置GPIO口的高低是没法实现输出PWM的。好在树莓派的某些PIN口有这种模式,那就是PIN12口。可以通过控制PIN12口的PWM模式来实现。就理解为方波把。由于pygpio暂不支持操作硬件的PWM。这里我们用wiringpi库。

wiringPi中的pinMode (1,PWM_OUT),可以设置模式。PIN12是wiringpi的1号。



图中t(pwm)就是一个周期的时间长度。对于2K频率来说,那么周期就是1S/2K=500us。图中的D叫做占空比。指的是高电平的时间占用整个周期时间的百分比。第一个周期D=50%,那么就是高电平低电平的时间各占一半。接下来的D为33%,那就是通电时间为33%,剩余的不通电时间占用67%。

占空比的确会影响频率,但是我没有具体去探究会如何影响频率。我测试的时候使用的占空比是50%,也就是高低电平各占用一半的时间。

由于可以参考的例子是在太少了。只能自己翻芯片手册查找相关资料。具体的相关资料在BCM2835芯片手册的第九章(具体翻阅手册查看,真是最好的办法)。阅读这一章以后我得出的关键点有如下几点:
1 PWM的频率是受时钟管理器控制的,(树莓派的基础时钟频率是19.2MHZ)。
2 PWM的输出占空比模式有两种,一种是平衡模式,一种是MS模式。

先看占空比中的平衡模式和MS模式,假设我们希望输出的占空比为 N/M。

平衡模式是指的按照某一种算法计算何时发送低电平,何时发送高电平,该算法力求任意一段时间占空比都最接近N/M,下图是(4/8的时候的几种发送方式),很显然good的算法任意取得一段时间都更加接近4/8。

M/S模式就是整个S周期内,先发送M时间的高电平,剩余的S-M时间为低电平。



因此如果是4/8的占空比。

M/S模式8个时间长度内发送的就是 11110000 (周期为8个时间长度)。   而平衡模式则是 10101010(可以说最小周期为2个时间长度,大的周期为 8个时间长度)。

可能看不懂没关系。用图来解释更有说服力。

假设我们需要的频率为5KHZ,那么周期时间就是1s/5000hz=200us。设定占空比为 0.5 也就是高低电平各占一半,那么需要高电平占100us,低电平占100us。

如果是平衡模式。一个大周期内(200us)波形图看起来如下:


也就是这个大周期内,任意取一段时间占空比都接近0.5,其实实际频率比5K要大几倍。

如果是MS模式。则看起来如下:



显然这个才是我们需要的标准的5K频率。因为这个模式最小频率就是200us了。
wiringPi中的pwmSetMode (PWM_MODE_MS) 可以设置为ms模式。

前面说到树莓派基础时钟频率是19.2MHZ。pwm也受这个基础频率的控制,也就是最小的基础周期是1/19200000 S。这个周期太小了,我们控制蜂鸣器需要2-5K的频率。我们先将基础频率调大一些。通过pwmsetClock(int clock)可以将时钟基础频率设置为 19.2M/clock的大小。然后我们再基于这个频率通过pwmsetRasnge(int range)设置最终的频率,range的范围是2-4095。
通过pwmsetClock(clock)以及pwmsetRasnge(range)将最终的频率控制在 19.2MHz/clock/range的大小。
这里我设置clock为32 将时钟基础频率设置为19.2MHZ/32=600khz。
这样我们只要设置range从300到120就能得到2k-5k的频率。

那如何设置占空比呢?还有一个函数pwmWrite(value)。value指定了range指定的时间内发送高电平的基础周期个数(以时钟基础频率计算)。因此value/range就是占空比。pwmWrite(range/2)就能得到50%的占空比。range/5 就得到20%占空比。如果设置value为0,那么就是这段时期内一直是低电平,没有任何高电平,蜂鸣器就不发声了。
验证一下如下图。


50% (range/2)

20% (range/5)

因此我们可以初始化里面这么写

void init() 
{ 
  if (wiringPiSetup () == -1) 
       exit (1) ; 
  //设置针脚为pwm输出模式
  pinMode (1, PWM_OUTPUT) ;
//设置pwm 信号模式为ms模式
  pwmSetMode(PWM_MODE_MS);
 //设置时钟基础频率为19.2M/32=600KHZ 
  pwmSetClock(32); 
} 


为了后续能弹奏不同频率的音阶。封装一个beep函数以及beep的持续时间。

void beep(int freq,int t_ms) 
{ 
      int range; 
      if(freq<2000||freq>5000) 
      { 
	printf("invalid freq"); 
	return; 
      } 
      //设置range为 600KHZ/freq。也就是由range个1/600KHZ组成了freq频率的周期。
      range=600000/freq。
      pwmSetRange(range); 
      //设置占空比为50%。
      pwmWrite(1,range/2); 
      if(t_ms>0) 
      { 
	delay(t_ms); 
      } 
}


通过delay来控制延时。
通过 pwmWrite(1,0)来关闭输出。

剩下的就是查找 一闪一闪亮晶晶的简谱。对应设定好频率和持续时间。随后循环播放出来就可以了。
这里就只截图,具体代码下载pwm.c查看。







接线图如下。BCM标号1(PIN12 )接无源蜂鸣器的正极。负极接GND,为了接线方便。我买了扩展版和排线哦。(第一次错买了树莓派2的40 PIN,第二次卖家给我发错货了。第三次才买到,也是坎坷)。



编译执行
gcc -o pwm pwm.c -lwiringpi
sudo ./pwm
就可以听到播放曲谱了。
建议不要多听。因为2K-5K的频率对于人的耳朵实在是有点高了,听多了刺耳心慌。
学会了pwm就可以控制一些需要脉冲波控制的外部设备了。

有人会说,设置GPIO为输出模式。
PinWrite(1);
sleep(100us);
pinWrite(0);
sleep(100us);
这样不是也行吗?
的确这样是可以的,但是CPU占用的资源很高。使用python的话时间控制更是不精准,因此既然有硬件的PWM模块我们还是使用一下这个功能把。

其实我没想本节这么复杂的。以为蜂鸣器接上电源就会响。不过省了两毛钱的同时还让我学到了更多的东西。有时候网上查不到的一些东西,就需要自己认认真真查看相关资料测试。还有就是硬件比软件麻烦多了。

下一节是人体感应器。感应到人体以后配合蜂鸣器报警。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
免费 3
支持
分享
打赏 + 5.00雪花
打赏次数 1 雪花 + 5.00
 
最新回复 (6)
雪    币: 44229
活跃值: (19960)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
感谢分享,辛苦了
2016-9-23 22:02
0
雪    币: 47
活跃值: (376)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
非常感谢,辛苦了,这个系列的我都会看,不过有好多不懂的地方,希望多看几遍,动手操作几次就掌握了
2016-10-13 23:06
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
专门注册了账号来点赞,并赞赏了5块钱。这是我用树莓派驱动的第一个硬件,为知识付费是应该的,当然要点赞了。
另外,我觉得楼主认真的态度特别值得学习,希望有机会认识一下。
2017-6-5 20:59
0
雪    币: 1392
活跃值: (4872)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
5
beAcoder 专门注册了账号来点赞,并赞赏了5块钱。这是我用树莓派驱动的第一个硬件,为知识付费是应该的,[em_20]当然要点赞了。 另外,我觉得楼主认真的态度特别值得学习,希望有机会认识一下。
土豪你好  土豪罩我
2017-6-6 10:56
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
pinMode  (1,  PWM_OUTPUT)  执行这句为什么会死机
2017-11-26 20:29
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
警告!!!
执行编译好的文件必须sudo啊
就是sudo  ./pwm这个!!
我测试的时候忘了加sudo,结果卡死,差点损坏sd卡...
2017-12-25 20:43
0
游客
登录 | 注册 方可回帖
返回
//