from microbit import *
while True:
if button_a.was_pressed():
display.show('A')
if button_b.was_pressed():
display.show('B')
while True: 表示「永遠重複」。程式不是一直盯著按鍵不放,而是持續檢查是否發生「按過一次」的事件。
五、範例 3:搖一搖,顯示隨機點數
from microbit import *
from random import randint
while True:
if accelerometer.was_gesture('shake'):
number = randint(1, 6)
display.show(str(number))
sleep(800)
這個例子同時練習:感測器、條件判斷、變數、隨機數與字串轉換。
六、範例 4:溫度計與序列主控台
from microbit import *
while True:
celsius = temperature()
display.scroll(str(celsius) + 'C')
print(celsius)
sleep(2000)
from microbit import *
import radio
radio.on()
radio.config(group=23)
while True:
if button_a.was_pressed():
radio.send('Hello')
display.show(Image.HAPPY)
message = radio.receive()
if message:
display.scroll(message)
重點:兩片 micro:bit 的 group 必須相同,才像在同一個無線頻道。請改成不同組別測試,觀察訊息是否還能收到。
八、從 MakeCode Python 搬家時,不能直接複製的地方
MakeCode Python
micro:bit MicroPython
basic.show_number(51)
display.show('5') 或 display.scroll('51')
basic.forever(...)
while True:
radio.send_value()
radio.send()、radio.receive()
兩者都是 Python,但 API 不同。若要控制 CuteBot、Joystick:bit 等擴充硬體,必須使用廠商提供、可在 MicroPython 使用的模組;MakeCode 的擴充功能不能直接複製過來。
九、課堂任務:微型智慧環境站
顯示目前溫度;當溫度高於自訂門檻時顯示警示圖案。
按 A 顯示目前溫度,按 B 顯示光線值。
每 5 秒用 Radio 傳送一行格式化資料,例如 T=28,L=120。
另一片 micro:bit 收到資料後顯示圖示,並在序列主控台列印收到的原始訊息。
十、學習檢核
我能說明 from microbit import * 的用途。
我能用 while True 撰寫持續運作的程式。
我能用序列主控台檢查 print() 輸出的資料。
我能設定兩片 micro:bit 使用相同的 Radio 群組並互相傳訊息。
我知道 MakeCode Python 與 MicroPython 的語法相似,但 API 不可直接混用。
x = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.X),
0, 1023, -100, 100)
y = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.Y),
0, 1023, -100, 100)
if x >= -10 and x <= 10:
x = 0
if y >= -10 and y <= 10:
y = 0
# 搖桿端:提出配對要求
radio.send_value("pair", pairId)
# 小車端:確認同一組後回覆
if name == "pair" and value == pairId:
paired = True
radio.send_value("ack", pairId)
七、第五個關鍵:回饋讓系統真正可用
無線系統不能只「送出去」。V5 讓小車將狀態回傳給搖桿,並以蜂鳴器與震動告訴使用者目前情況:
配對成功:短音+震動一次。
慢、中、快:分別以 1、2、3 次提示確認。
前方接近障礙物:提示減速;距離過近:連續提示並停止。
F 緊急停止:低音與震動,直到按 C、D、E 之一才解除。
def feedback(times, tone):
for index in range(times):
music.play_tone(tone, music.beat(BeatFraction.SIXTEENTH))
joystickbit.Vibration_Motor(80)
basic.pause(60)
除錯提醒:Joystick:bit 的震動函式名稱為 Vibration_Motor,其中 V 與 M 必須大寫。
x = 0
y = 0
speed = 70
radio.set_group(51)
basic.show_number(2) # 開機預設為一般速度
def on_button_pressed_a():
global speed
speed = 40
basic.show_number(1) # 慢速
input.on_button_pressed(Button.A, on_button_pressed_a)
def on_button_pressed_b():
global speed
speed = 70
basic.show_number(2) # 一般速度
input.on_button_pressed(Button.B, on_button_pressed_b)
def on_button_pressed_ab():
global speed
speed = 100
basic.show_number(3) # 快速
input.on_button_pressed(Button.AB, on_button_pressed_ab)
def on_forever():
global x, y
x = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.X),
0, 1023, -100, 100)
y = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.Y),
0, 1023, -100, 100)
# 搖桿死區:回到中央時停止
if x >= -10 and x <= 10:
x = 0
if y >= -10 and y <= 10:
y = 0
# 依速度模式縮放輸出值
x = x * speed / 100
y = y * speed / 100
radio.send_value("x", x)
radio.send_value("y", y)
basic.pause(50)
basic.forever(on_forever)
(二)Q霸小車端:V3 超音波安全避障
xValue = 0
yValue = 0
lastReceiveTime = -1000
distance = 0
radio.set_group(51)
basic.show_number(51)
cuteBot.motors(0, 0)
def on_received_value(name, value):
global xValue, yValue, lastReceiveTime
if name == "x":
xValue = value
elif name == "y":
yValue = value
lastReceiveTime = control.millis()
radio.on_received_value(on_received_value)
def on_forever():
global distance
# 優先保護 1:逾 0.5 秒未收到訊號,立即停車
if control.millis() - lastReceiveTime > 500:
cuteBot.motors(0, 0)
else:
distance = cuteBot.ultrasonic(cuteBot.SonarUnit.Centimeters)
leftSpeed = Math.constrain(yValue + xValue, -100, 100)
rightSpeed = Math.constrain(yValue - xValue, -100, 100)
# 優先保護 2:僅在向前時啟用前方避障
if yValue > 0 and distance > 0 and distance <= 15:
cuteBot.motors(0, 0)
basic.show_icon(IconNames.NO)
elif yValue > 0 and distance > 15 and distance <= 30:
cuteBot.motors(leftSpeed * 0.4, rightSpeed * 0.4)
basic.show_icon(IconNames.SMALL_DIAMOND)
else:
cuteBot.motors(leftSpeed, rightSpeed)
basic.clear_screen()
basic.pause(30)
basic.forever(on_forever)
x = 0
y = 0
speed = 70
radio.set_group(51)
basic.show_number(2) # 開機預設為一般速度
def on_button_pressed_a():
global speed
speed = 40
basic.show_number(1) # 慢速
input.on_button_pressed(Button.A, on_button_pressed_a)
def on_button_pressed_b():
global speed
speed = 70
basic.show_number(2) # 一般速度
input.on_button_pressed(Button.B, on_button_pressed_b)
def on_button_pressed_ab():
global speed
speed = 100
basic.show_number(3) # 快速
input.on_button_pressed(Button.AB, on_button_pressed_ab)
def on_forever():
global x, y
x = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.X),
0, 1023, -100, 100)
y = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.Y),
0, 1023, -100, 100)
# 搖桿死區:回到中央時停止
if x >= -10 and x <= 10:
x = 0
if y >= -10 and y <= 10:
y = 0
# 依速度模式縮放輸出值
x = x * speed / 100
y = y * speed / 100
radio.send_value("x", x)
radio.send_value("y", y)
basic.pause(50)
basic.forever(on_forever)
(二)Q霸小車端:V3 超音波安全避障
xValue = 0
yValue = 0
lastReceiveTime = -1000
distance = 0
radio.set_group(51)
basic.show_number(51)
cuteBot.motors(0, 0)
def on_received_value(name, value):
global xValue, yValue, lastReceiveTime
if name == "x":
xValue = value
elif name == "y":
yValue = value
lastReceiveTime = control.millis()
radio.on_received_value(on_received_value)
def on_forever():
global distance
# 優先保護 1:逾 0.5 秒未收到訊號,立即停車
if control.millis() - lastReceiveTime > 500:
cuteBot.motors(0, 0)
else:
distance = cuteBot.ultrasonic(cuteBot.SonarUnit.Centimeters)
leftSpeed = Math.constrain(yValue + xValue, -100, 100)
rightSpeed = Math.constrain(yValue - xValue, -100, 100)
# 優先保護 2:僅在向前時啟用前方避障
if yValue > 0 and distance > 0 and distance <= 15:
cuteBot.motors(0, 0)
basic.show_icon(IconNames.NO)
elif yValue > 0 and distance > 15 and distance <= 30:
cuteBot.motors(leftSpeed * 0.4, rightSpeed * 0.4)
basic.show_icon(IconNames.SMALL_DIAMOND)
else:
cuteBot.motors(leftSpeed, rightSpeed)
basic.clear_screen()
basic.pause(30)
basic.forever(on_forever)
x = 0
y = 0
speed = 70
radio.set_group(51)
basic.show_number(2) # 開機預設為一般速度
def on_button_pressed_a():
global speed
speed = 40
basic.show_number(1) # 慢速
input.on_button_pressed(Button.A, on_button_pressed_a)
def on_button_pressed_b():
global speed
speed = 70
basic.show_number(2) # 一般速度
input.on_button_pressed(Button.B, on_button_pressed_b)
def on_button_pressed_ab():
global speed
speed = 100
basic.show_number(3) # 快速
input.on_button_pressed(Button.AB, on_button_pressed_ab)
def on_forever():
global x, y
x = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.X),
0, 1023, -100, 100)
y = Math.map(joystickbit.get_rocker_value(joystickbit.rockerType.Y),
0, 1023, -100, 100)
# 搖桿死區:回到中央時停止
if x >= -10 and x <= 10:
x = 0
if y >= -10 and y <= 10:
y = 0
# 依速度模式縮放輸出值
x = x * speed / 100
y = y * speed / 100
radio.send_value("x", x)
radio.send_value("y", y)
basic.pause(50)
basic.forever(on_forever)