How can we help you today?
【通訊】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 會以此位址作為識別進行配對。
核心功能說明
- 事件回呼機制 (Callback Functions):
attach(notify):這是一個極其高效的設計。每當搖桿狀態改變(如按下一顆按鈕),程式會立即執行notify()函式,您不需要在loop()中不斷查詢按鍵狀態,節省了大量 CPU 運算資源。attachOnConnect(onConnect):用於處理成功連線瞬間的動作。範例中結合了Buzzer類別,在連線成功時發出三次響聲,提供明確的非視覺化回饋。
- 多樣化的輸入判斷:
- 數位按鈕 (Digital Buttons):包含方向鍵、幾何鍵(△、□、O、X)及肩鍵(L1、R1)。回傳值為布林,非常適合用於控制噴氣、發射或切換模式。
- 類比搖桿 (Analog Sticks):提供左、右兩組搖桿的 X 與 Y 軸數值。數值範圍通常為 -128 到 127,適合用於馬達差速轉向控制(如前進速度與左右轉比率)。
- 線性類比按鈕:
- 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.
}
