[Python]使用樹莓派+無源蜂鳴器播放<鐵血丹心>

源代碼: https://github.com/fly-studio...

條件

  • 樹莓派4B
  • 無源蜂鳴器3V: 3毛錢一個
  • 杜邦線: 2根
  • 語言: Python 3

接線

image.png

蜂鳴器正極: 做者使用的是GPIO 1 也就是第28個接口,
對於GPIO口沒有要求,只要GPIO口均可以html

GPIO 引腳圖見: https://pinout.xyz/

蜂鳴器負極: 任意GND接口git

無源蜂鳴器發出聲音

想讓無源蜂鳴器發出聲音,其實就是持續輸出PWM脈衝github

import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO.setup(1, GPIO.OUT) # 設置GPIO 1爲輸出
pwm = GPIO.PWM(1, 4978) # 設置GPIO 1爲PWM輸出, 脈衝爲4978Hz
pwm.start(0)
pwm.ChangeDutyCycle(50) # 持續發出脈衝電平
time.sleep(0.5) # 持續0.5s聲音
pwm.stop()

GPIO.cleanup()
上面 GPIO.PWM(1, 4978)就是 GPIO 1的輸出脈衝設置爲4978Hz,即1秒有4978個輸出週期
pwm.ChangeDutyCycle(50) 不能爲100,由於100等於沒有振盪電流,設置爲50便可

音符對照表

引用: https://shumeipai.nxez.com/20...

其實上例中4978對應的音符是D8#,其它音符能夠查看下圖的spa

image.png
音符定義 頻率 音名 簡譜
image.pngcode

開始編寫歌曲

因此,只要知道了簡譜,對比上表,就能夠調用不一樣的PWM脈衝來發出不一樣的聲音。htm

若是你要實現和絃,那就須要多個蜂鳴器

鐵血丹心的簡譜

image.png

三個文件

txdx.py # 簡譜
tone.py # 音符表
main.py

txdx.py

# 鐵血丹心的簡譜
# 能夠爲2種格式
# [音符名(string), 持續時間(s)]
# [頻率(int), 持續時間(s)]
txdx_sheet = [
    # 1
    ['NOTE_A4', 1.5],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_A4', 1],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_E4', 0.5],  # 3

    # 2
    ['NOTE_G4', 1],  # 5
    ['NOTE_D4', 3],  # 2

    # 3
    ['NOTE_C4', 1.5],  # 1
    ['NOTE_A3', 0.5],  # .6
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_F4', 0.5],  # 4

    # 4
    ['NOTE_E4', 3],  # 3
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_G4', 0.5],  # 5

    # 5
    ['NOTE_A4', 1.5],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_A4', 1],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_E4', 0.5],  # 5

    # 6
    ['NOTE_G4', 1],  # 5
    ['NOTE_D4', 3],  # 2

    # 7
    ['NOTE_C4', 1.5],  # 1
    ['NOTE_A3', 0.5],  # .6
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_G3', 0.5],  # .5
    ['NOTE_B3', 0.5],  # .7

    # 8
    ['NOTE_A3', 4],  # .6

    [0, 1],  # 0
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_C4', 1.5],  # 1
    ['NOTE_B3', 0.5],  # .7

    #
    ['NOTE_A3', 1.5],  # .6
    ['NOTE_E3', 0.5],  # .3
    ['NOTE_A3', 2],  # .6

    # ['NOTE_A3', 1],        # .6
    ['NOTE_A4', 0.5],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_E4', 1],  # 3
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_D4', 0.5],  # 2

    ['NOTE_E4', 3],  # 3

    ['NOTE_E4', 0.5],  # 3
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_C4', 1.5],  # 1
    ['NOTE_B3', 0.5],  # .7

    ['NOTE_A3', 1.5],  # .6
    ['NOTE_E3', 0.5],  # .6
    ['NOTE_A3', 2],  # .6

    [0, 1],  # 0
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_C4', 0.5],  # 1
    ['NOTE_A3', 1],  # .6
    ['NOTE_C4', 0.5],  # 1
    ['NOTE_D4', 0.5],  # 1

    ['NOTE_E4', 3],  # 3*/
    ['NOTE_E4', 1],  # 3 逐草四方

    ['NOTE_A4', 1.5],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_A4', 1],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_E4', 0.5],  # 3

    ['NOTE_G4', 1],  # 5
    ['NOTE_D4', 3],  # 2

    ['NOTE_C4', 1.5],  # 1
    ['NOTE_A3', 0.5],  # .6
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_FS4', 0.5],  # #4

    ['NOTE_E4', 3],  # 3
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_G4', 0.5],  # 5

    ['NOTE_A4', 1.5],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_A4', 1.0],  # 6
    ['NOTE_G4', 0.5],  # 5
    ['NOTE_E4', 0.5],  # 3

    ['NOTE_G4', 1.0],  # 5
    ['NOTE_D4', 3],  # 2

    ['NOTE_C4', 1.5],  # 1
    ['NOTE_A3', 0.5],  # .6
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_G3', 0.5],  # .5
    ['NOTE_B3', 0.5],  # .7

    ['NOTE_A3', 3],  # .6

    [0, 1],  # 0
    ['NOTE_E4', 0.5],  # 3 應知愛意似
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_C4', 1.0],  # 1
    ['NOTE_C4', 0.5],  # 1
    ['NOTE_B3', 0.5],  # .7

    ['NOTE_A3', 1.5],  # .6
    ['NOTE_E3', 0.5],  # .3
    ['NOTE_A3', 2.0],  # .6

    [0, 1],  # 0
    ['NOTE_A3', 0.5],  # .6
    ['NOTE_G3', 0.5],  # .5
    ['NOTE_E3', 1.0],  # .3
    ['NOTE_G3', 0.5],  # .5
    ['NOTE_D3', 0.5],  # .2

    ['NOTE_E3', 3.0],  # .3

    [0, 1],  # 0
    ['NOTE_E4', 0.5],  # 3 身經百劫也
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_C4', 1.0],  # 1
    ['NOTE_C4', 0.5],  # 1
    ['NOTE_B3', 0.5],  # .7

    ['NOTE_A3', 1.5],  # .6
    ['NOTE_E4', 0.5],  # 3
    ['NOTE_D4', 2.0],  # 2

    [0, 1],  # 0
    ['NOTE_D4', 0.5],  # 2
    ['NOTE_C4', 0.5],  # 1
    ['NOTE_A3', 1.0],  # .6
    ['NOTE_B3', 0.5],  # .7
    ['NOTE_G3', 0.5],  # .5

    ['NOTE_A3', 3.0],  # .6
]

tone.py 文件

TONE = {
    'NOTE_B0' : 31,
    'NOTE_C1' : 33,
    'NOTE_CS1': 35,
    'NOTE_D1' : 37,
    'NOTE_DS1': 39,
    'NOTE_E1' : 41,
    'NOTE_F1' : 44,
    'NOTE_FS1': 46,
    'NOTE_G1' : 49,
    'NOTE_GS1': 52,
    'NOTE_A1' : 55,
    'NOTE_AS1': 58,
    'NOTE_B1' : 62,
    'NOTE_C2' : 65,
    'NOTE_CS2': 69,
    'NOTE_D2' : 73,
    'NOTE_DS2': 78,
    'NOTE_E2' : 82,
    'NOTE_F2' : 87,
    'NOTE_FS2': 93,
    'NOTE_G2' : 98,
    'NOTE_GS2': 104,
    'NOTE_A2' : 110,
    'NOTE_AS2': 117,
    'NOTE_B2' : 123,
    'NOTE_C3' : 131,
    'NOTE_CS3': 139,
    'NOTE_D3' : 147,
    'NOTE_DS3': 156,
    'NOTE_E3' : 165,
    'NOTE_F3' : 175,
    'NOTE_FS3': 185,
    'NOTE_G3' : 196,
    'NOTE_GS3': 208,
    'NOTE_A3' : 220,
    'NOTE_AS3': 233,
    'NOTE_B3' : 247,
    'NOTE_C4' : 262,
    'NOTE_CS4': 277,
    'NOTE_D4' : 294,
    'NOTE_DS4': 311,
    'NOTE_E4' : 330,
    'NOTE_F4' : 349,
    'NOTE_FS4': 370,
    'NOTE_G4' : 392,
    'NOTE_GS4': 415,
    'NOTE_A4' : 440,
    'NOTE_AS4': 466,
    'NOTE_B4' : 494,
    'NOTE_C5' : 523,
    'NOTE_CS5': 554,
    'NOTE_D5' : 587,
    'NOTE_DS5': 622,
    'NOTE_E5' : 659,
    'NOTE_F5' : 698,
    'NOTE_FS5': 740,
    'NOTE_G5' : 784,
    'NOTE_GS5': 831,
    'NOTE_A5' : 880,
    'NOTE_AS5': 932,
    'NOTE_B5' : 988,
    'NOTE_C6' : 1047,
    'NOTE_CS6': 1109,
    'NOTE_D6' : 1175,
    'NOTE_DS6': 1245,
    'NOTE_E6' : 1319,
    'NOTE_F6' : 1397,
    'NOTE_FS6': 1480,
    'NOTE_G6' : 1568,
    'NOTE_GS6': 1661,
    'NOTE_A6' : 1760,
    'NOTE_AS6': 1865,
    'NOTE_B6' : 1976,
    'NOTE_C7' : 2093,
    'NOTE_CS7': 2217,
    'NOTE_D7' : 2349,
    'NOTE_DS7': 2489,
    'NOTE_E7' : 2637,
    'NOTE_F7' : 2794,
    'NOTE_FS7': 2960,
    'NOTE_G7' : 3136,
    'NOTE_GS7': 3322,
    'NOTE_A7' : 3520,
    'NOTE_AS7': 3729,
    'NOTE_B7' : 3951,
    'NOTE_C8' : 4186,
    'NOTE_CS8': 4435,
    'NOTE_D8' : 4699,
    'NOTE_DS8': 4978,
}

main.py

import time
import RPi.GPIO as GPIO
from tone import TONE

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)


def beep(channel: int, freq: int, duration: float, *, rising_tone: float = 1):
    """
    播放一個音符
    :param channel: GPIO的數字號,須要和上面的GPIO.setmode(GPIO.BCM)對應
    :param freq: 頻率
    :param duration: 播放時長 
    :param rising_tone: 升降調 0.3 ~ 1.0 ~ 3.0
    :return: 
    """
    if freq <= 0:
        time.sleep(duration)
        return
    pwm = GPIO.PWM(channel, freq * rising_tone) # 輸出該頻率的電平

    try:
        pwm.start(0)
        pwm.ChangeDutyCycle(50)
        if duration > 0:
            time.sleep(duration) # 播放時長
    finally:
        pwm.stop()

def play(channel: int, sheet: list):
    """
    播放簡譜
    簡譜能夠爲以下格式(參照上文的txdx.py):
    - [音符名(string), 持續時間(s)]
    - [頻率(int), 持續時間(s)]
    :param channel: GPIO的數字號,須要和上面的GPIO.setmode(GPIO.BCM)對應
    :param sheet: 簡譜
    :return: 
    """
    GPIO.setup(channel, GPIO.OUT)
    for m in sheet:
        beep(channel, TONE[m[0]] if m[0] in TONE else int(m[0] or 0), m[1])
try:
    from txdx import txdx_sheet
    play(1, txdx_sheet)

finally:
    GPIO.cleanup()
相關文章
相關標籤/搜索