MicroPython 簡化了 micro:bit 的程式開發,讓音樂和機器人控制變得更易上手。藉由內建的 music 模組,可以輕鬆播放內建或自定義的旋律,並控制播放速度和節奏。同時,speech 模組賦予了 micro:bit 語音合成的能力,可調整語音引數,創造更豐富的聲音效果。文章進一步探討如何結合音樂與語音合成,例如讓 micro:bit 唱歌,並提供實作範例。此外,文章也介紹瞭如何使用 MicroPython 控制機器人,包含伺服馬達控制、距離感測和避障功能的程式碼範例,並以 Trundle Bot 和 BeatBoxing 專案為例,展示如何整合硬體與軟體,實作機器人的基本功能和進階應用。最後,文章也討論了更複雜的機器人控制系統設計,例如 Bit:Bot 的控制邏輯,為讀者提供更廣泛的學習方向。

micro:bit上的音樂功能

micro:bit內建了一個簡單易用的音樂模組,可以用來播放不同的音調和旋律。以下是一個簡單的例子:

import music
from microbit import accelerometer

while True:
    music.pitch(accelerometer.get_x(), 20)

內容解密:

  1. 讀取加速度計:這段程式碼讀取micro:bit上的加速度計X軸值,並根據該值產生對應的音調。
  2. 播放音調music.pitch函式用於播放特定的音調,第一個引數是頻率,第二個引數是播放時間。

量化加速度計讀數

為了使輸出的聲音更像音樂,我們可以對加速度計的讀數進行量化處理。以下是一個範例:

import music
from microbit import accelerometer

buckets = [
    262,  # C
    294,  # D
    330,  # E
    392,  # G
    440   # A
]

while True:
    reading = abs(accelerometer.get_x())
    bucket = min(4, max(0, reading // 200))  # 量化
    music.pitch(buckets[bucket], 20)

內容解密:

  1. 定義音階:首先,我們定義了一個包含五個音符的列表,代表一個五聲音階。
  2. 量化讀數:我們將加速度計的絕對值讀數量化到0到4之間的整數,對應於五聲音階中的不同音符。
  3. 播放量化後的音調:根據量化後的索引,我們從buckets列表中選擇對應的頻率,並播放相應的音調。

使用 MicroPython 播放音樂與語音

MicroPython 提供了一個簡易的方式來播放音樂和語音。透過內建的 music 模組,可以輕鬆地播放旋律和控制音樂的播放。

播放內建旋律

MicroPython 的 music 模組包含了一系列內建的旋律,可以直接呼叫這些旋律來播放音樂。例如:

import music
music.play(music.NYAN)

這些內建的旋律包括 BADDYBA_DINGBIRTHDAYBLUES 等多種不同的音樂。

內容解密:

  • music.play() 函式用於播放指定的旋律。
  • music.NYAN 是一個內建的旋律常數,代表特定的音樂旋律。

自定義旋律

除了播放內建旋律外,也可以透過定義自己的旋律來播放。MicroPython 使用一個簡單的音樂 DSL(Domain-Specific Language)來定義旋律。

tune = ["C4:4", "D", "E", "C", "C", "D", "E", "C",
        "E", "F", "G:8", "E:4", "F", "G:8",
        "G:2", "A", "G", "F", "E:4", "C", "G:2", "A", "G", "F", "E:4", "C",
        "C", "G3", "C4:8", "C:4", "G3", "C4:8"]
music.play(tune, wait=False, loop=True)

內容解密:

  • tune 是一個列表,包含了按照特定格式定義的音符。
  • 每個音符的格式為 NOTE_NAME[octave][:duration],例如 "C4:4" 表示在第四八度音階的 C 音符,持續 4 個節拍單位。
  • music.play() 函式播放自定義的旋律,可以透過 wait=False 使播放非同步進行,透過 loop=True 使旋律迴圈播放。

控制音樂播放

MicroPython 提供了多種方法來控制音樂的播放,包括改變節奏、停止播放等。

music.set_tempo(bpm=180)  # 設定節奏為每分鐘 180 拍
music.stop()  # 停止音樂播放

內容解密:

  • music.set_tempo(bpm=180) 設定音樂的節奏為每分鐘 180 拍。
  • music.stop() 用於停止當前的音樂播放。

語音合成

MicroPython 也提供了語音合成的功能,可以讓裝置發出語音。

import speech
speech.say("Hello, World!", speed=120, pitch=100, throat=100, mouth=200)

內容解密:

  • speech.say() 函式用於讓裝置發出語音。
  • 可以透過引數調整語音的特性,如速度、音調、喉音和口型等。

語音合成技術與音樂的結合

語音合成技術是一種能夠將文字轉換成聲音的技術,而當這項技術與音樂結合時,便能創造出令人驚豔的效果。在 MicroPython 中,我們可以利用語音合成模組來產生語音,甚至可以讓 micro:bit 唱歌。

語音合成的基礎

在語音合成中,聲音的基本單位是音素(phonemes)。音素可以分為兩大類別:母音和子音。母音又可以進一步分為單純母音和雙母音。子音則分為有聲子音和無聲子音。

有聲子音與無聲子音

有聲子音需要使用聲帶來產生聲音,例如 “L”、“N” 和 “Z”。無聲子音則是透過氣流來產生聲音,例如 “P”、“T” 和 “SH”。

# 有聲子音範例
voiced_consonants = ["R", "D", "L", "G", "W", "J", "M", "N", "B", "V", "DH", "Z", "ZH"]
# 無聲子音範例
unvoiced_consonants = ["S", "SH", "F", "TH", "P", "T", "K", "CH", "H"]

特殊音素

除了基本的有聲和無聲子音外,還有一些特殊的音素,例如表示發音的變化或特殊的發音方式。

# 特殊音素範例
special_phonemes = ["UL", "UM", "UN", "Q"]

使用語音合成模組

在 MicroPython 中,可以使用 speech 模組來進行語音合成。首先,需要將文字轉換成音素,然後才能使用 pronounce 函式來發音。

import speech

# 將文字轉換成音素
phonemes = speech.translate("Hello")
# 發音
speech.pronounce(phonemes)

新增重音

為了使語音聽起來更自然,可以新增重音。重音是透過在母音後面新增數字來實作的,不同的數字代表不同的重音型別。

# 新增重音範例
stress_example = "/HEH3LOW"
speech.pronounce(stress_example)

語音合成與音樂的結合

要讓 micro:bit 唱歌,可以使用 sing 函式,並在音素前新增註解來指定音高。

import speech

# 定義歌曲的音符
solfa = [
    "#115DOWWWWWW",  # Doh
    "#103REYYYYYY",  # Re
    "#94MIYYYYYY",   # Mi
    "#88FAOAOAOAOR", # Fa
    "#78SOHWWWWW",   # Soh
    "#70LAOAOAOAOR", # La
    "#62TIYYYYYY",   # Ti
    "#58DOWWWWWW"    # Doh
]

# 將音符串接成一首歌
song = ''.join(solfa)
# 唱歌
speech.sing(song, speed=100)

實作範例:讓 micro:bit 唱一首歌

以下是完整的範例程式碼,展示如何讓 micro:bit 唱一首歌。

import speech

# 定義歌曲的每一行
line1 = [
    '#26DEYYYYYYYYY',
    '#31ZIYIYIYIYIYIYIY',
    '#39DEYYYYYYYYY',
    '#52ZIYIYIYIYIYIYIY',
    '#46GIXV',
    '#42MIYIY',
    '#39YAOW',
    '#46AEAEAEN',
    '#39SERER',
    '#52DUXUXUXUXUXUXUXUXUXUXUXUX'
]

line2 = [
    '#35AYYYYYYMM',
    '#26/HAEAEAEAEAEAEF',
    '#31KREYYYYYYY',
    '#39ZIYIYIYIYIYIYIY',
    '#46AXLL',
    '#42FAOR',
    '#39DHER',
    '#35LUHUHUHV',
    '#31AXAXV',
    '#35YUXUXUXUXUXUXUXUXUXUX'
]

line3 = [
    '#31IHT',
    '#29WOWNT',
    '#31BIY',
    '#35ER',
    '#26STAYYYYY',
    '#31LIHSH',
    '#35MAE',
    '#39RIXIXIXIXIXIXIXIXIXIXIXIXIXJ',
    '#35AYY',
    '#31KAEAEAEAENT',
    '#39ER',
    '#46FAOAOAORD',
    '#39ER',
    '#46KAA',
    '#52RIXIXIXIXIXIXIXIXIXIXIXIXIXJ'
]

line4 = [
    '#52BUHT',
    '#39YUXUXL',
    '#31LUXK',
    '#35SWIYIYIYIYT',
    '#52ER',
    '#39PAAAAAAN',
    '#31ER',
    '#35SIYIYIYT',
    '#31UHV',
    '#29ER',
    '#26BAY',
    '#31SIH',
    '#39KUXL',
    '#35MEYYYYD',
    '#52FER',
    '#39TUXUXUXUXUXUXUXUXUXUXUX'
]

# 唱每一行
speech.sing(''.join(line1))
speech.sing(''.join(line2))
speech.sing(''.join(line3))
speech.sing(''.join(line4))

內容解密:

此程式碼展示瞭如何使用 MicroPython 的 speech 模組來讓 micro:bit 唱一首歌。首先定義了歌曲的每一行,每一行都是由多個音符組成,每個音符都指定了音高和發音。然後使用 sing 函式將每一行唱出來。這種技術可以應用於各種創意專案中,例如製作互動式音樂作品或有聲書等。透過調整音符和節奏,可以創造出豐富多樣的音樂效果。

使用 MicroPython 控制機器人

機器人技術因其教育用途而日益普及,許多開發者利用 micro:bit 創造出有趣的機器人專案。本章將探討兩個使用 MicroPython 的機器人專案,展示如何利用 micro:bit 實作簡單的機器人控制。

Trundle Bot 專案

Trundle Bot 是一個簡單的輪式機器人,配備類別比距離感測器,能夠檢測前方障礙物並自動避開。它使用兩個連續旋轉伺服馬達驅動,具有簡單的程式碼和硬體結構。

硬體需求

  • micro:bit 主機板
  • 2 個 9g 連續旋轉伺服馬達
  • Pololu Carrier with Sharp GP2Y0A60SZLF 類別比距離感測器(3V)
  • 2 個輪子
  • Pololu caster ball
  • 可攜式電源(3.3V 至 4.2V)

程式碼解析

from microbit import pin0, pin1, pin2

# 設定伺服馬達控制腳位
left_servo = pin0
right_servo = pin1

# 設定距離感測器腳位
distance_sensor = pin2

def forward():
    # 控制伺服馬達向前移動
    left_servo.write_analog(180)
    right_servo.write_analog(0)

def stop():
    # 停止伺服馬達
    left_servo.write_analog(90)
    right_servo.write_analog(90)

def turn_left():
    # 向左轉
    left_servo.write_analog(0)
    right_servo.write_analog(0)

def turn_right():
    # 向右轉
    left_servo.write_analog(180)
    right_servo.write_analog(180)

while True:
    distance = distance_sensor.read_analog()
    if distance < 200:  # 若偵測到障礙物
        stop()
        turn_left()  # 向左轉
    else:
        forward()  # 向前移動

內容解密:

  1. forward() 函式:控制兩個伺服馬達以相反方向旋轉,使機器人向前移動。
  2. stop() 函式:將伺服馬達的控制訊號設為中間值,使其停止。
  3. turn_left()turn_right() 函式:控制伺服馬達以相同方向旋轉,使機器人向左或向右轉。
  4. 距離感測器讀取:透過 distance_sensor.read_analog() 讀取距離值,若小於閾值則執行避障動作。

BeatBoxing micro:bit 專案

另一個有趣的專案是使用 micro:bit 製作節奏口技(beatboxing)效果。透過 speech 模組,可以讓 micro:bit 發出類別似口技的聲音,並透過按鈕切換不同的節奏模式。

程式碼範例

import speech
from microbit import sleep, button_a, button_b, display, Image

# 定義口技聲音
bass_drum = "BUH"
snare = "CHIXIX"
roll = "DGDG"
rest = ""

def beat_box(sound):
    if sound:
        display.show(Image.HEART)
        speech.pronounce(sound)
    else:
        sleep(220)

beats1 = [bass_drum, rest, rest, rest, snare, rest, rest, rest]
beats2 = [bass_drum, snare, snare, snare, bass_drum, snare, roll, roll]

def play(beats):
    for beat in beats:
        beat_box(beat)

selected = beats1

while True:
    if button_a.was_pressed():
        selected = beats1
    elif button_b.was_pressed():
        selected = beats2
    play(selected)

內容解密:

  1. beat_box(sound) 函式:根據輸入的聲音引數,使用 speech.pronounce() 發出聲音,若無聲音則暫停一段時間。
  2. play(beats) 函式:播放指定的節奏序列。
  3. 按鈕控制:透過按鈕 A 和 B 切換不同的節奏模式。

這些範例展示瞭如何利用 MicroPython 控制機器人和創作有趣的音效,為學習者和開發者提供了豐富的創作可能性。

微位元機器人控制系統設計與實作

伺服馬達控制類別實作

微位元機器人的運動控制核心在於伺服馬達的管理,而這部分的功能被封裝在一個名為 Servo 的類別中:

import microbit

class Servo:
    def __init__(self, pin, trim=0):
        self.pin = pin
        self.trim = trim
        self.speed = 0
        self.pin.set_analog_period(20)

    def set_speed(self, speed):
        self.pin.write_analog(int(25 + 100 * (90 + speed) / 180 + self.trim))
        self.speed = speed

內容解密:

  1. 初始化引數:建構函式接受兩個引數:pin(伺服馬達連線的實體針腳)和 trim(微調引數,用於補償伺服馬達的效能差異)。
  2. PWM 設定:透過 set_analog_period(20) 設定 PWM 訊號的週期為 20 毫秒,這是伺服馬達控制的標準組態。
  3. 速度控制set_speed 方法根據輸入的速度值計算對應的類別比輸出,並寫入指定的針腳,從而控制伺服馬達的轉速。

機器人類設計

機器人的整體控制由 Robot 類別負責整合各個元件:

class Robot:
    def __init__(self):
        # 記得檢查微調值
        self.left_servo = Servo(microbit.pin0, 2)
        self.right_servo = Servo(microbit.pin1, 1)

    def go(self, distance):
        microbit.display.show(microbit.Image.ARROW_S)
        self.left_servo.set_speed(-90)
        self.right_servo.set_speed(90)
        microbit.sleep(int(distance * 2000 / 17))
        self.stop()

    def turn(self, angle):
        if angle > 0:
            microbit.display.show(microbit.Image.ARROW_E)
            self.left_servo.set_speed(-90)
            self.right_servo.set_speed(-90)
            microbit.sleep(int(angle * 64 / 9))
        else:
            microbit.display.show(microbit.Image.ARROW_W)
            self.left_servo.set_speed(90)
            self.right_servo.set_speed(90)
            microbit.sleep(int(-angle * 64 / 9))
        self.stop()

    def stop(self):
        microbit.display.show(microbit.Image.DIAMOND)
        self.left_servo.set_speed(0)
        self.right_servo.set_speed(0)

    def get_distance(self):
        return microbit.pin2.read_analog()

內容解密:

  1. 初始化:建立兩個 Servo 例項來控制左右伺服馬達,並可根據需要調整 trim 值以修正行進方向。
  2. 運動控制go 方法控制機器人前進指定距離;turn 方法根據給定的角度轉彎;stop 方法停止馬達運轉。
  3. 距離感測get_distance 方法讀取連線在針腳 2 的距離感測器的類別比值,用於檢測障礙物距離。

簡易自主避障實作

透過簡單的事件迴圈,機器人能夠自主移動並避開障礙物:

robot = Robot()
while True:
    robot.go(5)
    if robot.get_distance() > 700:
        robot.turn(20)
        left_distance = robot.get_distance()
        robot.turn(-40)
        right_distance = robot.get_distance()
        robot.turn(20)
        if left_distance < right_distance:
            robot.turn(60)
        else:
            robot.turn(-60)

內容解密:

  1. 基本邏輯:機器人持續前進,當檢測到前方障礙物太近時(距離值大於 700),會暫停並進行左右探測。
  2. 路徑選擇:比較左右兩側的距離感測值,選擇距離較大的方向進行轉向,以避開障礙物。

Bit:Bot 高階機器人控制

對於像 Bit:Bot 這樣的高階機器人套件,控制邏輯會更加複雜,需要處理更多的感測器輸入和輸出控制,例如 NeoPixels、蜂鳴器和線跟隨感測器等。