掌控者 PS2 (PS2) × SPIKE × Pybricks

互動教學SPIKE

第一次用?先跟著互動教學在網頁上做一遍,再照下面的步驟接主機。

這一頁只講 Pybricks(Python):在 SPIKE Prime/Robot Inventor 上用它讀掌控者 PS2 (PS2)的安裝步驟、每個值怎麼讀、能用的命令與範例。要換產品、主機或軟體,用上方的切換列。

安裝與設定

你需要

  • 感應器:掌控者 PS2 (PS2)(SPIKE 版)。
  • 主機:SPIKE Prime 或 Robot Inventor。
  • 電腦:Chrome 瀏覽器,打開 code.pybricks.com 就能寫,不用安裝。
  • 主機韌體:要先換成 Pybricks 韌體 v4.1(code.pybricks.com 正式版是 v4.1.1;MBC SPIKE 積木網站燒的 v4.1.0 也可以)。本站範例都照 v4.1 寫。
  • 函式庫:MBC_gamepad_Lib.py(要用「匯入函式庫」的寫法才需要)。自己寫新程式只要匯入 MBC_sensors.py,一個檔適用全部 MBC 感應器。

注意

Pybricks 3.6.1 版的函式庫與範例已不再更新(2026 年新款 SPIKE Prime 也不能用 3.6.1)。還沒升級的主機,舊檔放在下載專區的「舊版(不再更新)」。

安裝軟體

  1. 用 Chrome 打開 code.pybricks.com。
  2. 主機換成 Pybricks 韌體:最簡單的方法是到 MBC SPIKE 積木網站 上方選單「SPIKE 主機 → 安裝/更新 Pybricks 韌體」,約 3 分鐘。
  3. 之後想回到樂高官方 App,用 SPIKE App 就能換回樂高原廠韌體。

讓軟體認得感應器

Pybricks 有兩種讀法,挑一種就好:

  1. 內建指令(不用函式庫):直接用 Pybricks 內建的感應器指令讀,不用載入額外檔案,最快上手。
  2. 匯入函式庫:下載 MBC_gamepad_Lib.py,拿到高解析位置、全部通道等更多資料。

匯入函式庫的步驟:

  1. 在 code.pybricks.com 左邊檔案區按「Import a file(匯入檔案)」。
  2. 範例檔和 MBC_gamepad_Lib.py 兩個都要匯入,放在同一個專案列表裡。
  3. 點開範例,按 ▶ 執行。

重要

新專案用 MBC_sensors.py;舊專案只換掉原本那一個檔。 MBC_sensors.py 一個檔適用全部 MBC 感應器(EXP6、Servo6 擴充器的函式庫另外下載),寫法是 from MBC_sensors import MBC_LINE8,類別名稱跟舊檔名裡的一樣。舊檔名(例如本頁範例用的 MBC_gamepad_Lib.py)保留給舊程式:用新版的同名檔換掉原本那個檔就好,程式不用改。但每個舊檔名都是整份共用檔,一個程式匯入 3 個以上舊檔名,會超過 SPIKE 程式槽約 51 KB 的上限;要混用多款感應器,就只匯入 MBC_sensors.py。

提示

檔名要跟程式裡 import 的名字完全一樣,函式庫才載得進來,否則會出現 ImportError。本站下載的函式庫檔名都沒有版本字尾,不用改名。

提示

函式庫建立物件時大多有 multitask 參數:填 False 是一般模式,一行一行執行;填 True 是多工模式,每個呼叫前要加 await,可以同時做很多件事。

接線

  1. 用連接線把感應器插在主機的 C 孔(A~F 任一孔都可以)。
  2. 程式裡的孔要選同一個:內建指令用 Port.A~Port.F;函式庫的 port 參數多半是 1~6,對應 A~F。
  3. 接頭卡榫朝上,輕輕推進去。

讓手把連上接收器

PS2 的 2.4G 手把和它的接收頭是原廠成對的,不用按任何配對鍵。

  1. 接收器接好、主機開機。
  2. 打開手把電源,手把會自己連上。
  3. 看接收器板子上的綠燈:亮著=還沒接到手把;熄掉=已經接到手把。
  4. 手把上的 ANALOG(或 MODE)燈要亮,搖桿才有數值。接收器一接上手把會自動切到這個模式;燈沒亮就按一下手把中間的 ANALOG 鍵。

危險

2.4GHz 是公共頻段,跟 Wi-Fi、微波爐共用。同一場地有 12 套以上同時使用時可能互相干擾,這種場合建議改用藍牙版(PS4/PS5)。

函式庫與範例下載(Pybricks 4.1)

  • 全部下載(.zip):MBC_sensors.py、MBC_gamepad_Lib.py 和 6 個新手範例
  • 單獨下載函式庫:MBC_sensors.py(新專案用這個,一個檔適用全部 MBC 感應器,寫 from MBC_sensors import MBC_GAMEPAD)・MBC_gamepad_Lib.py(本頁範例與舊程式用)

注意

Pybricks 3.6.1 版範例已不再更新,舊檔放在下載專區的「舊版(不再更新)」。舊範例裡按鍵算出來是小數(例:印出 1.0),拿來判斷有沒有按還是對的;要印整數就外面包 int()。Pybricks 4.x 請用 SPIKE 新手範例 或 MBC 函式庫。

全部按鍵合成一個數字:buttons() 和 buttons_psx()

函式庫有兩種「16 個鍵合成一個數字」的寫法。按鍵是同一組,只是每個鍵代表的數字不一樣:

按鍵 pad.buttons()(MBC 排列) pad.buttons_psx()(PSX 排列)
上/右/下/左 1/2/4/8 16/32/64/128
▲/●/✕/■ 16/32/64/128 4096/8192/16384/32768
L2/R2/L1/R1 256/512/1024/2048 256/512/1024/2048
SELECT/L3/R3/START 4096/8192/16384/32768 1/2/4/8
判斷某一個鍵 pad.pressed('CROSS') pad.pressed_psx('CROSS') 或 pad.buttons_psx() & PSX_CROSS
  • **新手用 buttons()/pressed()**:方向鍵、圖形鍵的數字跟官方 App「反射光」一樣,本頁範例都用這個。
  • buttons_psx() 用 PS2 手把原本的按鍵順序,PS2 和 PS4 接收器送出的數字相同;Arduino(I2C)讀到的十六鍵也是這個排列,程式要跟 Arduino 共用同一套按鍵數字時用它。只有 SPIKE 版能用(讀模式 9 的第 7 個數字)。
  • 沒連上手把時兩個都是 0。
from pybricks.parameters import Port
from pybricks.tools import wait
from MBC_gamepad_Lib import MBC_GAMEPAD, PSX_CROSS

pad = MBC_GAMEPAD(Port.C)
while True:
    pad.update()                 # 每圈先更新一次
    n = pad.buttons_psx()        # PSX 排列的十六鍵
    if n & PSX_CROSS:            # ✕ 有按
        print('CROSS')
    if pad.pressed_psx('L1'):    # 用名稱判斷也可以
        print('L1')
    wait(50)

提示

掌控者 PS2 的 EV3/SPIKE App/Pybricks 積木用法也整理在 指令說明(PDF)。

重要

Pybricks 4.1 以上、不裝函式庫(內建 ColorSensor 積木)時:按鍵(reflection() 要先取整數)和 LX、LY、RX(ambient())照常讀得到,RY 讀不到(4.1 的 ambient() 只剩 1 位小數)。要 RY 請改裝 MBC 函式庫(讀模式 9,新舊韌體都行);新韌體的替代讀法上機確認後補上。

第一次測試

  1. 主機開機,在 code.pybricks.com 連上主機。
  2. 匯入並打開本頁的範例 1,按 ▶。
  3. 主控台印出的數字跟著感應器前方的東西變化,就是接好了。

常見問題

  • 出現 ImportError? 函式庫沒有匯入到同一個專案,或檔名跟 import 的名字不同。把檔名改成 MBC_gamepad_Lib.py 再匯入一次。
  • 範例跑不起來、指令不認得? 主機韌體太舊:本站範例照 Pybricks v4.1 寫,先把主機更新到 v4.1。3.6.1 已不再更新,舊版檔案在下載專區。
  • 感應器拔線(或線鬆了)怎麼辦? 程式不會停下來:函式庫會回傳上一次讀到的值,並在主控台印一次提醒(中英並列:MBC: Port C 讀不到感應器,先回傳上一次的值 / no sensor, using the last value);開機時就沒接上的話回傳 None。要在程式裡檢查,用物件的 sensor_ok():最近一次有讀到是 True,讀不到是 False(多工模式要寫 await)。插回去後函式庫會繼續讀;如果是開機時就沒接上、又用多工模式,要重新執行程式。
  • 標「只有 Pybricks 版」的範例讀到怪數字? 那個範例用的是感應器 2026-10 以後韌體的新模式,舊韌體讀到的會是別的數字。
  • 換回官方 App 後連不上? 主機現在是 Pybricks 韌體:用 SPIKE App 換回樂高原廠韌體。

讀值

程式假設感應器插 A 孔。「MBC 函式庫」寫法要先把函式庫 .py 一起匯入 Pybricks。

十六鍵 buttons16

十六鍵
範圍 意思
0~65535 bit 16 個按鍵合成一個數(PSX 排列,1 = 按下):bit0 SELECT、1 L3、2 R3、3 START、4 上、5 右、6 下、7 左、8 L2、9 R2、10 L1、11 R1、12 ▲、13 ●、14 ✕、15 ■;未連線 = 0
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

w = dev.read(9)[6]
buttons16 = w & 0xFFFF   # 十六鍵(int16 轉回 0~65535;按住 ■ 時讀到負數)

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
buttons16 = pad.buttons_psx()

模式 0 (edu) byte 6 🔒;模式 5 v[0] 🔒;模式 6 v[2];模式 9 v[6] 🔒。備註:App 原始藍 = button16(.ino:201-211); Pybricks reflection() 編碼:11 鍵 complexXY = SELECT<<10 | R1<<9 | L1<<8 | ■<<7 | ✕<<6 | ●<<5 | ▲<<4 | 左<<3 | 下<<2 | 右<<1 | 上,a = /25、b = (餘+1)×10−1,3 個 int16 = a×256+b → reflection() = complexXY;L2、R2、L3、R3、START 讀不到(.ino:334-358)。2026-10-30 起(方案 A,使用者定案):模式 5 總和 S = ceil((10×complexXY + RY)×3.072),R = G = S/3、B = S−2R → Pybricks 4.1.x int(reflection()) = complexXY(不變)、round(reflection()×10) % 10 = RY(1~9);3.6.1/4.0.0 的 reflection() 照舊 = complexXY; v2 = button16(PSX); v6 = button16(PSX)

方向鍵 dpad

方向鍵
範圍 意思
0~15 bit 上 1、右 2、下 4、左 8(同時按相加),0~15;未連線 = 0
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

w = dev.read(9)[0]
dpad = w & 0x0F   # 方向鍵(bit 0~3)

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
dpad = pad.pressed('UP')

模式 0 (edu) byte 1 🔒;模式 0 (toy) byte 0 🔒;模式 1 byte 0;模式 6 v[0] lo;模式 9 v[0] 🔒。備註:byte1 = 方向 | 形狀<<4(App 反射光):低 4 bit; byte0 = 方向 | 形狀<<4; 低 4 bit(高 4 bit = 形狀); v0 = 方向 | 形狀<<4(bit0-3)

形狀鍵 shape

形狀鍵
範圍 意思
0~15 bit ▲ 1、● 2、✕ 4、■ 8(同時按相加),0~15;未連線 = 0;0x22 的 R 高 4 bit
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

w = dev.read(9)[0]
shape = (w >> 4) & 0x0F   # 形狀鍵(bit 4~7)

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
shape = pad.pressed('TRIANGLE')

模式 0 (edu) byte 1 🔒;模式 0 (toy) byte 0 🔒;模式 1 byte 0;模式 6 v[0] hi;模式 9 v[0] 🔒。備註:高 4 bit; 高 4 bit; 高 4 bit; v0 bit4-7

肩鍵 shoulder

肩鍵
範圍 意思
0~15 bit L2 1、R2 2、L1 4、R1 8(同時按相加),0~15;未連線 = 0
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

w = dev.read(9)[1]
shoulder = w & 0x0F   # 肩鍵(bit 0~3)

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
shoulder = pad.pressed('L1')

模式 0 (edu) byte 0 🔒;模式 2 byte 0;模式 6 v[1] lo;模式 9 v[1] 🔒;模式 0 (toy) byte 6 🔒;模式 0 (toy) byte 1 🔒。備註:byte0 = 肩 | 功能<<4(App 顏色,START = −128):低 4 bit; 低 4 bit(高 4 bit = 功能); v1 = 肩 | 功能<<4(bit0-3); 原始藍 = 肩 | 功能<<4(0~255); 單鍵編號(L2=1 R2=2 L1=3 R1=4 SELECT=5 L3=6 R3=7 START=8,沒按 0;同時按只回編號最小的那個)

功能鍵 func

功能鍵
範圍 意思
0~15 bit SELECT 1、L3 2、R3 4、START 8(同時按相加),0~15;未連線 = 0;0x22 的 G 高 4 bit
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

w = dev.read(9)[1]
func = (w >> 4) & 0x0F   # 功能鍵(bit 4~7)

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
func = pad.pressed('START')

模式 0 (edu) byte 0 🔒;模式 2 byte 0;模式 6 v[1] hi;模式 9 v[1] 🔒;模式 0 (toy) byte 6 🔒;模式 0 (toy) byte 1 🔒。備註:高 4 bit; 高 4 bit; v1 bit4-7; 原始藍 = 肩 | 功能<<4(0~255); 單鍵編號(L2=1 R2=2 L1=3 R1=4 SELECT=5 L3=6 R3=7 START=8,沒按 0;同時按只回編號最小的那個)

已連線 connected

範圍 意思
0~1 1 = 手把已連線(psx.read() 成功),0 = 沒有;未連線時所有按鍵 0、搖桿回中
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

connected = dev.read(3)[0]   # 已連線

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
connected = pad.connected()

模式 3 byte 0。備註:#67 改:LIGHT 3×int8 = [已連線, 電量, 0](原本 = 4 組按鍵)

電量 battery

範圍 意思
0 % 0~100;PS2 手把沒有電量 → 恆 0(PS4 才有)
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

battery = dev.read(3)[1]   # 電量

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
battery = pad.battery()

模式 3 byte 1。備註:#67 改:PS2 送 0

搖桿 LX/LY/RX/RY stick

搖桿 LX/LY/RX/RY
範圍 意思
1~9(5 = 中間) SPIKE 讀到的是換算值 19(5 = 中間)。I2C 暫存器:10 LX、11 LY、12 RX、13 RY:−100 ~ +100,0 = 中間,右/上為正(原始 0255 死區 ±7 吸成中心);未連線 = 0。EV3/SPIKE/MATRIX 送的是 099(50 = 中間)或 19(5 = 中間),見各平台欄
from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port

dev = PUPDevice(Port.A)   # 感應器插 A 孔

stick = list(dev.read(9)[2:6])   # [LX, LY, RX, RY]

MBC 函式庫

from pybricks.parameters import Port
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.A)
pad.update()   # 每圈先更新一次
stick = pad.stick('LX')

模式 0 (edu) byte 2 🔒;模式 0 (toy) byte 2 🔒;模式 4 v[0];模式 7 v[2] 🔒;模式 9 v[2] 🔒。備註:byte2~3 = LX×10+LY、byte4~5 = RX×10+RY(11~99,中心 55;App 原始紅/綠); 原始紅 = LX×10+LY、原始綠 = RX×10+RY(各 1~9,5 = 中間); v0 = LX | LY<<8、v1 = RX | RY<<8(各 1~9,5 = 中間); Pybricks ambient() 用:v2 = LX×1000 + LY×100 + RX×10 + RY(1111~9999,中心 5555);v0、v1 同模式 6;個位數 RY 在 4.1.x 的 ambient() 讀不到,4.1.x 改從模式 5 reflection() 的小數位讀(見按鍵 buttons16); v2~v5 = LX、LY、RX、RY(0~99 ÷10,0 補 1)

這個軟體讀不到:L2 類比、R2 類比、系統鍵、手把類型。要用這些值請改用 Arduino/mBlock/micro:bit。

命令

SPIKE 接頭是唯讀的,這個軟體不能送命令:校準用感應器上的按鈕,切黑白線、門檻等設定改用 Arduino I2C、mBlock 或 micro:bit。

範例

範例 1:按鍵測試

這個範例會做什麼:主機螢幕一直顯示「按鍵的數字」。按不同的鍵,數字就不一樣,可以用來確認每一個鍵都正常。

要準備什麼

  • SPIKE 主機 1 台
  • 掌控者 PS2 接收器+2.4G 手把(已連上,見上面)

怎麼接:接收器插 C 孔。

下載程式

Pybricks
ex01_button_number.py+函式庫
Pybricks 程式碼
# 掌控者PS2 範例 1:按鍵測試(螢幕顯示按鍵數字)
# 接線:掌控者PS2 接收器 → C 埠
from pybricks.hubs import PrimeHub
from pybricks.parameters import Port
from pybricks.tools import wait
from MBC_gamepad_Lib import MBC_GAMEPAD

hub = PrimeHub()
pad = MBC_GAMEPAD(Port.C)       # 接收器插在 C 埠

while True:
    pad.update()                # 先讀一次手把
    n = pad.buttons()           # 全部按鍵合成一個數字:沒按 = 0,上 = 1、右 = 2、下 = 4、左 = 8…
    hub.display.text(str(n))    # 主機螢幕捲動顯示這個數字
    print(n)                    # 電腦畫面也印出來
    wait(100)                   # 等 0.1 秒再讀下一次

一步一步看懂程式

  1. 一直重複:下面的積木會一直做,直到你按停止。
  2. 讀按鍵:官方 App 用「反射光」,讀到方向鍵和圖形鍵;MBC 積木網站和 Pybricks 用「全部按鍵」,16 個鍵都讀得到。
  3. 顯示在螢幕上:數字會在螢幕上捲過去(按住按鍵,等它捲完)。
  4. 等 0.1 秒再讀下一次。

跑起來應該看到什麼

按住 三種寫法都顯示 MBC 積木網站、Pybricks 才有
沒按 0
上 1
右/下/左 2/4/8
▲/●/✕/■ 16/32/64/128
上+▲ 一起按 17(1+16,同時按就相加)
L2/R2/L1/R1 官方 App 還是 0(肩鍵要用「顏色」積木,範例 3 會用到) 256/512/1024/2048
SELECT/L3/R3/START 官方 App 還是 0 4096/8192/16384/32768

常見問題

  • 一直是 0,按什麼都沒反應? → 手把還沒連上:看接收器的綠燈是不是還亮著,打開手把電源或換電池。
  • 主機說找不到感應器、或數字怪怪的? → 接收器可能是 EV3 版韌體,要用 SPIKE 版。

範例 2:搖桿數值

這個範例會做什麼:主機螢幕顯示左搖桿上下的位置(1 ~ 9)。放開是 5,往上推變大、往下拉變小。

要準備什麼:同範例 1。

怎麼接:接收器插 C 孔。

下載程式

Pybricks
ex02_stick_value.py+函式庫
Pybricks 程式碼
# 掌控者PS2 範例 2:搖桿數值(螢幕顯示左搖桿上下的位置)
# 接線:掌控者PS2 接收器 → C 埠
from pybricks.hubs import PrimeHub
from pybricks.parameters import Port
from pybricks.tools import wait
from MBC_gamepad_Lib import MBC_GAMEPAD

hub = PrimeHub()
pad = MBC_GAMEPAD(Port.C)       # 接收器插在 C 埠

while True:
    pad.update()                # 先讀一次手把
    y = pad.stick('LY')         # 左搖桿上下:1(拉到最下)~ 5(中間)~ 9(推到最上)
    hub.display.number(y)       # 主機螢幕顯示這個數字
    print('LX', pad.stick('LX'), 'LY', y, 'RX', pad.stick('RX'), 'RY', pad.stick('RY'))   # 電腦畫面印出 4 個方向
    wait(100)

一步一步看懂程式

  1. 讀左搖桿上下:
    • 官方 App:「原始紅色」讀到的是 X×10+Y(例如 59=左右在中間 5、往上推到底 9),所以用「除以 10 的餘數」把 Y 拿出來(59 → 9)。
    • MBC 積木網站:直接選「左搖桿 Y(1~9)」。
    • Pybricks:pad.stick('LY')。
  2. 顯示在螢幕上。MBC 積木網站和 Pybricks 也會在電腦畫面印出數字(Pybricks 4 個方向都印)。
  3. 等 0.1 秒再讀下一次。

跑起來應該看到什麼

  • 放開搖桿:5。
  • 慢慢往上推:6、7、8、9。
  • 慢慢往下拉:4、3、2、1。

常見問題

  • 一直是 5,推了也不會變? → 手把在「數位模式」:按一下手把的 ANALOG 鍵,讓 ANALOG 燈亮起來。
  • 還沒開手把就顯示 1? → 比較舊的接收器韌體在還沒接到手把時,搖桿會讀到 1(等於拉到最下面)。打開手把就會回到 5。範例 5 有加保護,不會因為這樣一開機就倒車。
  • 想看右搖桿或左右方向? → MBC 積木網站:把下拉選單換成「右搖桿 Y」或「左搖桿 X」;官方 App:右搖桿用「原始綠色」,左右方向用「除以 10 取整數」;Pybricks:把 'LY' 換成 'RY'、'LX'、'RX'。

範例 3:按鍵控制燈和聲音

這個範例會做什麼:按 ▲ 主機燈變綠色、按 ● 變紅色、按 ✕ 變藍色、按 ■ 變粉紅色(跟手把上的顏色一樣),都沒按就關燈。按 L1 嗶一聲低音、按 R1 嗶一聲高音。

要準備什麼:同範例 1。

怎麼接:接收器插 C 孔。

下載程式

Pybricks
ex03_light_sound.py+函式庫
Pybricks 程式碼
# 掌控者PS2 範例 3:按鍵控制燈和聲音
# 接線:掌控者PS2 接收器 → C 埠
# ▲ 綠燈、● 紅燈、✕ 藍燈、■ 粉紅燈(跟手把上的顏色一樣),都沒按就關燈;L1 低音嗶、R1 高音嗶
from pybricks.hubs import PrimeHub
from pybricks.parameters import Color, Port
from pybricks.tools import wait
from MBC_gamepad_Lib import MBC_GAMEPAD

hub = PrimeHub()
pad = MBC_GAMEPAD(Port.C)               # 接收器插在 C 埠

while True:
    pad.update()                        # 先讀一次手把
    if pad.pressed('TRIANGLE'):         # ▲
        hub.light.on(Color.GREEN)
    elif pad.pressed('CIRCLE'):         # ●
        hub.light.on(Color.RED)
    elif pad.pressed('CROSS'):          # ✕
        hub.light.on(Color.BLUE)
    elif pad.pressed('SQUARE'):         # ■
        hub.light.on(Color.MAGENTA)
    else:                               # 4 個都沒按
        hub.light.off()

    if pad.pressed('L1'):
        hub.speaker.beep(262, 100)      # 低音 Do(262 Hz),響 0.1 秒
    if pad.pressed('R1'):
        hub.speaker.beep(523, 100)      # 高音 Do(523 Hz)
    wait(50)

一步一步看懂程式

  1. 先把按鍵讀進「變數」(變數=有名字的盒子,可以放一個數字):官方 App 用兩個盒子,「按鍵」放反射光(方向鍵+圖形鍵)、「肩鍵」放顏色(L1、R1…)。MBC 積木網站和 Pybricks 不用自己存,直接問「某個鍵有沒有被按下」。
  2. 如果 ▲ 有按 → 綠燈。
  3. 否則,如果 ● 有按 → 紅燈;否則如果 ✕ → 藍燈;否則如果 ■ → 粉紅燈。
  4. 都不是 → 關燈。
  5. 另外兩個「如果」:L1 有按 → 嗶低音(官方 App 音符 60、另外兩種 262 Hz,都是「Do」);R1 有按 → 嗶高音(音符 72/523 Hz,高八度的 Do)。
  6. 官方 App 判斷「▲ 有按」的寫法:(按鍵 ÷ 16) 取整數,除以 2 的餘數 = 1。● 換成 32、✕ 換成 64、■ 換成 128;L1 是 (肩鍵 ÷ 4)、R1 是 (肩鍵 ÷ 8)。

跑起來應該看到什麼

  • 按住 ▲:綠燈;放開:燈熄。
  • 同時按 ▲ 和 ●:綠燈(上面的「如果」先成立就不看下面的)。
  • 按住 L1:一直嗶嗶嗶低音。

常見問題

  • 官方 App 按 L1、R1 沒聲音? → 肩鍵是用「顏色」積木讀的(本頁依韌體和官方範例整理,尚未逐一上機確認)。先跑範例 1 確認方向鍵、圖形鍵正常;再把範例 1 的「反射光」換成「顏色」,按 L1 應該顯示 4、R1 顯示 8。
  • 燈的顏色怎麼換? → 官方 App:點「set Power Button light to」積木上的顏色圓點;MBC 積木網站:點「主機燈號設為」的下拉選單;Pybricks:把 Color.GREEN 換成 Color.YELLOW 之類。

範例 4:方向鍵開車

這個範例會做什麼:按住方向鍵,車子就往那個方向走;放開就停。上=前進、下=後退、左=原地左轉、右=原地右轉。

要準備什麼

  • 範例 1 的東西,再加上
  • 兩輪小車(兩顆馬達當輪子)

怎麼接

  • 接收器插 C 孔
  • 左輪接 E、右輪接 F

下載程式

Pybricks
ex04_dpad_drive.py+函式庫
Pybricks 程式碼
# 掌控者PS2 範例 4:方向鍵開車(按住才走,放開就停)
# 接線:掌控者PS2 接收器 → C 埠;左輪馬達 → E 埠;右輪馬達 → F 埠
from pybricks.parameters import Direction, Port
from pybricks.pupdevices import Motor
from pybricks.tools import wait
from MBC_gamepad_Lib import MBC_GAMEPAD

pad = MBC_GAMEPAD(Port.C)                          # 接收器插在 C 埠
left = Motor(Port.E, Direction.COUNTERCLOCKWISE)   # 左輪:反過來裝,所以設成逆時針才是往前
right = Motor(Port.F)                              # 右輪

while True:
    pad.update()                    # 先讀一次手把
    if pad.pressed('UP'):           # 上 → 前進(功率 50%)
        left.dc(50)
        right.dc(50)
    elif pad.pressed('DOWN'):       # 下 → 後退
        left.dc(-50)
        right.dc(-50)
    elif pad.pressed('LEFT'):       # 左 → 原地左轉:左輪往後、右輪往前
        left.dc(-30)
        right.dc(30)
    elif pad.pressed('RIGHT'):      # 右 → 原地右轉
        left.dc(30)
        right.dc(-30)
    else:                           # 都沒按 → 停
        left.dc(0)
        right.dc(0)
    wait(50)

一步一步看懂程式

  1. 告訴主機輪子怎麼裝:左右兩顆馬達是面對面裝的,所以左輪要「反過來轉」才會往前。
    • MBC 積木網站:「E 接 樂高 馬達 馬達正轉 逆時針」(F 是順時針);Pybricks:Direction.COUNTERCLOCKWISE。這樣設好之後,兩輪都給正的數字就是往前。
    • 官方 App 的馬達積木沒有這個設定,所以左輪 E 的數字要加負號:往前是 E -50、F 50。
  2. 一直重複:讀按鍵。
  3. 如果 上 有按 → 兩輪都往前(功率 50%)。
  4. 否則如果 下 → 兩輪都往後。
  5. 否則如果 左 → 左輪往後、右輪往前 → 原地左轉(功率 30%,轉慢一點比較好控制)。
  6. 否則如果 右 → 原地右轉。
  7. 都沒按 → 兩輪功率 0,停下來。
按住 MBC 積木網站、Pybricks(E, F)
上 50, 50
下 -50, -50
左 -30, 30
右 30, -30
沒按 0, 0

跑起來應該看到什麼:按住上,車子往前走;放開,車子停。

常見問題

  • 按上卻往後退? → 馬達的裝法跟樂高標準小車相反:MBC 積木網站把 E、F 的「正轉」方向對調;Pybricks 左輪改成 Direction.CLOCKWISE、右輪改成 Motor(Port.F, Direction.COUNTERCLOCKWISE);官方 App 把所有數字的正負號都對調。
  • 按上卻原地打轉? → 只有一邊的方向反了:只改那一顆馬達的正負號(或正轉方向)。
  • 手把關掉或沒電了,車子還在走? → 先按主機中間的按鈕停止程式,再檢查手把電池。

範例 5:雙搖桿坦克開車

這個範例會做什麼:像開坦克一樣:左搖桿管左輪、右搖桿管右輪。兩支都往前推=前進、都往後拉=後退、一前一後=原地轉彎。推越多跑越快,放開就停。

要準備什麼:同範例 4。

怎麼接:接收器插 C 孔;左輪接 E、右輪接 F。

下載程式

Pybricks
ex05_tank_drive.py+函式庫
Pybricks 程式碼
# 掌控者PS2 範例 5:雙搖桿坦克開車(左搖桿管左輪、右搖桿管右輪)
# 接線:掌控者PS2 接收器 → C 埠;左輪馬達 → E 埠;右輪馬達 → F 埠
from pybricks.hubs import PrimeHub
from pybricks.parameters import Color, Direction, Port
from pybricks.pupdevices import Motor
from pybricks.tools import wait
from MBC_gamepad_Lib import MBC_GAMEPAD

hub = PrimeHub()
pad = MBC_GAMEPAD(Port.C)                          # 接收器插在 C 埠
left = Motor(Port.E, Direction.COUNTERCLOCKWISE)   # 左輪:反過來裝,所以設成逆時針才是往前
right = Motor(Port.F)                              # 右輪

# 開始前的保護:等兩支搖桿都在中間(4~6)才開始,車子才不會一開機就衝出去
while True:
    pad.update()
    if 4 <= pad.stick('LY') <= 6 and 4 <= pad.stick('RY') <= 6:
        break
    wait(20)
hub.light.on(Color.GREEN)                          # 綠燈 = 可以開了

while True:
    pad.update()                                   # 先讀一次手把
    ly = pad.stick('LY')                           # 左搖桿上下 1~9
    ry = pad.stick('RY')                           # 右搖桿上下 1~9
    # 死區:搖桿在中間附近(4~6)就當成 0,放開手車子就停
    if 4 <= ly <= 6:
        left_power = 0
    else:
        left_power = (ly - 5) * 25                 # 7 → 50%、9 → 100%、3 → -50%、1 → -100%
    if 4 <= ry <= 6:
        right_power = 0
    else:
        right_power = (ry - 5) * 25
    left.dc(left_power)
    right.dc(right_power)
    wait(20)

一步一步看懂程式

  1. 開始前的保護:先「等到」兩支搖桿都在中間(4 ~ 6)才開始,然後亮綠燈。這樣手把還沒連上、或一開機搖桿被碰到時,車子不會突然衝出去。
  2. 一直重複:讀左搖桿上下(Y)和右搖桿上下(Y)。官方 App 是「原始紅色」和「原始綠色」除以 10 的餘數。
  3. 死區:搖桿在 4 ~ 6 就把功率設成 0。手放開時搖桿不一定剛好回到 5,有了死區車子才會乖乖停住。
  4. 否則:功率=**(搖桿 − 5) × 25**。推到 7 是 50%、推到底 9 是 100%;拉到 3 是 -50%、拉到底 1 是 -100%。
  5. 把功率給馬達:左輪 E 用左搖桿的功率、右輪 F 用右搖桿的功率。官方 App 的左輪要 × -1(原因同範例 4)。

跑起來應該看到什麼

  • 程式一開始:放開搖桿就亮綠燈,車子不動。
  • 兩支搖桿一起往前推:前進,推越多越快。
  • 左搖桿往前、右搖桿往後:原地右轉。
  • 放開:停車。

常見問題

  • 按了執行,一直沒亮綠燈? → 搖桿沒在中間,或手把還沒連上(比較舊的接收器韌體在還沒接到手把時搖桿會讀到 1)。放開搖桿、打開手把電源,就會亮綠燈開始。
  • 推一點點車子不會動? → 這是死區,推到 7 以上(或拉到 3 以下)才會動。想要更靈敏,可以把「4 ~ 6」改成「5 ~ 5」,但放開時車子可能會慢慢滑。
  • 太快不好控制? → 把「× 25」改成「× 15」(推到底變 60%)。
  • 前後顛倒或原地打轉? → 同範例 4 的常見問題。

範例 6(進階):連線狀態與電量

注意

這個範例只有 Pybricks 版。 它用的「連線狀態」和「電量」放在接收器的模式 3,樂高官方 App 和 MBC 積木網站讀不到。接收器韌體要是 2026-10 以後的版本,舊韌體讀到的會是別的數字。 程式碼就是範例,不需要截圖。

這個範例會做什麼:程式一開始亮紅燈,等到手把連上才亮綠燈、嗶一聲,並印出接收器種類和韌體版本;之後螢幕一直顯示手把電量(PS2 的 2.4G 手把沒有電量資訊,所以一直是 0),手把關機就變回紅燈、螢幕顯示「--」。

要準備什麼:同範例 1(主機+接收器+手把)。

怎麼接:接收器插 C 孔。

下載程式

Pybricks
ex06_connected_battery.py+函式庫
Pybricks 程式碼
# 掌控者PS2 範例 6:連線狀態與電量(等手把連上才開始,螢幕顯示電量)
# 接線:掌控者PS2 接收器 → C 埠
# 只有 Pybricks 版:連線狀態和電量放在接收器的「模式 3」,官方 App 和積木網站讀不到;接收器韌體要 2026-10 以後
from pybricks.hubs import PrimeHub
from pybricks.parameters import Color, Port
from pybricks.tools import wait
from MBC_gamepad_Lib import MBC_GAMEPAD

hub = PrimeHub()
pad = MBC_GAMEPAD(Port.C)                    # 接收器插在 C 埠

hub.light.on(Color.RED)                      # 紅燈 = 手把還沒連上
while not pad.connected():                   # 等到手把連上(True)才往下
    wait(200)
hub.light.on(Color.GREEN)                    # 綠燈 = 連上了
hub.speaker.beep()
print('接收器種類', pad.kind(), ' 韌體', pad.firmware_version())   # 例如 PS4 (1, 0)

while True:
    if pad.connected():
        battery = pad.battery()              # PS2 手把沒有電量資訊,一直是 0
        hub.display.number(min(battery, 99)) # 螢幕最多只能顯示兩位數
        hub.light.on(Color.GREEN)
        print('已連線  電量', battery, '%')
    else:                                    # 手把關機或離太遠 → 斷線
        hub.display.text('--')
        hub.light.on(Color.RED)
        print('斷線了')
    wait(500)

一步一步看懂程式

  1. pad.connected():手把有沒有連上接收器(True/False)。開頭用「等到連上」取代範例 5 的「等搖桿在中間」,更可靠。
  2. pad.kind()、pad.firmware_version():接收器是 PS2 還是 PS4 款、韌體幾版(讀感應器的模式 8)。
  3. 一直重複:連著就顯示 pad.battery()(PS2 一直是 0)、綠燈;斷線就紅燈、「--」。
  4. 這個範例沒有呼叫 pad.update(),因為沒有要讀按鍵。要讀按鍵的程式請照範例 1~5 的寫法,connected() 放在迴圈外或偶爾呼叫(每次呼叫接收器要切換模式,多花幾十 ms)。

跑起來應該看到什麼:手把還沒開:紅燈。打開手把電源,連上的瞬間:綠燈+嗶,螢幕顯示 0(PS2 沒有電量)。把手把關掉:紅燈、「--」。

常見問題

  • 為什麼電量一直是 0? → PS2 的 2.4G 手把本來就不會回報電量;想看電量請用 掌控者 PS4/PS5。
  • 一直紅燈? → 手把電源沒開、或接收器韌體太舊(2026-10 以前)沒有連線狀態,請更新韌體。
  • 可以跟範例 5 合併嗎? → 可以:把範例 5 開頭的「等搖桿在中間」換成「等到 pad.connected()」。

其他問題

  • 主機認不到感應器? 拔掉重插一次,等 2 秒;換一個孔試試。官方 App 會把它顯示成「顏色感應器」,這是正常的。
  • 可以同時用官方 App 和 Pybricks 嗎? 一次只能裝一種韌體:Pybricks 與 MBC 積木網站用 Pybricks 韌體,官方 App 用樂高原廠韌體;隨時可以用 SPIKE App 換回原廠韌體。

還有問題?到 聯絡我們 附上你用的軟體和程式截圖。

下載

本頁依據

  • 主機與軟體清單:_build/guides.json
  • 值與命令:_build/protocol/ps2.json(單一真相來源)
  • 安裝與設定:_build/guides/software/spike-pybricks.zh.md、_build/guides/product/ps2/spike-pybricks.zh.md
  • 範例:sensors/ps2/spike-examples.md
LINE 詢價選購指南