掌控者 PS2 (PS2) × micro:bit × MakeCode

互動教學micro:bit

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

這一頁只講 MakeCode(積木/JavaScript):在 BBC micro:bit V1/V2 上用它讀掌控者 PS2 (PS2)的安裝步驟、每個值怎麼讀、能用的命令與範例。要換產品、主機或軟體,用上方的切換列。

要買哪個版本、怎麼接

買 通用 I2C 版,接 micro:bit 擴充板的 I2C 孔(SDA = P20、SCL = P19),出廠位址 0x42。這款耗電小,VCC 可以先接 micro:bit 的 3V 腳(V1 約 90 mA、V2 約 190 mA);用電池供電時電壓可能掉到 3 V 以下,不穩就改外接 5 V(GND 要和 micro:bit 共地)。

掌控者 PS2 (PS2) × BBC micro:bit V1/V2

安裝與設定

你需要

  • 感應器:掌控者 PS2 (PS2)(通用 I2C 版)。SPIKE 版、EV3 版韌體不同,接 micro:bit 讀不到。
  • 主板:BBC micro:bit V1 或 V2,加上能接到 P19/P20 的擴充板或鱷魚夾轉接板。
  • 軟體:MakeCode 網頁版(makecode.microbit.org,積木/JavaScript);離線版(Windows/Mac App)也可以,第一次加擴充要連網。
  • 擴充:pxt-mbc-sensors v2(MIT,免下載,貼網址就能加)。

重要

上機待測:擴充 v2.0.5 已在 MakeCode 編譯通過(V1+V2),還沒有接實機逐顆積木核對數值。積木名稱以 GitHub 發布版 為準。

安裝軟體

  1. 打開 makecode.microbit.org → 新專案。
  2. 編輯器語言切到 繁體中文(右上齒輪 → Language),積木就會顯示中文。

讓軟體認得感應器

  1. 點積木區下方的 進階 → 擴充(齒輪選單裡也有「擴充」)。
  2. 在搜尋框貼上 https://github.com/contactmbcrobot/pxt-mbc-sensors,按 Enter。
  3. 點出現的 mbc-sensors 卡片,積木區會多出「MBC 感應器」分類(循行者、測距者、掌控者、陀螺儀、神攝手、裝置六組)。
  4. 用範例:右上切到 JavaScript → 貼上範例 → 下載 .hex 拖進 MICROBIT 磁碟。

提示

不需要送審、不需要下載檔案:老師把網址給學生貼就能用。要固定版本可貼 https://github.com/contactmbcrobot/pxt-mbc-sensors#v2.0.5。

接線

micro:bit 的 I2C 腳位是固定的:P19 = SCL、P20 = SDA(金手指邊緣接頭,要用擴充板或鱷魚夾轉接板才接得到)。MBC 4P 感應器線的 TX 接 SCL、RX 接 SDA,跟接 Arduino 是同一條線。

感應器 micro:bit 說明
SCL(TX) P19 I2C 時脈
SDA(RX) P20 I2C 資料
VCC 3V 或外部 5 V 耗電大的產品不能吃 micro:bit 的 3V
GND GND 外部供電時 GND 要和 micro:bit 共地
  • 3V 腳電流:V1 約 90 mA、V2 約 190 mA;用電池時電壓可能掉到 2 V 多。測距者 8 路、掌控者 PS4/PS5、神攝手 一定要外部 5 V;其他產品可先試 3V,電池供電時建議外部 5 V。
  • 電壓準位:MBC 產品的 I2C 線是 3.3 V 準位,跟 micro:bit 相容,不需要準位轉換。
  • 這個產品的出廠位址是 0x42;位址不同的產品可以串在同一組 P19/P20 上。

讓手把連上接收器

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

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

危險

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

第一次測試

  1. 先用「裝置 → 等位址 0x42 的裝置就緒」或「位址 0x42 的裝置就緒?」積木確認接線。
  2. 下載本頁範例 1 的 .hex 到 micro:bit。
  3. LED 顯示的數字跟著感應器前方的東西變化,就是接好了。

常見問題

  • 讀值一直是 0? 裝置沒接時讀值積木回 0(內部的 −32768 已過濾)、是/否積木一律回「否」,不會報錯。依序檢查:接線(SDA=P20、SCL=P19)→ 外接電源有沒有開 →「位址 … 的裝置就緒?」是不是 true。
  • V1 的指南針、加速度計也壞了? V1 的 I2C 線和板上加速度計共用,感應器卡住 SDA 會連帶讓它們失效;V2 把外部 I2C 分開了。
  • 時好時壞? STM32 產品(循行者、測距者、PS2、陀螺儀)會時脈延展,micro:bit V2 的 nRF52 對此有已知問題(errata 219),V1/V2 都要實測;ESP32 產品(PS4、神攝手)不延展,擴充已內建「寫完編號等 2 ms 再讀」。
  • 兩個同類產品一起接? 同類產品位址相同,先用「裝置 → 把位址 … 的裝置改成位址 …」把其中一個改掉(重開機生效),再用該產品的「改用位址」積木告訴擴充新位址。

讀值

MakeCode 加入 pxt-mbc-sensors 擴充後,在「MBC 感應器」分類找積木;JavaScript 寫法一併列出,位址 0x42。

十六鍵 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
(掌控者 十六鍵位元圖 :: #00A4E4)
let buttons16 = mbc.padButtons()   // 十六鍵:0~65535 bit

相關積木「掌控者 按鈕 [✕] 被按住?」

let padButtonPressed = mbc.padButtonPressed(MbcPadButton.Cross)

相關積木「當掌控者 按鈕 [✕] [按下]」

mbc.onPadButton(MbcPadButton.Cross, MbcPadButtonEvent.Pressed, function () {
})

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

方向鍵 dpad

方向鍵
範圍 意思
0~15 bit 上 1、右 2、下 4、左 8(同時按相加),0~15;未連線 = 0
(掌控者 [方向鍵 v](0~15) :: #00A4E4)
let dpad = mbc.padGroup(MbcPadGroup.Dpad)   // 方向鍵:0~15 bit

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

形狀鍵 shape

形狀鍵
範圍 意思
0~15 bit ▲ 1、● 2、✕ 4、■ 8(同時按相加),0~15;未連線 = 0;0x22 的 R 高 4 bit
(掌控者 [形狀鍵 v](0~15) :: #00A4E4)
let shape = mbc.padGroup(MbcPadGroup.Shapes)   // 形狀鍵:0~15 bit

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

肩鍵 shoulder

肩鍵
範圍 意思
0~15 bit L2 1、R2 2、L1 4、R1 8(同時按相加),0~15;未連線 = 0
(掌控者 [肩鍵 v](0~15) :: #00A4E4)
let shoulder = mbc.padGroup(MbcPadGroup.Shoulders)   // 肩鍵:0~15 bit

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

功能鍵 func

功能鍵
範圍 意思
0~15 bit SELECT 1、L3 2、R3 4、START 8(同時按相加),0~15;未連線 = 0;0x22 的 G 高 4 bit
(掌控者 [功能鍵 v](0~15) :: #00A4E4)
let func = mbc.padGroup(MbcPadGroup.Functions)   // 功能鍵:0~15 bit

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

已連線 connected

範圍 意思
0~1 1 = 手把已連線(psx.read() 成功),0 = 沒有;未連線時所有按鍵 0、搖桿回中
<掌控者 手把已連線? :: #00A4E4>
let connected = mbc.padConnected()   // 已連線:0~1

感應器沒接好(讀不到)時回「否」。

電量 battery

範圍 意思
0 % 0~100;PS2 手把沒有電量 → 恆 0(PS4 才有)
(掌控者 電量(百分比) :: #00A4E4)
let battery = mbc.padBattery()   // 電量:0 %

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

L2 類比 l2Analog

範圍 意思
0~255 L2 壓力 0~255(DualShock 2 類比模式才有壓力值;手把沒有壓力值時按下 = 255、放開 = 0);未連線 = 0
(掌控者 扳機 [L2 v] 類比值 :: #00A4E4)
let l2Analog = mbc.padTrigger(MbcPadTrigger.L2)   // L2 類比:0~255

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

R2 類比 r2Analog

範圍 意思
0~255 R2 壓力 0~255(同 08);未連線 = 0
(掌控者 扳機 [R2 v] 類比值 :: #00A4E4)
let r2Analog = mbc.padTrigger(MbcPadTrigger.R2)   // R2 類比:0~255

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

系統鍵 sysKeys

範圍 意思
0 bit b0 PS 鍵、b1 擷取鍵;PS2 手把沒有 → 恆 0(PS4 才有)

擴充沒有這顆積木;在 JavaScript 用 mbc.readValue(位址, 編號) 讀(讀不到 = −32768)。相關積木:「掌控者 系統鍵 [PS] 被按住?」。

let sysKeys = mbc.readValue(0x42, 0x0A)   // 系統鍵:0 bit

手把類型 padType

範圍 意思
0~2 0 沒有手把、1 PS2 數位模式、2 PS2 類比模式(3 PS4、4 PS5 只有 PS4 接收器會出現)
(掌控者 手把類型 :: #00A4E4)
let padType = mbc.padType()   // 手把類型:0~2

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

搖桿 LX/LY/RX/RY stick

搖桿 LX/LY/RX/RY
範圍 意思
-100~+100 10 LX、11 LY、12 RX、13 RY:−100 ~ +100,0 = 中間,右/上為正(原始 0255 死區 ±7 吸成中心);未連線 = 0。EV3/SPIKE/MATRIX 送的是 099(50 = 中間)或 1~9(5 = 中間),見各平台欄
(掌控者 搖桿 [左搖桿 X v] :: #00A4E4)
let stick = [mbc.padStick(MbcPadAxis.LeftX), mbc.padStick(MbcPadAxis.LeftY), mbc.padStick(MbcPadAxis.RightX), mbc.padStick(MbcPadAxis.RightY)]   // 搖桿 LX/LY/RX/RY:-100~+100

感應器沒接好(讀不到)時回 0,先用「位址 … 的裝置就緒?」確認接線。

命令

震動 vibrate

[強度 0~255],0 = 停;PS2 接收器收到後回 ACK 但忽略(250614 已關手把震動),PS4 才有作用

掌控者 震動 強度 (200) :: #00A4E4
mbc.padRumble(200)   // 震動

燈條顏色 setLed

[R][G][B] 各 0~255;PS2 手把沒有燈條,接收器收到後回 ACK 但忽略,PS4 才有作用

掌控者 燈條顏色 [#ff0000] :: #00A4E4
mbc.padLight(0xff0000)   // 燈條顏色

範例

這一頁是寫給完全沒寫過程式的人。5 個範例從「LED 顯示讀值」開始,一步一步做到「開車」。全部用 MakeCode 網頁版+MBC 擴充 pxt-mbc-sensors v2 寫:切到 JavaScript 把範例貼上就能用,也可以切回積木模式看它變成哪些積木。

重要

  • 擴充 pxt-mbc-sensors v2 還沒上機驗證。本頁的範例都在電腦上用 MakeCode CLI 編譯通過(V1+V2 各一次),數值方向、就緒時間、供電等實機結果見下方「硬體關卡」的「上機待測」。
  • 請用 通用 I2C 版的產品。SPIKE 版、EV3 版韌體不同,接 micro:bit 讀不到。

提示

PS2 手把的 2.4G 接收頭插在接收器上,打開手把電源就會自動連線(接收器指示燈看 產品頁)。接收器要是通用 I2C 版韌體。PS2 手把沒有震動回傳、燈條和電量,這三個積木送出去會被忽略。

軟體對照表

寫法 micro:bit V1 micro:bit V2 怎麼用
MakeCode 網頁版(makecode.microbit.org,積木/JavaScript) ✔(記憶體較小,本頁範例都編得過) ✔ 新專案 → 齒輪 → 擴充 → 貼 https://github.com/contactmbcrobot/pxt-mbc-sensors → 右上切到 JavaScript → 貼上範例 → 下載 .hex 拖進 MICROBIT 磁碟
MakeCode 離線版(Windows/Mac App) ✔ ✔ 同上;第一次加擴充要連網
Python Editor(MicroPython) — — 還沒有 MBC 模組
  • 聲音:V2 有內建喇叭;V1 要在 P0 接蜂鳴器或耳機才有聲音。
  • 伺服/馬達:範例用 pins.servoWritePin,一顆 9g 伺服(SG90)接 P1;開車用兩顆連續旋轉伺服(FS90R 之類),左輪 P1、右輪 P2。伺服電源一律外接 4.8~6 V 電池盒,電池負極要和 micro:bit GND 接在一起(共地);不要從 micro:bit 3V 腳推伺服。
  • 積木文字:MakeCode 語言切成繁體中文,擴充的積木就是中文(例如「循行者 線位置」);本頁表格同時列出中文積木和 JavaScript 寫法。

開始之前:硬體關卡(上機待測)

micro:bit 是 3.3 V 的板子,接 MBC 產品前每一關都要過;打「上機待測」的是擴充 v2 還沒在實機確認的項目。

關卡 這款產品 狀態
電壓 MBC 產品的 I2C 都是 3.3 V 準位,直接接 P19/P20,不用準位轉換 ✔
供電 接收器是 STM32+2.4G 模組,約 40 mA,可以先試 micro:bit 的 3V 腳(V1 約 90 mA、V2 約 190 mA 上限);不穩就外接 5 V 上機待測
I2C 上拉 micro:bit 板上已有 4.7 kΩ;產品板若也有上拉,並聯後要確認低電位 ≤ 0.3×VDD 上機待測
時脈延展 STM32 從機預設會時脈延展,V2(nRF52833)對延展有已知問題,要 V1、V2 各測一次 上機待測
位址衝突 出廠位址 0x42,和掌控者 PS4/PS5 一樣;兩個接收器同時接要先用「裝置」分類的「改成位址」積木換掉一個 —
就緒時間 接收器開機馬上就緒(F3 b0);手把連上後 F3 b1 = 1,範例用「手把已連線?」判斷 上機待測

讀不到值時先看:接線(SDA=P20、SCL=P19)→ 外接電源有沒有開 → 擴充「裝置」分類的「位址 … 的裝置就緒?」積木是不是 true。

接線(所有範例共用)

掌控者 PS2 × micro:bit
感應器 micro:bit
SDA P20
SCL P19
VCC 3V(或外接 5 V)
GND GND(伺服電池負極也接這裡)

這頁會用到的數值

搖桿每一軸 −100~+100,放開是 0,右、上為正。按鍵直接用下拉選單選名稱。

積木(繁中) JavaScript 範圍 意思 用在
掌控者 搖桿 左搖桿 X/Y、右搖桿 X/Y mbc.padStick(MbcPadAxis.LeftY) −100~+100 0 = 中間,右/上 = 正 1, 5
掌控者 按鈕 … 被按住? mbc.padButtonPressed(MbcPadButton.Up) true / false 16 個鍵都可以選:上下左右、△○✕□、L1 R1 L2 R2、L3 R3、SELECT/SHARE、START/OPTIONS 4
當掌控者 按鈕 … 按下/放開 mbc.onPadButton(MbcPadButton.Cross, MbcPadButtonEvent.Pressed, ...) 事件 按下或放開的那一瞬間執行一次 2
掌控者 扳機 L2/R2 類比值 mbc.padTrigger(MbcPadTrigger.R2) 0~255 PS2 數位手把只有 0(放開)或 255(按下);DualShock 2 類比模式才有壓力 3
掌控者 手把已連線? mbc.padConnected() true / false 沒連線時按鍵全 0、搖桿回中 1, 2, 4, 5
掌控者 電量(百分比) mbc.padBattery() 0~100 PS2 手把恆 0(只有 PS4/PS5 有) 5
等位址 … 的裝置就緒 mbc.waitReady(mbc.ADDR_PAD, 3000) true / false 最多等 3 秒,接收器有回應就 true(進階 → 裝置) 1

範例 1:搖桿點點

這個範例會做什麼:推左搖桿,LED 上的亮點跟著跑;手把沒連線畫 X。按 A 顯示左搖桿 X 的數字、按 B 顯示 Y。用來確認接收器接好、手把連上、方向正確。

要準備什麼

  • micro:bit V1 或 V2+USB 線
  • 掌控者 PS2 接收器(通用 I2C 版)+4P 線+PS2 2.4G 無線手把(接收頭插在接收器上)

怎麼接:照上面的接線表:SDA → P20、SCL → P19、VCC → 3V(或外接 5 V)、GND → GND。

下載程式:ex01_stick_dot.ts(右鍵另存)→ MakeCode 新專案 → 齒輪 → 擴充 → 貼 https://github.com/contactmbcrobot/pxt-mbc-sensors → 右上切到 JavaScript → 全選刪掉原本的內容、把檔案內容貼上 → 下載,把 .hex 拖進 MICROBIT 磁碟。

程式

// 掌控者 PS2 × micro:bit 範例 1:搖桿點點(LED 上的點跟著左搖桿動)
// 做什麼:推左搖桿,LED 上的亮點跟著跑;手把沒連線畫 X。按 A 顯示左搖桿 X 的數字、按 B 顯示 Y。
// 接線:接收器 SDA → P20、SCL → P19、VCC → 3V(或外接 5 V)、GND → GND 共地。
// 準備:手把先跟接收器配對好(看產品頁)。MakeCode 新專案 → 擴充 → 貼 https://github.com/contactmbcrobot/pxt-mbc-sensors → 切到 JavaScript 把本檔全部貼上 → 下載到 micro:bit。
// 看到什麼:開機打勾(找到接收器);手把沒開 → X;放開搖桿 → 點在正中間;推到右上 → 點跑到右上角。

let busy = false

if (mbc.waitReady(mbc.ADDR_PAD, 3000)) {
    basic.showIcon(IconNames.Yes)
} else {
    basic.showIcon(IconNames.No)                          // 沒回應:檢查 P19/P20 和外接電源
}

basic.forever(function () {
    if (busy) {
        basic.pause(100)
        return
    }
    if (!mbc.padConnected()) {                            // 手把沒連上
        basic.showIcon(IconNames.No, 0)
        basic.pause(200)
        return
    }
    let sx = mbc.padStick(MbcPadAxis.LeftX)               // −100(左)~ +100(右),0 = 中間
    let sy = mbc.padStick(MbcPadAxis.LeftY)               // −100(下)~ +100(上)
    let x = Math.round(Math.map(sx, -100, 100, 0, 4))
    let y = Math.round(Math.map(sy, -100, 100, 4, 0))     // 上 = 正 → 第 0 列
    basic.clearScreen()
    led.plot(x, y)
    basic.pause(50)
})

input.onButtonPressed(Button.A, function () {
    busy = true
    basic.showNumber(mbc.padStick(MbcPadAxis.LeftX))
    busy = false
})
input.onButtonPressed(Button.B, function () {
    busy = true
    basic.showNumber(mbc.padStick(MbcPadAxis.LeftY))
    busy = false
})

一步一步看懂程式

  1. mbc.waitReady(mbc.ADDR_PAD, 3000):接收器有回應打勾,沒有打 X。
  2. forever:!mbc.padConnected() 手把沒連上 → X,等 0.2 秒再看。
  3. sx = mbc.padStick(LeftX)、sy = mbc.padStick(LeftY):−100~+100。
  4. x = Math.map(sx, −100, 100, 0, 4);y = Math.map(sy, −100, 100, 4, 0):上是正,所以 Y 要倒過來(第 0 列在上面)。
  5. basic.clearScreen() 再 led.plot(x, y) 畫一個點。
  6. A/B:basic.showNumber 顯示數字,busy 讓點先暫停。

跑起來應該看到什麼

  • 開機:打勾。手把沒開:X。
  • 按手把 PS 鍵連上:點在正中間。
  • 左搖桿推到右上:點跑到右上角;按 A 顯示 100、按 B 顯示 100。
  • 往左推一半:點在左邊第二行;A 顯示約 −50。

常見問題

  • 一直 X? → 手把沒連上:確認 2.4G 接收頭插在接收器上、手把電源有開、手把的 ANALOG 燈有亮。
  • 點只會在中間附近動? → 正常,搖桿推到底才會到角落;想放大改 Math.map(sx, −60, 60, 0, 4)。
  • 開機就是 X(找不到感應器)? → 看接線 SDA=P20、SCL=P19 有沒有接反;外接電源有沒有開;用鱷魚夾接的話夾子有沒有碰到旁邊的腳。
  • 模擬器裡數字都是 0? → 正常。MakeCode 模擬器沒有真的 I2C,讀到的都是 0;要看真的數值一定要下載到 micro:bit。
  • V1 沒有聲音? → V1 沒有喇叭,在 P0 和 GND 之間接蜂鳴器或耳機。

範例 2:按鍵變圖案和聲音

這個範例會做什麼:△ ○ ✕ □ 各畫一個圖案+一個音,方向鍵畫箭頭。全部用「當掌控者按鈕 … 按下」事件積木寫。

要準備什麼

  • 範例 1 的東西
  • V1 另外要蜂鳴器或耳機接 P0

怎麼接:同範例 1。

下載程式:ex02_button_sound.ts(右鍵另存)→ MakeCode 新專案 → 齒輪 → 擴充 → 貼 https://github.com/contactmbcrobot/pxt-mbc-sensors → 右上切到 JavaScript → 全選刪掉原本的內容、把檔案內容貼上 → 下載,把 .hex 拖進 MICROBIT 磁碟。

程式

// 掌控者 PS2 × micro:bit 範例 2:按鍵變圖案和聲音
// 做什麼:△ ○ ✕ □ 各畫一個圖案+一個音;方向鍵畫箭頭。
// 接線:接收器 SDA → P20、SCL → P19、VCC → 3V(或外接 5 V)、GND → GND 共地。V1 要在 P0 接蜂鳴器或耳機才有聲音(V2 有內建喇叭)。
// 準備:手把配對好;擴充與貼程式的方法同範例 1。
// 看到什麼:按 △ → 三角形+Do;○ → 靶心+Mi;✕ → X+Sol;□ → 方形+高音 Do;方向鍵 → 四個方向的箭頭。

mbc.onPadButton(MbcPadButton.Triangle, MbcPadButtonEvent.Pressed, function () {
    basic.showIcon(IconNames.Triangle, 0)
    music.playTone(Note.C, 200)
})
mbc.onPadButton(MbcPadButton.Circle, MbcPadButtonEvent.Pressed, function () {
    basic.showIcon(IconNames.Target, 0)
    music.playTone(Note.E, 200)
})
mbc.onPadButton(MbcPadButton.Cross, MbcPadButtonEvent.Pressed, function () {
    basic.showIcon(IconNames.No, 0)
    music.playTone(Note.G, 200)
})
mbc.onPadButton(MbcPadButton.Cross, MbcPadButtonEvent.Released, function () {
    basic.clearScreen()
})
mbc.onPadButton(MbcPadButton.Square, MbcPadButtonEvent.Pressed, function () {
    basic.showIcon(IconNames.Square, 0)
    music.playTone(Note.C5, 200)
})
mbc.onPadButton(MbcPadButton.Up, MbcPadButtonEvent.Pressed, function () {
    basic.showArrow(ArrowNames.North, 0)
})
mbc.onPadButton(MbcPadButton.Down, MbcPadButtonEvent.Pressed, function () {
    basic.showArrow(ArrowNames.South, 0)
})
mbc.onPadButton(MbcPadButton.Left, MbcPadButtonEvent.Pressed, function () {
    basic.showArrow(ArrowNames.West, 0)
})
mbc.onPadButton(MbcPadButton.Right, MbcPadButtonEvent.Pressed, function () {
    basic.showArrow(ArrowNames.East, 0)
})

basic.forever(function () {
    if (!mbc.padConnected()) {                            // 手把沒連線就一直顯示小愛心提醒
        basic.showIcon(IconNames.SmallHeart, 0)
    }
    basic.pause(500)
})

一步一步看懂程式

  1. mbc.onPadButton(MbcPadButton.Triangle, Pressed, ...):△ 按下那一瞬間執行一次 → 三角形圖案、Note.C。
  2. ○ → 靶心、Note.E;□ → 方形、Note.C5。
  3. ✕ 按下 → X 圖案、Note.G;✕ 放開另外一個事件 → 清螢幕。
  4. 上下左右各一個事件 → 四個箭頭。
  5. forever:手把沒連線時每 0.5 秒畫小愛心提醒。

跑起來應該看到什麼

  • 按 △:三角形、Do。
  • 按住 ✕:X;放開:螢幕清掉。
  • 按方向鍵:箭頭。

常見問題

  • 按了沒反應? → 先跑範例 1 確認手把連上;PS2 手把要在 ANALOG 模式(紅燈亮)。
  • 想加 L1/R1? → 多複製一個事件,按鈕選 MbcPadButton.L1。

範例 3:扳機控制伺服

這個範例會做什麼:R2 按下伺服轉到 180°、L2 按下轉到 0°、都放開回 90°(PS2 數位手把的扳機只有 0 或 255,所以是跳的;DualShock 2 類比模式才會漸變)。LED 長條顯示 R2。按 A 顯示目前角度。

要準備什麼

  • 範例 1 的東西
  • 9g 伺服(SG90)×1
  • 4.8~6 V 電池盒+杜邦線

怎麼接:接收器同範例 1。伺服 橘(訊號)→ P1、紅 → 外接 4.8~6 V 電池正極、棕 → 電池負極,電池負極再接一條到 micro:bit GND(共地)。

下載程式:ex03_trigger_servo.ts(右鍵另存)→ MakeCode 新專案 → 齒輪 → 擴充 → 貼 https://github.com/contactmbcrobot/pxt-mbc-sensors → 右上切到 JavaScript → 全選刪掉原本的內容、把檔案內容貼上 → 下載,把 .hex 拖進 MICROBIT 磁碟。

程式

// 掌控者 PS2 × micro:bit 範例 3:扳機控制伺服
// 做什麼:R2 壓多深,伺服就往右轉多少;L2 往左;兩邊都放開回正中。LED 長條顯示 R2 的壓力。按 A 顯示目前角度。
// 接線:接收器 SDA → P20、SCL → P19、VCC → 3V(或外接 5 V)、GND → GND。伺服 橘(訊號)→ P1、紅 → 外接 4.8~6 V 電池正極、棕 → 電池負極並接 micro:bit GND。
// 準備:9g 伺服(SG90)。
// 看到什麼:慢慢壓 R2 → 長條變長、伺服慢慢轉到 180°;壓 L2 → 轉到 0°;放開 → 90°。

let angle = 90

basic.forever(function () {
    let r2 = mbc.padTrigger(MbcPadTrigger.R2)             // 0(放開)~ 255(壓到底)
    let l2 = mbc.padTrigger(MbcPadTrigger.L2)
    angle = Math.round(90 + (r2 - l2) * 90 / 255)         // R2 → 90~180、L2 → 90~0
    pins.servoWritePin(AnalogPin.P1, angle)
    led.plotBarGraph(r2, 255)
    basic.pause(30)
})

input.onButtonPressed(Button.A, function () {
    basic.showNumber(angle)
})

一步一步看懂程式

  1. forever:r2 = mbc.padTrigger(R2)、l2 = mbc.padTrigger(L2),各 0~255。
  2. angle = 90 + (r2 − l2) × 90 / 255:只壓 R2 → 90~180;只壓 L2 → 90~0;Math.round 取整數。
  3. pins.servoWritePin(AnalogPin.P1, angle) 每 30 ms 更新。
  4. led.plotBarGraph(r2, 255):長條顯示 R2 壓力。

跑起來應該看到什麼

  • 按 R2:長條全亮、伺服轉到 180°。
  • 按 L2:轉到 0°。兩個都按:回 90°。
  • 放開:90°,長條全暗。

常見問題

  • PS2 手把一壓就跳到底? → PS2 數位手把的 L2/R2 只有 0 或 255,沒有壓力值;要漸變改用右搖桿:angle = 90 + padStick(RightX) × 0.9。
  • 伺服抖? → 伺服要外接電池、共地。

範例 4:方向鍵開車

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

要準備什麼

  • 兩輪小車:兩顆連續旋轉伺服(FS90R 之類)當輪子+一顆萬向輪
  • 接收器固定在車上
  • 4.8~6 V 電池盒(伺服用)+外接 5 V(接收器用,可以是同一個行動電源)

怎麼接:接收器同範例 1。左輪連續旋轉伺服訊號 → P1、右輪 → P2,兩顆伺服的紅線接 4.8~6 V 電池盒正極、棕線接電池負極,電池負極再接 micro:bit GND。

下載程式:ex04_dpad_drive.ts(右鍵另存)→ MakeCode 新專案 → 齒輪 → 擴充 → 貼 https://github.com/contactmbcrobot/pxt-mbc-sensors → 右上切到 JavaScript → 全選刪掉原本的內容、把檔案內容貼上 → 下載,把 .hex 拖進 MICROBIT 磁碟。

程式

// 掌控者 PS2 × micro:bit 範例 4:方向鍵開車
// 做什麼:按住方向鍵車子就往那個方向走,放開就停:上 = 前進、下 = 後退、左 = 原地左轉、右 = 原地右轉。手把斷線車子自動停。
// 接線:接收器 SDA → P20、SCL → P19、VCC → 3V(或外接 5 V)、GND → GND。左輪連續旋轉伺服訊號 → P1、右輪 → P2;伺服電源 4.8~6 V 電池盒,電池負極接 micro:bit GND。
// 準備:兩輪小車(兩顆連續旋轉伺服當輪子)。
// 看到什麼:按住上 → 車子前進、LED 朝上箭頭;放開 → 停;手把關掉 → X、車停。

// 左輪伺服 P1、右輪伺服 P2(連續旋轉伺服);left/right = −100~100,正 = 前進
function drive(left: number, right: number): void {
    left = Math.constrain(left, -100, 100)
    right = Math.constrain(right, -100, 100)
    pins.servoWritePin(AnalogPin.P1, Math.round(90 + left * 0.9))    // 90 = 停、180 = 全速前進、0 = 全速後退
    pins.servoWritePin(AnalogPin.P2, Math.round(90 - right * 0.9))   // 右輪裝的方向相反,所以用減的
}

basic.forever(function () {
    if (!mbc.padConnected()) {                            // 斷線:停車
        drive(0, 0)
        basic.showIcon(IconNames.No, 0)
    } else if (mbc.padButtonPressed(MbcPadButton.Up)) {
        drive(50, 50)                                     // 前進
        basic.showArrow(ArrowNames.North, 0)
    } else if (mbc.padButtonPressed(MbcPadButton.Down)) {
        drive(-50, -50)                                   // 後退
        basic.showArrow(ArrowNames.South, 0)
    } else if (mbc.padButtonPressed(MbcPadButton.Left)) {
        drive(-30, 30)                                    // 左輪往後、右輪往前 = 原地左轉
        basic.showArrow(ArrowNames.West, 0)
    } else if (mbc.padButtonPressed(MbcPadButton.Right)) {
        drive(30, -30)                                    // 原地右轉
        basic.showArrow(ArrowNames.East, 0)
    } else {
        drive(0, 0)                                       // 都沒按:停
        basic.clearScreen()
    }
    basic.pause(50)
})

一步一步看懂程式

  1. function drive(left, right):左輪 P1、右輪 P2,−100~100,正 = 前進;右輪裝反所以用減的。
  2. forever:先看 !mbc.padConnected() → 斷線就 drive(0, 0)、X。
  3. mbc.padButtonPressed(Up) → drive(50, 50) 前進、上箭頭;Down → drive(−50, −50)。
  4. Left → drive(−30, 30):左輪往後、右輪往前 = 原地左轉;Right 相反。
  5. 都沒按 → drive(0, 0) 停、清螢幕。每 50 ms 一輪。

跑起來應該看到什麼

  • 按住上:前進、上箭頭;放開:停。
  • 按住左:原地左轉。
  • 關掉手把:X、車停。

常見問題

  • 按上卻往後? → 兩顆伺服都裝反:drive 裡 + left 改 - left、- right 改 + right。只有一輪反 → 只改那一行。
  • 按上卻原地轉? → 只有一邊反了,只改那一顆的正負號。
  • 放開還慢慢動? → 連續旋轉伺服的停止點不一定是 90,調伺服的微調螺絲或把 90 改 88~92。

範例 5:雙搖桿坦克+安全啟動(綜合)

這個範例會做什麼:左搖桿管左輪、右搖桿管右輪,推越多越快,一前一後原地轉。一開始要兩支搖桿都放開(在中間)才會「解鎖」,斷線就鎖回去,車子不會一開機就衝出去。按 A 顯示電量(PS2 手把恆 0)。

要準備什麼

  • 範例 4 的小車

怎麼接:同範例 4。

下載程式:ex05_tank_drive.ts(右鍵另存)→ MakeCode 新專案 → 齒輪 → 擴充 → 貼 https://github.com/contactmbcrobot/pxt-mbc-sensors → 右上切到 JavaScript → 全選刪掉原本的內容、把檔案內容貼上 → 下載,把 .hex 拖進 MICROBIT 磁碟。

程式

// 掌控者 PS2 × micro:bit 範例 5:雙搖桿坦克+安全啟動(綜合)
// 做什麼:左搖桿管左輪、右搖桿管右輪,推越多越快。一開始要兩支搖桿都放開(在中間)才會「解鎖」開車;斷線就鎖回去。按 A 顯示手把電量(PS2 手把沒有電量,恆 0)。
// 接線:同範例 4(接收器 P19/P20;左輪 P1、右輪 P2、伺服外接電池、共地)。
// 準備:兩輪小車。
// 看到什麼:放開兩支搖桿 → 打勾(解鎖);兩支都往前推 → 前進;一前一後 → 原地轉;放開 → 停;關手把 → X 並鎖住。

const DEAD = 15                                           // 死區:搖桿在 ±15 以內當成 0
let armed = false

// 左輪伺服 P1、右輪伺服 P2(連續旋轉伺服);left/right = −100~100,正 = 前進
function drive(left: number, right: number): void {
    left = Math.constrain(left, -100, 100)
    right = Math.constrain(right, -100, 100)
    pins.servoWritePin(AnalogPin.P1, Math.round(90 + left * 0.9))    // 90 = 停、180 = 全速前進、0 = 全速後退
    pins.servoWritePin(AnalogPin.P2, Math.round(90 - right * 0.9))   // 右輪裝的方向相反,所以用減的
}

function deadZone(v: number): number {                    // 搖桿在中間附近就當 0,放開手車子才會停
    if (Math.abs(v) < DEAD) {
        return 0
    }
    return v
}

input.onButtonPressed(Button.A, function () {
    basic.showNumber(mbc.padBattery())                    // 手把電量 0~100(PS2 手把恆 0)
})

basic.forever(function () {
    if (!mbc.padConnected()) {
        drive(0, 0)
        armed = false                                     // 斷線後要重新解鎖
        basic.showIcon(IconNames.No, 0)
        basic.pause(200)
        return
    }
    let ly = deadZone(mbc.padStick(MbcPadAxis.LeftY))     // 左搖桿上下 −100~+100
    let ry = deadZone(mbc.padStick(MbcPadAxis.RightY))    // 右搖桿上下
    if (!armed) {
        if (ly == 0 && ry == 0) {                         // 兩支都放開才解鎖
            armed = true
            basic.showIcon(IconNames.Yes, 0)
        }
        basic.pause(50)
        return
    }
    drive(ly, ry)                                         // 左搖桿 → 左輪、右搖桿 → 右輪
    basic.pause(20)
})

一步一步看懂程式

  1. DEAD = 15:死區。deadZone(v):搖桿在 ±15 以內就回傳 0,放開手車子才會真的停。
  2. forever:斷線 → 停車、armed = false、X。
  3. ly、ry = 左右搖桿上下,經過死區。
  4. !armed:兩支都是 0 才 armed = true、打勾;否則什麼都不做。
  5. 解鎖後 drive(ly, ry):左搖桿直接給左輪、右搖桿給右輪(−100~100 剛好是 drive 的範圍)。
  6. 按 A 顯示電量(PS2 手把沒有電量回報,永遠 0)。

跑起來應該看到什麼

  • 開機、手把連上:兩支搖桿放開 → 打勾。
  • 兩支都往前推:前進,推越多越快;左前右後:原地右轉;放開:停。
  • 關手把:X,再開要重新放開搖桿才解鎖。

常見問題

  • 一直沒打勾? → 搖桿沒回中(有偏移)。把 DEAD 改 25。
  • 太快不好控制? → drive(ly, ry) 改 drive(ly / 2, ry / 2)。
  • 想改成一支搖桿開車? → drive(ly + lx, ly − lx),lx 用 padStick(LeftX)。

下一步

其他問題

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

下載

本頁依據

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