Python 程式實習:從搖桿遙控車學會事件、通訊與安全控制
寫程式不只是讓硬體動起來,而是把使用者操作、資料傳輸、狀態判斷與安全處置串成可靠的系統。本教材以 Joystick:bit 遙控 Q霸小車的五個版本為案例,帶領大三學生由「可動」走向「可維運」。
建議時間:3 小時實作課+1 週小組延伸挑戰
一、學習目標
- 能以 Python 讀取搖桿資料,並透過無線廣播控制雙輪車。
- 能用變數、函式、條件判斷、迴圈與事件處理程式互動。
- 理解 x、y 軸混合為左右馬達速度的差速控制概念。
- 能加入死區、逾時停車、避障與緊急停止等安全機制。
- 能為多人共用場域設計一對一裝置配對與可維護的編號策略。
二、從 V1 到 V5:程式能力如何成長?
| 版本 | 核心功能 | Python 觀念 |
|---|---|---|
| V1 | 搖桿讀值、廣播遙控 | 變數、對應換算、無限迴圈 |
| V2 | 死區、三段速度、斷線停車 | 條件判斷、狀態變數、時間差 |
| V3 | 超音波避障 | 感測資料、優先順序、限制輸出 |
| V4 | C、D、E、F 四鍵操作 | 事件驅動、函式、介面設計 |
| V5 | 一對一配對、蜂鳴器、震動回饋 | 通訊協定、握手、雙向狀態回傳 |
三、第一個關鍵:把搖桿數值變成可用的控制值
Joystick:bit 的 x、y 軸原始值範圍為 0~1023;馬達速度較適合使用 -100~100。先進行範圍對應,再做死區處理,才能避免搖桿已回正、小車卻慢慢滑動的問題。
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
思考題:為什麼死區不能設得太小?又為什麼不能設得太大?請分別從感測器誤差與操控精準度說明。
四、第二個關鍵:差速控制不是左右各寫一個方向
以 y 作為前後速度、x 作為轉向量,左右輪可以用下面兩行程式同時完成前進、後退與轉彎:
leftSpeed = Math.constrain(yValue + xValue, -100, 100)
rightSpeed = Math.constrain(yValue - xValue, -100, 100)
cuteBot.motors(leftSpeed, rightSpeed)
其中 Math.constrain() 是防呆設計:斜向推搖桿時,加總可能超過 100;若不限制,行為會因硬體函式處理方式不同而不穩定。
五、第三個關鍵:安全程式要有優先順序
安全不是在最後補一個 if。小車端應明確定義決策順序:
if emergencyStop:
cuteBot.motors(0, 0)
elif control.millis() - lastControlTime > 500:
cuteBot.motors(0, 0)
elif yValue > 0 and distance > 0 and distance <= 15:
cuteBot.motors(0, 0)
elif yValue > 0 and distance <= 30:
cuteBot.motors(leftSpeed * 0.4, rightSpeed * 0.4)
else:
cuteBot.motors(leftSpeed, rightSpeed)
這是嵌入式系統常見的「安全優先」寫法。程式可讀性比把所有條件塞進一行更重要,因為日後需要維護、測試與除錯。
六、第四個關鍵:多人場域不能共用同一個廣播群組
若兒童館內十支搖桿都使用群組 51,任一孩子推動搖桿都可能讓十台車一起動。V5 的改善方式是以 pairId 建立專屬群組:
pairId = 1 # 第 1 組設備
radio.set_group(100 + pairId) # 使用群組 101
同組搖桿與小車的 pairId 必須一致;第 2 組改為 2,便使用群組 102。再以 pair 與 ack 訊息建立握手確認:
# 搖桿端:提出配對要求
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 必須大寫。
八、實作任務:把 V5 變成可展示的智慧遙控車
- 完成基本搖桿遙控與差速轉彎。
- 加入死區、三段速度與 0.5 秒斷線停車。
- 加入超音波避障,設定停止距離與減速距離。
- 使用 C、D、E、F 建立速度與緊急停止事件。
- 完成一對一配對;兩組設備同時開機,驗證不會互相控制。
- 設計一項自己的狀態回饋,例如配對失敗、低電量或任務完成提示。
九、評量規準
| 面向 | 檢核重點 |
|---|---|
| 功能正確 | 可前後左右控制,速度切換與四鍵功能正常。 |
| 安全設計 | 斷線、障礙物與緊急停止都能安全停車。 |
| 程式品質 | 變數命名清楚、重複程式整理為函式、條件順序合理。 |
| 場域思考 | 兩組以上設備可同時使用且不互相干擾。 |
十、延伸挑戰
將小車設計成兒童館任務車:小朋友先配對自己的車,依顏色指示完成巡遊、避障與停靠任務;系統記錄完成時間與安全停車次數。這會把 Python 從單純語法練習,轉化為可被真實使用者操作、觀察與改進的智慧系統。
沒有留言:
張貼留言