2026年9月3日 星期四

Python 程式實習:從搖桿遙控車學會事件、通訊與安全控制

Python 程式實習:從搖桿遙控車學會事件、通訊與安全控制

寫程式不只是讓硬體動起來,而是把使用者操作、資料傳輸、狀態判斷與安全處置串成可靠的系統。本教材以 Joystick:bit 遙控 Q霸小車的五個版本為案例,帶領大三學生由「可動」走向「可維運」。

適用課程:Python 程式實習、物聯網與智慧生活、嵌入式系統入門
建議時間:3 小時實作課+1 週小組延伸挑戰

一、學習目標

  1. 能以 Python 讀取搖桿資料,並透過無線廣播控制雙輪車。
  2. 能用變數、函式、條件判斷、迴圈與事件處理程式互動。
  3. 理解 x、y 軸混合為左右馬達速度的差速控制概念。
  4. 能加入死區、逾時停車、避障與緊急停止等安全機制。
  5. 能為多人共用場域設計一對一裝置配對與可維護的編號策略。

二、從 V1 到 V5:程式能力如何成長?

版本核心功能Python 觀念
V1搖桿讀值、廣播遙控變數、對應換算、無限迴圈
V2死區、三段速度、斷線停車條件判斷、狀態變數、時間差
V3超音波避障感測資料、優先順序、限制輸出
V4C、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。再以 pairack 訊息建立握手確認:

# 搖桿端:提出配對要求
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,其中 VM 必須大寫。

八、實作任務:把 V5 變成可展示的智慧遙控車

  1. 完成基本搖桿遙控與差速轉彎。
  2. 加入死區、三段速度與 0.5 秒斷線停車。
  3. 加入超音波避障,設定停止距離與減速距離。
  4. 使用 C、D、E、F 建立速度與緊急停止事件。
  5. 完成一對一配對;兩組設備同時開機,驗證不會互相控制。
  6. 設計一項自己的狀態回饋,例如配對失敗、低電量或任務完成提示。

九、評量規準

面向檢核重點
功能正確可前後左右控制,速度切換與四鍵功能正常。
安全設計斷線、障礙物與緊急停止都能安全停車。
程式品質變數命名清楚、重複程式整理為函式、條件順序合理。
場域思考兩組以上設備可同時使用且不互相干擾。

十、延伸挑戰

將小車設計成兒童館任務車:小朋友先配對自己的車,依顏色指示完成巡遊、避障與停靠任務;系統記錄完成時間與安全停車次數。這會把 Python 從單純語法練習,轉化為可被真實使用者操作、觀察與改進的智慧系統。

延伸閱讀:本教材的五篇實作基礎

沒有留言:

張貼留言