Skip to main content
< All Topics
Print

【通訊】PS3搖桿 | PS3 GamePad

簡介


無線搖桿是賦予機器人「遠端控制」能力的靈魂。在現實生活中,這類技術廣泛應用於空拍機操控、水下探測機器人,甚至是現代戰場上的地面無人車。透過熟悉的遊戲控制器,我們能以直覺的搖桿推動與按鈕組合,遠距離傳達複雜指令。這不僅讓機器人的操作像玩遊戲一樣簡單有趣,更能讓使用者在安全的距離外,精準地指揮機器人執行偵查、搬運或競技等任務。

dual2s 函式庫整合了低功耗藍牙通訊技術,讓開發者能直接使用標準的 PS3 遊戲搖桿來控制機器人。透過事件驅動(Event-driven)的機制,當搖桿的按鍵被按下或類比搖桿位移時,系統會自動觸發對應的處理函式,大幅簡化了主迴圈(loop)的撰寫難度。本範例展示了如何設定連線回呼、讀取全按鍵狀態以及獲取精確的類比座標值。

技術規格與連線

  • 通訊協議:Bluetooth Classic。
  • 開發環境:ESP32 Arduino Core v3.3.5。
  • 配對機制:搖桿需先透過 PC 工具設定特定的 MAC 位址(範例中為 20:00:00:00:00:00),ESP32 會以此位址作為識別進行配對。

核心功能說明

  1. 事件回呼機制 (Callback Functions)
    • attach(notify):這是一個極其高效的設計。每當搖桿狀態改變(如按下一顆按鈕),程式會立即執行 notify() 函式,您不需要在 loop() 中不斷查詢按鍵狀態,節省了大量 CPU 運算資源。
    • attachOnConnect(onConnect):用於處理成功連線瞬間的動作。範例中結合了 Buzzer 類別,在連線成功時發出三次響聲,提供明確的非視覺化回饋。
  2. 多樣化的輸入判斷
    • 數位按鈕 (Digital Buttons):包含方向鍵、幾何鍵(△、□、O、X)及肩鍵(L1、R1)。回傳值為布林,非常適合用於控制噴氣、發射或切換模式。
    • 類比搖桿 (Analog Sticks):提供左、右兩組搖桿的 X 與 Y 軸數值。數值範圍通常為 -128 到 127,適合用於馬達差速轉向控制(如前進速度與左右轉比率)。
  3. 線性類比按鈕
    • PS3 搖桿的 L2 與 R2 支援壓力感應,能根據按下的深度回傳不同數值,這在控制機器人平穩加速時非常實用。

開發重點建議

  • MAC 位址同步:如果搖桿無法連線,請確認搖桿內部的 MAC 位址是否與程式碼中 Ps3.begin() 的位址完全一致。
  • 低延遲控制:由於採用事件回呼模式,請避免在 notify() 函式中加入過長的 delay(),以免造成操控延遲感。

dual2s控制器與環境


AI學伴


互動(1):基於函數庫 – dual2s

互動(2):基於範例程式

👉 你也可以在dual2s函數庫(./example/basic)中找到此範例程式。

/*=====================================================================================
yesio.net / 2026.03.12 / by nick
# Filename:08_PS3GamePad.ino
# Function:PS3搖桿使用範例 / Exampde code for PS3 GamePad.
# Toolchain & Libs:ESP32 Arduino Core v3.3.5 (ESP-IDF v5.1), dual2s
======================================================================================*/
#include <dual2s.h>

Buzzer bz(DUAL2S_HW::BUZZER);

void notify() {

    // 顯示按鍵狀態
    if (Ps3.data.button.cross)    Serial.println("按下:X 按鈕");
    if (Ps3.data.button.circle)   Serial.println("按下:O 按鈕");
    if (Ps3.data.button.triangle) Serial.println("按下:△ 按鈕");
    if (Ps3.data.button.square)   Serial.println("按下:□ 按鈕");

    if (Ps3.data.button.up)    Serial.println("按下:上鍵");
    if (Ps3.data.button.down)  Serial.println("按下:下鍵");
    if (Ps3.data.button.left)  Serial.println("按下:左鍵");
    if (Ps3.data.button.right) Serial.println("按下:右鍵");

    if (Ps3.data.button.l1) Serial.println("按下:L1 按鈕");
    if (Ps3.data.button.l2) Serial.println("按下:L2 按鈕");
    if (Ps3.data.button.r1) Serial.println("按下:R1 按鈕");
    if (Ps3.data.button.r2) Serial.println("按下:R2 按鈕");

    if (Ps3.data.button.select) Serial.println("按下:SELECT 按鈕");
    if (Ps3.data.button.start)  Serial.println("按下:START 按鈕");
    if (Ps3.data.button.ps)     Serial.println("按下:PS 按鈕");

    // 顯示搖桿數值
    Serial.printf("左搖桿 X: %d, Y: %d\n", Ps3.data.analog.stick.lx, Ps3.data.analog.stick.ly);
    Serial.printf("右搖桿 X: %d, Y: %d\n", Ps3.data.analog.stick.rx, Ps3.data.analog.stick.ry);

}

void onConnect() {
  //連線成功
  for(int i=0; i<3; i++){ bz.alarm(); delay(200);}

  Serial.println("PS3 控制器已連接!");
}

void setup() {
  Serial.begin(115200);
  bz.alarm();

  Ps3.attach(notify);              // 設定按鍵變更時的回呼函式
  Ps3.attachOnConnect(onConnect);  // 設定成功連線時的回呼函式
  Ps3.begin("20:00:00:00:00:00");  // 輸入你的搖桿位址
}

void loop() {
  //主程式區 ---------------------------------------
  //Develop your code here.
}
Table of Contents