玩學機內建了一個蜂鳴器(Buzzer),這堂課我們將要用這個發聲裝置來做一些有趣的應用。課程開始之前,我們先來了解蜂鳴器的構造與發聲原理。
蜂鳴器(Buzzer)是一種常見的聲音輸出設備,通常用於在嵌入式系統、電子設備和電子專案中產生聲音或音效。蜂鳴器通過振動產生聲音,發聲原理如下:
微控制器非常擅長在其GPIO引腳上生成數位輸出。這些數位信號可在零電壓和正電壓(如3.3伏或5伏)之間快速切換。但它們並非設計用來創建連續變化電壓的“類比”輸出。不過,我們可用一種稱為「脈衝寬度調製(Pulse Width Modulation)」的技術來只用數位輸出來模擬各種聲音頻率。
脈寬調製不是改變電信號的高度,而是改變數位信號脈衝之間的寬度的過程。通過改變數位信號之間的距離,我們可以生成一個聽起來像具有更高或更低頻率或音調的信號。
MicroPython提供了一個強大的函式庫,叫做 PWM,讓您輕鬆生成不同形狀的訊號。
工作週期(Duty Cycle) 是指脈衝高時的時間百分比。
我們先用積木程式來教大家如何讓玩學機發出聲音。
因此,我們聲音類的程式,都會使用文字程式來編寫。
PWM 是一種波形產生器,Pin#25 是接到 WiFiBoy 蜂鳴器的 IO 輸出線路。設定聲音發出頻率440Hz,鋼琴中間的La (A) 通常是440 Hz。每高八度音,頻率就增加一倍,高八度的 La 就是 880Hz,低八度的 La 就是 220Hz。 snd.duty(100) 設定聲音能量強度為 100 ,也就是把蜂鳴器聲音開到最大。snd.duty(0),就是把聲音關掉。音樂撥放完畢後,要記得要用 snd.deinit() 關閉 PWM 物件。
from machine import Pin, PWM
from utime import sleep
snd_PIN = Pin(17, 2).value(1) # 啟動聲音輸出腳位
snd = PWM(Pin(25, 2)) # 建立在 25腳位的 PWM 物件
snd.duty(0)
def play(f, t):
snd.freq(f) # 設定撥放的聲音頻率
snd.duty(50) # 設定工作週期為 50%
time.sleep(t) # 暫停 t 秒
snd.duty(0) # 關閉工作週期
play(880, 0.2)
play(440, 0.2)
play(220, 0.2)
snd.deinit()
from machine import Pin, PWM
from utime import sleep
# 設定
snd_PIN = Pin(17,2).value(1)
snd = PWM(Pin(25,2))
ON_TIME = .25
OFF_TIME = .1
def play(freq, t):
snd.duty(50)
snd.freq(freq)
sleep(t)
snd.duty(0)
# 演奏音階
freq = 30
for i in range(64):
print(freq)
play(freq, 0.2)
freq = int(freq * 1.15)
snd.deinit() # 關閉 PWM
我們參考英文維基百科條目「Scientific_pitch_notation」,讓學員可以從這張對照表快速知道 88 鍵的鋼琴,每個琴鍵對應的頻率值,這樣我們未來編寫程式時,才不用背一大堆數字。
如果您要更進一步認識「音階標準頻率」的相關知識,可以參考「https://www.youtube.com/watch?v=czGQiTHaffM」這個教學影片,專文「震動噪音科普專欄_音階標準頻率」介紹連結在「http://aitanvh.blogspot.com/2018/03/blog-post_19.html」。
有了這兩張表,我們再來看內建的 toneng 聲音引擎文件就會比較容易看懂。
請輸入 help(toneng),您會看到底下的輸出結果。
>>> help(toneng)
object <module 'toneng' from 'toneng.py'> is of type module
__file__ -- toneng.py
__name__ -- toneng
freqlist -- [110, 117, 123, 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247, 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951, 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902, 8372, 8870, 9397, 9956, 10548, 11175, 11840, 12544, 13290, 14080, 14917, 15804, 16744]
counter -- 0
play -- <function play at 0x3ffe6290>
playing -- 0
ndutyd -- 5
_tempo -- 80
initduty -- 100
tempo -- <function tempo at 0x3ffe62a0>
machine -- <module 'umachine'>
_snd -- PWM(Pin(25), freq=880, duty=0, resolution=16, (duty=0.00%, resolution=0.002%), mode=0, channel=0, timer=0)
_ps --
nduty -- -300
octave -- 3
ps -- <function ps at 0x3ffe62b0>
tone -- Timer(3ffe61b0; alarm_en=1, auto_reload=1, counter_en=1)
toneEngine -- <function toneEngine at 0x3ffe62c0>
import toneng # 匯入 toneng 音效引擎
# 輸入小蜜蜂簡譜
ps = "GEE2FDD2CDEFGGG2GEE2FDD2CEGGC1DDDDDEF2EEEEEFG2GEE2FDD2CEGGC1" # 小蜜蜂
toneng._ps = ps # 送入 toneng._ps 執行
謝謝各位讀者還能堅持到現在,明日我們要來介紹「使用超音波感測器作測距儀」。