micro:bit數字鋼琴

之前用水果和micro:bit連接,做了一個水果鋼琴,還滿多人喜歡,覺得有趣。水果鋼琴很有趣,但是不太靈敏,尤其是碰觸到水果後要馬上放手才會發出聲音,和我們直覺的用法不太一樣。今天就用電腦的序列埠和micro:bit連接(電腦如何和micro:bit連接,請參閱我之前的文章,序列埠和micro:bit溝通),用電腦鍵盤的數字按鍵來讓micro:bit發出聲音,希望做一個比較靈敏的數字鋼琴。因為我的電腦沒有藍芽,所以,我一直都是用序列埠來控制micro:bit。

用序列埠利用鍵盤的數字讓micro:bit成為鋼琴

電腦要和com port溝通,並且寫程式控制要傳送給micro:bit的訊息,首先要先安裝python,在這裡我用的python版本是3.5的版本,並且要安裝pynput及pyserial這兩個package。pynput是用來偵測鍵盤行為的套件;pyserial則是python用來和序列埠的裝置溝通的套件。以下為安裝套件指令

  • pip install pynput
  • pip install pyserial

安裝完後,請將以下程式放在某個資料夾,程式的檔名叫做key.py。請注意以下註解的地方,尤其是com port,請依照自己的電腦和micro:bit連接的com port自行修改。

from pynput import keyboard
import serial

#以下的com port請自行修改電腦和micro:bit連接的port
#第二個參數是micro:bit預設的bound rate,是115200,請不要修改,以免無法連結
ser = serial.Serial('COM23', 115200, timeout=1)

myChar=''
print('數字鋼琴程式執行中,按ESC便會結束程式......')


#以下是偵測鍵盤按鍵是否被按下的程序
def on_key_press(key):
    global myChar
    #偵測到如果按下ESC鍵,則程式結束
    if key==keyboard.Key.esc:
       ser.close()
       return False
    else:
       if hasattr(key, 'char'):
          if key.char!=myChar and str.isdigit(key.char):
             myChar=key.char
             print('%s按下' % key)
             ser.write((myChar+'\n').encode())


#以下是偵測鍵盤按鍵是否被放開的程序
def on_key_release(key):
    global myChar
    if hasattr(key, 'char'):
       if str.isdigit(key.char) and key.char==myChar:
          myChar=''
          print('%s放開' % key)
          ser.write('c\n'.encode())

with keyboard.Listener(on_press = on_key_press,on_release = on_key_release) as listener:
    listener.join()  

程式放好之後,執行以下的指令以啟動python程式

  • py key.py

上面的程式我已經把不能按到的鍵盤應該都用程式避開了,也就是鍵盤只用0~9的數字會被接受,並傳送到micro:bit去發出聲音,至於要結束這支python只要按ESC鍵就會結束了。

按下數字鍵盤即可播放聲音,放開則停止播放,micro:bit也會顯示按下的數字

使用KSB035的擴充板,因為單純只是要使用蜂鳴器,且已接上電腦,可以不用上電池,蜂鳴器也會響

在micro:bit端的程式如下圖示:

如果上面的圖片懶得自己拉積木,就請到makecode裡,進入JavaScript頁面,將以下的程式碼輸入,應該會節省很多拉積木的時間:

let tone = ""
serial.onDataReceived(serial.delimiters(Delimiters.NewLine), () => {
    tone = serial.readUntil(serial.delimiters(Delimiters.NewLine))
    if (tone == "c") {
        pins.digitalWritePin(DigitalPin.P0, 0)
        basic.clearScreen()
    } else {
        basic.showString(tone)
        if (tone == "1") {
            music.ringTone(262)
        } else if (tone == "2") {
            music.ringTone(294)
        } else if (tone == "3") {
            music.ringTone(330)
        } else if (tone == "4") {
            music.ringTone(349)
        } else if (tone == "5") {
            music.ringTone(392)
        } else if (tone == "6") {
            music.ringTone(440)
        } else if (tone == "7") {
            music.ringTone(494)
        } else if (tone == "8") {
            music.ringTone(523)
        } else if (tone == "9") {
            music.ringTone(587)
        } else if (tone == "0") {
            music.ringTone(659)
        }
    }
})

2017/12/2發表於FB

https://www.facebook.com/permalink.php?story_fbid=1510273635674861&id=100000767174283