2019-07-02

Arduino 解析 PlayStation 手掣訊號

最近整理家中的物件時,找回一個 PlayStation One 手掣,想在電腦中使用
在下不打算購買轉接器,想自行改裝手掣,因此便開始學習了解電子訊號原理

資料搜集後,可以透迥 Arduino 獲得 PlayStation One 手掣 的訊號後,再傳送到電腦
在下購買一塊 Arduino UNO Rev 3 開始嘗試及學習了解電子工具
(一塊 Arduino UNO Rev 3 及其他配件大約 $300 左右,但一個 PlayStation 手掣 轉 USB Type-A 轉換器只需要 $30 ……)
甚麼是 Arduino 在下不在此詳細說明,可以到 Auduino官方網頁Arduino @ Wiki 了解

見下文
在下的 PlayStation 手掣 ,屬於 PlayStation One 的 DualShock 手掣 版本

引腳編排


見下文
1
2
3
4
5
6
7
8
9
PlayStation 手掣 共有 9支引腳 (Pin) ,圓角向下,從左起為第一引腳
(在下現在才發現在下的 PlayStation One 手掣沒有 第八引腳)

引腳功用


號碼顏色輸入輸出功能使用
1輸出Data必須
2輸入Command必須
37.0V ~ 9.0V 震動器 (震動手掣才有)選用
4接地線必須
53.3V 至 5.0V 電源線必須
6輸入Attention必須
7輸入Clock必須
8保留使用選用
9輸出Acknowledge選用
PlayStation 手掣雖然有 9支引腳,但主要使用 6支引腳便足夠運作
  • 電源線 (Power) - 接受 3.3V 至 5V 電源
  • 接地線 (Ground) - 電源回路
  • 資料 (Data) - 由手掣向目標發出的回應訊號,以 位元 為 單位,以 位元組 為 週期
  • 指令 (Command) - 由目標向手掣發出的指令訊號,以 位元 為 單位,以 位元組 為 週期
  • 關注 (Attention) - 由目標向手掣發出的控制訊號,控制 指令訊號 及 回應訊號 週期範圍
  • 定時 (Clock) - 由目標向手掣發出的控制訊號,控制 發出指令訊號 及 接收回應訊號 的狀態
其他引腳不連接亦不影響手掣基本運作

引腳訊號


引腳 初始化 指令訊號 及 回應訊號 週期
開始 位元組訊號 週期 完成 終止
指令訊號 位元 回應訊號 位元
att 高訊號 低訊號 高訊號
clk 高訊號 低訊號 高訊號
cmd 低訊號 高或低訊號
dat 高訊號 高或低訊號
Time 延遲16微秒 延遲2微秒 延遲2微秒 延遲16微秒 延遲16微秒
PlayStation 手掣 通過類似 週期 (Period) 的狀態 發出指令訊號 及 接收回應訊號,而且不同手掣亦會有些分別
在連接到主機前 PlayStation 手掣 會先發出 初始化 (Initialize) 的訊號,然後便會不斷執行 指令訊號及回應訊號 (Command and Response)
執行 指令與回應 前都會先發出 開始 (Start) 訊號,然後 延遲16微秒,在完成所有 位元組訊號 後,會發出 終止 (Stop) 訊號,再 延遲16微秒
位元組訊號 中,先 發出 指令訊號位元 (Command bit) ,延遲2微秒,然後會接收到 回應訊號位元 (Response bit) ,再延遲2微秒
由於 位元組 = 8個位元 ,因此一個完整的指令需要發出 8次指令訊號位元 並接收 8次回應訊號位元
將 8次回應訊號位元 整合成 位元組,才完成整個 位元組訊號
(1微秒 = 一百萬分之1秒)

指令及回應


編號 指令值 指令 回應值 回應
1 0x01 握手 (Handshake) 0xFF 連接 (Connect)
2 0x?? 操作 (Operation) 0x?? 手掣ID (Gamepad ID)
3 0x00 閒置 (Idle) 0x5A 準備 (Ready)
PlayStation 手掣 每次都會發出 3個位元組 標頭訊號
  • 握手 - 0x01
  • 操作 - 0x??
  • 閒置 - 0x00
並每個位元組訊號都會回應一個位元組
  • 已連接 - 0xFF
  • 手掣ID - 0x??
    • 標準手掣ID - 0x41
    • 類比手掣ID - 0x73
  • 已準備 - 0x5A

操作類型


指令值操作
0x40壓力感應按鈕 (Pressure Buttons)
0x42資料 (Data)
0x43設定 (Config)
0x44類比 (Analog)
0x4D震動 (Vibration)
0x4F壓力感應器 (Pressure Sensor)
第二個位元組訊號是區別操作類型
  • 壓力感應按鈕 - 設定需要啟動壓力感應的按鈕
  • 資料 - 回應手掣按鈕及轉軸訊號
  • 設定 - 控制手掣啟用或停止類比訊號、震動效果、壓力感應時,需要先啟動設定
  • 類比 - 設定啟用或停止類比訊號
  • 震動 - 設定啟用或停止震動效果
  • 壓力感應 - 設定啟用或停止壓力感應器

操作回應


手掣設定

編號指令回應
1握手連接
2設定手掣ID
3閒置準備
40x??0xFF
50x000xFF
60x000xFF
70x000xFF
80x000xFF
90x000xFF
100x000xFF
第4組位元組 設定 開啟關閉 設定狀態
  • 0x00 - 關閉
  • 0x01 - 開啟

類比設定

編號指令回應
1握手連接
2類比手掣ID
3閒置準備
40x??0xFF
50x??0xFF
60x000xFF
70x000xFF
80x000xFF
90x000xFF
100x000xFF
第4組位元組 設定 開啟關閉 設定狀態
  • 0x00 - 關閉
  • 0x01 - 開啟
第5組位元組 設定 鎖定不鎖定 狀態
  • 0x00 - 不鎖定
  • 0x03 - 鎖定

震動設定
編號指令回應
1握手連接
2震動手掣ID
3閒置準備
40x??0xFF
50x??0xFF
60xFF0xFF
70xFF0xFF
80xFF0xFF
90xFF0xFF
100xFF0xFF
第4組位元組 設定小震動器
  • 0xFF - 關閉
  • 0x00 - 開啟
第5組位元組 設定大震動器
  • 0xFF - 關閉
  • 0x01 - 開啟

壓力感應按鈕設定

編號指令回應
1握手連接
2壓力感應按鈕手掣ID
3閒置準備
40x??0xFF
50x??0xFF
60x000xFF
70x000xFF
80x000xFF
90x000xFF
100x000xFF
第4組位元組 設定需要設定壓力感應的按鈕 (有12個具備壓力感應的按鈕)
  • 0x00 - 右按鈕
  • 0x01 - 左按鈕
  • 0x02 - 上按鈕
  • 0x03 - 下按鈕
  • 0x04 - 三角按鈕
  • 0x05 - 圓圈按鈕
  • 0x06 - 交叉按鈕
  • 0x07 - 正方按鈕
  • 0x08 - L1按鈕
  • 0x09 - R1按鈕
  • 0x0A - L2按鈕
  • 0x0B - R2按鈕
第5組位元組 設定 開啟關閉 設定狀態
  • 0x00 - 關閉
  • 0x02 - 開啟

壓力感應設定

編號指令回應
1握手連接
2壓力感應器手掣ID
3閒置準備
40xFF0xFF
50xFF0xFF
60x??0xFF
70x000xFF
80x000xFF
90x000xFF
100x000xFF
第6組位元組 設定 開啟關閉 設定狀態
  • 0x00 - 關閉
  • 0x03 - 開啟
啟用 壓力感應設定 必須在 壓力感應按鈕設定 之後

手掣資料

編號指令回應
第0位元第1位元第2位元第3位元第4位元第5位元第6位元第7位元
1握手連接
2資料手掣ID
3閒置準備
4閒置SelectL3R3Start
5閒置L2R2L1R1三角圓圈交叉正方
6閒置右類比X轉軸數值,0x00 為最左 0xFF 為最右
7閒置右類比Y轉軸數值,0x00 為最上 0xFF 為最下
8閒置左類比X轉軸數值,0x00 為最左 0xFF 為最右
9閒置左類比Y轉軸數值,0x00 為最上 0xFF 為最下
10閒置右按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
11閒置左按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
12閒置上按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
13閒置下按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
14閒置三角按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
15閒置圓圈按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
16閒置交叉按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
17閒置正方按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
18閒置L1按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
19閒置R1按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
20閒置L2按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
21閒置R2按鈕壓力數值,0x00 為沒有按下 0xFF 為完全按下
標準手掣資料
原版 PlayStation 手掣 為例,完成 發出及接收3次位元組訊號 後,第4次及第5次位元組訊號 就是手掣按鈕的回應訊號
位元組訊號 是 十進制 0 至 255 (十六進制 0x00 至 0xFF) 之間的數值,以 二進制顯示 就是 00000000 至 11111111
每個二進制位值便是相對特定按鈕有否按下的狀態,沒有按下為 1 ,按下為 0
以 第4次位元組訊號 為例
  • Select 為 第0位元
  • L3 為 第1位元
  • R3 為 第2位元
  • Start 為 第3位元
  • 上 為 第4位元
  • 右 為 第5位元
  • 下 為 第6位元
  • 左 為 第7位元
由於 原版 PlayStation 手掣 沒有 L3 及 R3 ,因此無法按下,所以 L3 及 R3 的訊號必定是 1
如果同時按下 Start 及 Select ,回應的位元組訊號便會是 11110110 (二進制) 或 246 (十進制) 或 0xF6 (十六進制)
展示效果:
11110110
||||||||
|||||||>- Select (按下)
||||||>-- L3 (沒有按下)
|||||>--- R3 (沒有按下)
||||>---- Start (按下)
|||>----- 上 (沒有按下)
||>------ 右 (沒有按下)
|>------- 下 (沒有按下)
>-------- 左 (沒有按下)
第5次位元組訊號 都是以相同方法偵測按鈕有否按下的狀態

類比手掣資料

後期推出的 PlayStation 手掣 包含 L3 、 R3 、 左右類比操作,增加至 第6次至第9次位元組訊號
  • 第6次位元組訊號 指 右類比 的 X軸數值資料,越偏向左數值越接近 0 ,越偏向右數值越接近 255
  • 第7次位元組訊號 指 右類比 的 Y軸數值資料,越偏向上數值越接近 0 ,越偏向下數值越接近 255
  • 第8次位元組訊號 指 左類比 的 X軸數值資料,越偏向左數值越接近 0 ,越偏向右數值越接近 255
  • 第9次位元組訊號 指 左類比 的 Y軸數值資料,越偏向上數值越接近 0 ,越偏向下數值越接近 255
以 第6次位元組訊號 為例
如果沒有推動右類比,讓右類比置中,數值大約在 127 、 128 左右 (器材老化可能會有偏差,在下使用的手掣偏差值最大達到 25)
將右類比推向 最左會回應 0 ,最右會回應 255
第7次至第9次位元組訊號 都是以相同方法偵測其他轉軸數值
如果 以標準手掣測試類比轉軸數值,必定傳回 255

壓力感應手掣資料

再後期推出 PlayStation2 DualShock2 手掣還具備壓力感應按鈕,能感應按下的力度
第10次至第21次位元組訊 都是壓力感應的數值,沒有壓力感應的手掣,都會回應 255
啟動 類比操作 才能啟動 壓力感應器
  • 第10次位元組訊號 指 右按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第11次位元組訊號 指 左按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第12次位元組訊號 指 上按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第13次位元組訊號 指 下按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第14次位元組訊號 指 三角按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第15次位元組訊號 指 圓圈按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第16次位元組訊號 指 交叉按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第17次位元組訊號 指 正方按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第18次位元組訊號 指 L1按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第19次位元組訊號 指 R1按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第20次位元組訊號 指 L2按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255
  • 第21次位元組訊號 指 R2按鈕 的 壓力數值資料,沒有按下為 0 ,完全按下為 255

硬件連接


見下文
見下文
使用 跳線 (Jump Wire) 將 PlayStation 手掣引腳 接上

見下文
除了 Arduino 數碼引腳 (Digital Pin) 0, 1 外,數碼引腳 2 至 13 及 類比引腳 (Analog Pin) A0 至 A5 都能夠使用

見下文
見下文
見下文
PlayStation 手掣引腳Arduino引腳
12
23
4GND
53.3V
64
75
跳線另一端接駁到 Arduino 將會連接的引腳
(選用的引腳可以不連接)

硬件設置後,開始偏寫軟件編寫程式碼

Arduino IDE


使用由 Arduino 官方網站提供的 Arduino IDE 編程
可以到 https://www.arduino.cc/en/Main/Software 下載

見下文
見下文
在正式編寫程式碼前先設置正在使用的 Arduino型號Arduino連接埠
Tools > Board 選擇 Arduino型號
Tools > Port 選擇 Arduino連接埠

使用 Linux 的話,需要將使用者增加至 dialout 的群組中,讓使用者能存取 序列 (Serial) 操作

見下文
使用者及群組管理群組

見下文
選擇 dialout 群組後,按 屬性 (Properties)

見下文
群組成員 增加使用者到 dialout
* 修改系統資料需要使用 rootsuper user 帳戶 權限

使用指令亦可,在 Terminal 輸入
sudo usermod -a -G "dialout" "${USER}"

程式碼


先在全域區域宣告需要使用哪些引腳,方便追蹤程式碼及修改
const byte DAT_PIN = 2;
const byte CMD_PIN = 3;
const byte ATT_PIN = 4;
const byte CLK_PIN = 5;

void setup() { } 中設定
讓 Arduino 通過 序列埠 (Serial Port)115200 Baud 傳送資料
(可以選擇其他常用 Baud ,例如 9600, 19200, 38400 亦可)
根據 PlayStation 手掣引腳 的輸入輸出模式,設定 Arduino引腳 的輸入輸出模式
初始化 引腳訊號
Serial.begin(115200);
pinMode(DAT_PIN, INPUT);
pinMode(CMD_PIN, OUTPUT);
pinMode(ATT_PIN, OUTPUT);
pinMode(CLK_PIN, OUTPUT);
digitalWrite(DAT_PIN, HIGH);
digitalWrite(CMD_PIN, LOW);
digitalWrite(ATT_PIN, HIGH);
digitalWrite(CLK_PIN, HIGH);

根據位元組訊號編寫發出指令的功能方便重覆調用
const byte BIT_DELAY = 2;
const byte BYTE_DELAY = BIT_DELAY * 8;

byte sendCommand(byte command) {
    byte response = 0;
    for (byte i = 0; i < 8; i++) {
        const byte SHIFTED = 1 << i;
        digitalWrite(CLK_PIN, LOW);
        if ((command & SHIFTED) > 0) {
            digitalWrite(CMD_PIN, HIGH);
        } else {
            digitalWrite(CMD_PIN, LOW);
        }
        delayMicroseconds(BIT_DELAY);
        digitalWrite(CLK_PIN, HIGH);
        if (digitalRead(DAT_PIN) > LOW) {
            response |= SHIFTED;
        }
        delayMicroseconds(BIT_DELAY);
    }
    delayMicroseconds(BYTE_DELAY);
    return response;
}

void loop() { } 編寫程式讓 Arduino 不斷執行操作
digitalWrite(ATT_PIN, LOW);
delayMicroseconds(BYTE_DELAY);
sendCommand(0x01);
sendCommand(0x42);
sendCommand(0x00);
const byte BUTTON_SET_1 = sendCommand(0x00);
const byte BUTTON_SET_2 = sendCommand(0x00);
const byte RIGHT_X = sendCommand(0x00);
const byte RIGHT_Y = sendCommand(0x00);
const byte LEFT_X = sendCommand(0x00);
const byte LEFT_Y = sendCommand(0x00);
digitalWrite(ATT_PIN, HIGH);
delayMicroseconds(BYTE_DELAY);
char message[68] = "";
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x01) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x02) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x04) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x08) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x10) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x20) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x40) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_1 & 0x80) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x01) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x02) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x04) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x08) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x10) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x20) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x40) == 0);
sprintf(message, "%s%d, ", message, (BUTTON_SET_2 & 0x80) == 0);
sprintf(message, "%s%03d, ", message, LEFT_X);
sprintf(message, "%s%03d, ", message, LEFT_Y);
sprintf(message, "%s%03d, ", message, RIGHT_X);
sprintf(message, "%s%03d, ", message, RIGHT_Y);
Serial.println(message);
delay(16);

上載程式碼到 Arduino


見下文
Sketch ,按 Upload ,將程式碼上載到 Arduino

見下文
顯示 avrdude done. Thank you. 表示已經上載到 Arduino

見下文
Tools ,按 Monitor 監察序列
選擇與 Serial.begin 相同的 Buad 數值後,便可以正常顯示序列的內容
影片展示按下手掣按鈕及類比時,通常 Arduino 監察序列的功能讀取資料

// 開啟設定
digitalWrite(ATT_PIN, LOW);
delayMicroseconds(BYTE_DELAY);
sendCommand(0x01);
sendCommand(0x43);
sendCommand(0x00);
sendCommand(0x01); // 開啟設定指令
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
digitalWrite(ATT_PIN, HIGH);
delayMicroseconds(BYTE_DELAY);
 
// 開啟類比
digitalWrite(ATT_PIN, LOW);
delayMicroseconds(BYTE_DELAY);
sendCommand(0x01);
sendCommand(0x44);
sendCommand(0x00);
sendCommand(0x01); // 類比狀態, 0x00 為 關閉, 0x01 為開啟
sendCommand(0x03); // 狀態鎖定, 0x00 為 不鎖定, 0x03 為鎖定
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
digitalWrite(ATT_PIN, HIGH);
delayMicroseconds(BYTE_DELAY);
 
// 關閉設定
digitalWrite(ATT_PIN, LOW);
delayMicroseconds(BYTE_DELAY);
sendCommand(0x01);
sendCommand(0x43);
sendCommand(0x00);
sendCommand(0x00); // 關閉設定指令
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
digitalWrite(ATT_PIN, HIGH);
delayMicroseconds(BYTE_DELAY);

見下文
控制類比開關及鎖定
影片展示發出不同類比指令,啟動但不鎖定類比、閉關但不鎖定類比、開啟並鎖定類比 (在下沒有在影片展示閉關並鎖定類比)

// 加入需要壓力感應的按鈕
for (byte i = 0; i < 12; i++) {
    digitalWrite(ATT_PIN, LOW);
    delayMicroseconds(BYTE_DELAY);
    sendCommand(0x01);
    sendCommand(0x40);
    sendCommand(0x00);
    sendCommand(i); // 啟動需要壓力感應的按鈕
    sendCommand(0x02);
    sendCommand(0x00);
    sendCommand(0x00);
    sendCommand(0x00);
    sendCommand(0x00);
    sendCommand(0x00);
    digitalWrite(ATT_PIN, HIGH);
    delayMicroseconds(BYTE_DELAY);
}

// 啟動壓力感應器
digitalWrite(ATT_PIN, LOW);
delayMicroseconds(BYTE_DELAY);
sendCommand(0x01);
sendCommand(0x4F);
sendCommand(0x00);
sendCommand(0xFF);
sendCommand(0xFF);
sendCommand(0x03);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
sendCommand(0x00);
digitalWrite(ATT_PIN, HIGH);
delayMicroseconds(BYTE_DELAY);

見下文
啟動壓力感應器的設定
影片展示12個具備壓力感應的按鈕按下時的數值資料

見下文
在下為了測試震動器,購買了 9V電池接駁器9V電池

見下文
由於希望 不損壞接駁器 ,因此將 保護外彀卸下,露出金屬零件

見下文
使用鱷魚夾將接駁器的正負極接上
通常紅色線路為正極,黑色線路為負極
鱷魚夾的顏色只是方便展示正負極 ,若閣下沒有對色的鱷魚夾並沒有影響
若沒有鱷魚夾,使用萬字夾亦可,但要注意附近不要有易燃物或液體

見下文
連接鱷魚夾及跳線
注意:正極使用插頭插座跳線,負極使用雙插頭跳線

見下文
正極跳線連接到手掣第3引腳

見下文
負極跳線連接到 Arduino 另一個地接線引腳

// 啟動震動器
digitalWrite(ATT_PIN, LOW);
delayMicroseconds(BYTE_DELAY);
sendCommand(0x01);
sendCommand(0x4D);
sendCommand(0x00); // 小震動器設定,0xFF 為關閉, 0x00 為啟動
sendCommand(0x01); // 大震動器設定,0xFF 為關閉, 0x01 為啟動
sendCommand(0xFF);
sendCommand(0xFF);
sendCommand(0xFF);
sendCommand(0xFF);
sendCommand(0xFF);
sendCommand(0xFF);
digitalWrite(ATT_PIN, HIGH);
delayMicroseconds(BYTE_DELAY);
/*
其他程式碼
*/
sendCommand(0x01);
sendCommand(0x42);
sendCommand(0x00);
sendCommand(0xFF); // 啟用小震動器
sendCommand(0x40); // 以 0x40 啟用大震動器
/*
其他程式碼
*/

完成程式碼並上載到 Arduino 前,記得還要接上 9V電池

見下文
啟動震動器設定
影片展示小震動器及大震動器的驅動情況
小震動器 只能控制開啟或關閉 的設定
大震動器 能夠控制震動程度,範圍由 0x40 至 0xFF ,小於 0x40 則不會震動
注意:震動器放在硬質平台上啟用會非常噪吵,建議用布之類減震物品墊底以減低噪音

額外資料


見下文
見下文
見下文
使用 9V電池 能夠驅動 震動器後,在下嘗試使用 Arduino 提供的 5V 電源
5V 比 9V 低,測試失敗只是無法驅動震動器,並不是損壞震動器或 Arduino
因此直接將 手掣第3引腳 接駁到 Arduino 5V引腳
結果震動器能正常啟用,即是無需額外電源,只使用 Arduino 的電源已經足夠啟用手掣的震動器

在下將這個專案上載到 https://bitbucket.org/hkgoldenmra/playstationgamepad
https://create.arduino.cc/editor/hkgoldenmra/f3402f94-7eaf-443a-916c-19708f795aba/preview
有興趣可以透過 git
git clone "https://bitbucket.org/hkgoldenmra/playstationgamepad.git" --depth=1
下載、使用甚至改良

感想


在下最初都只是借解析 PlayStation 手掣為由,購買一塊 Arduino 嘗試接觸及學習電子知識
便開始尋找 Arduino 的資料,觀看在 Youtube 由 Arduino 創作人之一 Massimo Banzi 的 Arduino 入門教學
本來只係學習接駁電路,按 按鈕 後令 LED燈 發光,已經覺得很有趣,然後便學習 Arduino 的 AVR-C/C/C++ 的程式語言
之後便開始接駁電路到手掣,發覺完全不知如何整理,不懂看電路圖,不懂別人的 Arduino 函式庫,不懂手掣運作原理
抄別人的函式庫,跟著說明接駁引腳,但不知道有甚麼錯誤,網上尋找到的範例都是使用這個函式庫,但在下卻不能運作
再找到另一個函式庫,終於能夠運作,便慢慢由零開始理解函式庫內容
而註解資料太少,程式碼都是看不懂,最後還是從原始的電子訊號及其他手掣逆向工程文件開始理解
但文件內容仍然有很多不明確,例如網上有人指出使用 6V便可以驅動震動器,但又有人指出使用 9V會損壞震動器
最後在下還是使用鱷魚夾,直接將 9V電池 及 震動器 接駁並測試,幸好沒有損壞,最後在下發現使用 Arduino 的 5V 也可以驅動
現今有太多不明確不肯定的資訊,但可能全是錯誤,如果放棄思考,便會被誤導
需要由自己親身查證,不斷嘗試,才能找到答案

參考資料


沒有留言 :

張貼留言