(二十三)树莓派3B+ 驱动蜂鸣器播放《茉莉花》

在上一篇(十二)树莓派3B+ node-rpio库的使用–硬件PWM中已经介绍了树莓派的PWM的使用。这里实际就是在上一个的基础之上的一个应用。需要一些关于简谱和蜂鸣器的基本知识了。

1.简谱相关知识

简谱是指一种简易的记谱法。有字母简谱和数字简谱两种。
数字简谱以可动唱名法为基础,用1、2、3、4、5、6、7代表音阶中的7个基本级,读音为do、re、mi、fa、sol、la、ti(中国为si),英文由C、D、E、F、G、A、B表示,休止以0表示。每一个数字的时值名相当于五线谱的4分音符。
一般来说,所有音乐的构成有四个基本要素,而其中最重要的是“音的高低”和“音的长短”:
1、音的高低:任何一首曲子都是高低相间的音组成的,从钢琴上直观看就是越往左面的键盘音越低,越往右面的键盘音越高。就数字简谱来说,在数字的正上方或下方有若干点“˙”.“︰”符,点的多少可以理解为强度,越多越强,在其上方代表高音,在其下方代表低音。原理表现为物体振动频率,越高音振动频率越高,反之亦然。
2、音的长短:除了音的高低外,还有一个重要的因素就是音的长短。音的高低和长短的标注决定了该首曲子有别于另外的曲子,因此成为构成音乐的最重要的基础元素。原理表现为声音的时值长短。
3、音的力度:音乐的力度很容易理解,也叫强度。一首音乐作品总会有一些音符的力度比较强一些,有些地方弱一些。而力度的变化是音乐作品中表达情感的因素之一。原理表现为振幅的大小。
4、音质:也可以称音色。也就是发出音乐的乐器或人声。同样旋律的音高,男生和女生唱就不一样的音色;小提琴和钢琴的音色就不一样。
上述四项构成了任一首乐曲的基础元素。应该说简谱基本可以将这些基础性元素正确标注。
这里的4个因素在接下来的实验中可以总结为如下:

  1. 音可以用用1、2、3、4、5、6、7代表;
  2. 音的高低反应出来的就是声音的频率;
  3. 音的长短就是声音的节拍了,也就是长度;
  4. 音的力度是振幅的大小,在上一篇中,强度可以理解为占空比;
  5. 音质这个就是不同发声体的发声不一样。

在接下来的实验中,只需要关注1、2、3这3点。第4点我是固定在50%的占空比;第5点都是蜂鸣器,所以发声体固定了。

2.音的频率

下面介绍的都是7个音符,在低音、中音、高音下对应的不同频率:

1 2 3 4 5 6 7
低音(Hz) 262 294 330 349 392 440 494
中音(Hz) 523 587 659 698 784 880 988
高音(Hz) 1046 1175 1318 1397 1568 1760 1976

这里可以大致看是,低音是中音的一半,中音是高音的一半。
在简谱中低音、中音、高音的表示,这里极简一下:
1.正常一个音符的是中音,
2.音符下面1个实心圆点的是低音,2个是倍低音(这里都当低音处理);
3.音符上面1个实心圆点的是高音,2个是倍高音(这里都当高音处理);
4.在一般的歌曲中倍低音和倍高音计较少见,所以都当低音或者高音处理了。
接下来我们就可以构建一个二维数组了,低音、中音、高音各装7个音对应的频率。

let music_note = [
  [ 262,  294,  330,  349,  392,  440,  494  ], // 低音 1 2 3 4 5 6 7
  [ 523,  587,  659,  698,  784,  880,  988  ], // 中音 1 2 3 4 5 6 7
  [ 1046, 1175, 1318, 1397, 1568, 1760, 1976 ]  // 高音 1 2 3 4 5 6 7
]

3.音的长短

上面的分析已经说了音的长短就是节拍,每个音的长度,这里我们可以使用延时来实现一个特定音的长度了。但是这个延时是多少了呢?在简谱中每个音符有多少个节拍呢?在简谱中节拍怎么表示呢?这里请自行查找,我就说下我找到的规律在缩减下:
1.音符基础节拍是2个,
2.音符下面带一个横线的是1个节拍,下面2个横线的做一个横线处理(2个横线的在简谱中出现的很少),都是1拍
3.音符右边加1个横线的是3个节拍,加更多的都是4个了(太多了不好听了)

4.蜂鸣器相关知识

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电。蜂鸣器的发声原理由振动装置和谐振装置组成,而蜂鸣器又分为无源蜂鸣器与有源蜂鸣器。这里的“源”不是指电源。而是指的振荡源。
无源蜂鸣器内部没有驱动电路,需要接在音频输出电路中才能发声。声音频率可控,可以做出“多来米发梭拉西”的效果。
无源蜂鸣器的工作发声原理是:方波信号输入谐振装置转换为声音信号输出,无源他激型蜂鸣器的工作发声原理图如下:
在这里插入图片描述

有源蜂鸣器内部有一个简单的振荡电路,能将恒定的直流转化成一定频率的脉冲信号,程序控制方便但频率固定,一个高低电平就可以发声。
有源蜂鸣器的工作发声原理是:直流电源输入经过振荡系统的放大取样电路在谐振装置作用下产生声音信号,有源自激型蜂鸣器的工作发声原理图如下:
在这里插入图片描述

我使用的是无源蜂鸣器:
(二十三)树莓派3B+ 驱动蜂鸣器播放《茉莉花》_第1张图片

无源蜂鸣器驱动电路:
(二十三)树莓派3B+ 驱动蜂鸣器播放《茉莉花》_第2张图片

5.实验电路图

上班了再截图吧

6.实验代码

music_note.js文件存放低音、中音、高音各装7个音对应的频率表:

let music_note = 
[
  [ 262,  294,  330,  349,  392,  440,  494  ], // 低音 1 2 3 4 5 6 7
  [ 523,  587,  659,  698,  784,  880,  988  ], // 中音 1 2 3 4 5 6 7
  [ 1046, 1175, 1318, 1397, 1568, 1760, 1976 ]  // 高音 1 2 3 4 5 6 7
];
module.exports = music_note;

molihua.js文件存放简谱表:

// 第一个数字是音符的数值1234567之一,代表多来咪发...
// 第二个数字是012之一,代表低音、中音、高音
// 第三个数字是时间长度,以半拍为单位  1 2 3 4
let molihua = [
  // 好 一朵美 丽的
  3, 1, 2,   // 音符3 中音 2拍
  3, 1, 1,   // 音符3 中音 1拍
  5, 1, 1,   // 音符5 中音 1拍
  6, 1, 1,   // 音符6 中音 1拍
  1, 2, 1,   // 音符1 高音 1拍
  1, 2, 1,   // 音符1 高音 1拍
  6, 1, 1,   // 音符6 中音 1拍
  …… 省略
]
module.exports = molihua;

看上面的代码需要一份《茉莉花》的简谱:
(二十三)树莓派3B+ 驱动蜂鸣器播放《茉莉花》_第3张图片

song.js文件就是播放音乐的具体代码实现了。有了上面的介绍,下面的实现就不难了。

let rpio = require('rpio');
let musicNode = require('./music_note');
let molihua = require('./molihua');

let pwm_pin = 12;    // 定义 排针的第12引脚 PWM输出引脚
let clockdiv = 64;  // 19.2 * 1000000 / 64 = 300KHz
let pwm_range = 1024;
let bsseFreq = 300000; // 300HKz  基础频率

// pwm初始化
function pwmInit() {
     
  rpio.init({
     gpiomem: false});    /* Use /dev/mem for i²c/PWM/SPI */
  rpio.open(pwm_pin, rpio.PWM);
  rpio.pwmSetClockDivider(clockdiv); // 基础评率 100KHz
  rpio.pwmSetRange(pwm_pin, pwm_range);
}

// 播放音乐 逻辑的实现  播放其他歌曲只需替换歌曲文件即可
function song(){
     
  let molihua_len = molihua.length;
  for (let i = 0; i < molihua_len; i+=3) {
     
    let nodeIndex = i;  // 第几个位置
    let nodeItem = molihua[nodeIndex];     // 音符  目标频率
    let nodeDiao = molihua[nodeIndex + 1]; // 音调
    let nodePai = molihua[nodeIndex + 2];  // 节拍

    let range = bsseFreq / musicNode[nodeDiao][nodeItem - 1]; // 获取谱曲表中音符的频率 计算range值
    pwm_range = Math.ceil(range); // 取整 小数+1
    let data = pwm_range * 0.5; // 占空比 50%
    data = Math.ceil(data);

    rpio.pwmSetRange(pwm_pin, pwm_range);  
    rpio.pwmSetData(pwm_pin, data); 
    rpio.msleep(nodePai * 180); // 基础延时180ms  一个节拍180ms    
  }
}

function main(){
     
  pwmInit();
  while(1){
     
    song();
    rpio.sleep(2); // 暂停2s后循环播放    
  }
}
main()

7.实验现象

关注我查看视频

你可能感兴趣的:(树莓派学习记录,树莓派,node.js,PWM,蜂鸣器)