MBC 掌控者 PS2/PS4 × 樂高官方 SPIKE App(Python)

三個步驟用官方 SPIKE App 的 Python 讀掌控者

樂高官方 SPIKE App(教育版)也能寫 Python,不用換主機韌體。掌控者接收器在 App 裡是一顆顏色感應器,App 不能匯入自己的檔案,所以照這個順序寫:先把讀值小幫手貼在最上面,再建立物件、幫接收器取名字,最後每圈 update() 一次、用名字呼叫功能。PS2 和 PS4 接收器的寫法完全一樣。左邊一步一步做,右邊的程式會跟著長出來;在模擬手把上點按鍵、拖搖桿,就能看到程式會印出什麼。

1

貼上讀值小幫手

官方 App 的 Python 專案只有一個檔案,不能匯入自己的 .py,所以把「讀值小幫手」整段貼在程式最上面(小幫手開頭也寫了:照抄就好、不用改)。沒有它,後面寫的 GamepadApp 主機看不懂,會出現 NameError。

  1. 打開樂高官方 SPIKE App(教育版,SPIKE Prime 黃色主機),新增專案,選「Python」。
  2. 把右邊標 ① 的程式貼到最上面(小幫手只露第一行,按「顯示小幫手」看全部;「複製程式」一定是完整的)。小幫手也可以單獨下載:MBC_gamepad_App_helper.py(用記事本打開、全選複製)。
  3. 接收器插主機 A~F 任一孔,由主機供電;接收器要是 SPIKE 版韌體。PS2、PS4 接收器寫法一樣(小幫手也放在 PS4 的下載資料夾:PS4 版下載,內容相同),模擬手把下面可以切換 PS2/PS4。

小幫手幫你把官方 App 讀到的數字拆好(跟官方 App 積木頁同一套換算):

官方 App 讀到的裝的是小幫手的功能
color_sensor.reflection()(反射光)方向鍵+圖形鍵:上 1、右 2、下 4、左 8、△ 16、○ 32、✕ 64、□ 128,同時按就相加pressed('UP')…、buttons() 的低 8 位元
color_sensor.color()(顏色)肩鍵+功能鍵:L2 1、R2 2、L1 4、R1 8、SELECT(PS4:SHARE)16、L3 32、R3 64、START(PS4:OPTIONS)−128pressed('L1')…、buttons() 的高 8 位元
color_sensor.rgbi() 第 1 個(原始紅)左搖桿 X×10+Y(各 1 ~ 9,放開 55)stick('LX')(÷ 10 取整數)、stick('LY')(÷ 10 的餘數)
rgbi() 第 2 個(原始綠)右搖桿 X×10+Ystick('RX'), stick('RY')
rgbi() 第 3 個(原始藍)16 個鍵的另一種排法(PSX)不用(跟官方 App 積木頁一樣,見下面「讀不到的值」)
2

建立物件:幫感應器取名字

一台車可能接好幾個感應器,所以要「建立一個物件」:告訴小幫手接收器接在哪個孔(port.C 來自 from hub import port),並幫它取個名字。之後每次讀值都叫這個名字。

接收器接在哪個孔?
3

每圈 update(),再使用功能

官方 App 的程式放在 async def main(): 裡,最後 runloop.run(main()) 讓它開始跑;等待用 await runloop.sleep_ms(100)(不是 Pybricks 的 wait())。每圈先 .update() 讀一次,再用「名字+小數點+功能」。點一個功能,程式和輸出會換成它的範例。

模擬手把:點按鍵、拖動搖桿,看右邊的輸出怎麼變

模擬畫面是示意:點一下按鍵=按住,再點一下放開;拖動搖桿的圓點改變位置(放開滑鼠會停在那裡,按「全部放開」回到中間)。搖桿 1 ~ 9、5 = 中間,往右、往上數字變大。PS4 手把的電量固定示意為 80。

每個功能的範例

每個功能都有一段可以直接放進 main() 的範例(孔 C)。按「試試看」會切到第 3 步,右邊的程式和輸出會換成這個範例。

完整範例

按「複製」拿到完整程式(小幫手已經接好)。

搖桿開車(左輪 E、右輪 F)

        

!左搖桿上下管左輪、右搖桿上下管右輪(坦克式);按住 ✕ 停車。跑太快就把 SPEED 調小;往後跑就把兩顆馬達的線對調或把 SPEED 改成負數。

官方 App 讀不到的值

官方 App 只讀接收器的「組合資料」(按鍵和搖桿),下面這些功能讀不到。要用它們請改用 Pybricks MicroPython、Pybricks 積木(主機要換 Pybricks 韌體)或 MBC 積木網站。

功能(Pybricks 函式庫)為什麼讀不到/改用什麼
connected()手把有沒有連上讀不到。手把沒連線時,接收器送「按鍵全放開、搖桿在中間」,跟真的全部放開分不出來。
battery()手把電量(PS4/PS5 才有)讀不到。
kind()接收器是 PS2 還是 PS4 讀不到;兩款的寫法一樣,不用分。
buttons_psx()、pressed_psx()PSX 排列在原始藍裡,但舊的 PS4 接收器韌體排法不一樣,所以小幫手跟官方 App 積木頁一樣不用它;要用請改 Pybricks。
device_id()、firmware_version()、sensor_ok()感應器身分、韌體版本、有沒有接好都讀不到;拔線時官方 App 會怎樣還沒上機確認,所以模擬器沒有拔線選項。

使用注意

  1. 每圈先 update()。小幫手的功能都是拆「最近一次 update() 讀到的 8 個數字」;沒 update() 就一直是舊的(一開始全是 0,搖桿會讀到 0)。
  2. 這是官方 App 3 的寫法,跟 Pybricks 不一樣。孔位是 from hub import port 的 port.C(不是 Port.C)、等待是 await runloop.sleep_ms()(不是 wait()),Pybricks 的程式不能直接貼過來。家用版(Robot Inventor)App 的讀法不一樣,這頁是教育版的。
  3. 按鍵名稱用大寫字串。例如 pressed('CROSS');PS4/PS5 手把的 SHARE = 'SELECT'、OPTIONS = 'START',也可以直接寫 'SHARE'、'OPTIONS'。PS 鍵和觸控板讀不到。名稱打錯會出現 ValueError。
  4. 搖桿當開關時用 7 以上、3 以下。只推一點點時,往左、往下很快就變 4,往右、往上要推到一半左右才變 6,兩邊不一樣靈敏;把 4 ~ 6 當成「在中間」。往右、往上數字變大(到底 9),放開是 5。
  5. App Python 的讀法還沒上機逐一確認。換算照韌體和官方 App 積木頁整理;START 在 color() 讀到 −128,小幫手用 & 255 換成 128,pressed() 一樣判斷得對。