Wii傳統手把和左手把一樣,都採用標準的I2C通訊協議,因此能輕易地和Arduino整合在一起。我購買的Wii傳統控制器是2006年推出的第一代,外型就像超級任天堂手把般的小巧,底下是和GameCube手把的對照:
任天堂後來在2009年推出手感與按鍵配置更佳的「Wii傳統手把Pro」版,兩者的控制訊號格式都一樣。
下圖是傳統手把的按鈕與接腳名稱:
因為Wii的控制器採用特殊的接頭,讀者可以購買「Wii手把延長線」來裁剪接頭,或者Wii連接器的專用PCB板,甚至改造舊的桌上型電腦介面卡,以便和Arduino相連。
下圖是筆者使用舊的電腦介面卡改造的Wii連接器外觀(請參閱《超圖解Arduino互動設計入門》11-19頁):
和左手把一樣,傳統手把的I2C位址也是0x52,每次也都會傳回6個位元組的資料,裡面包含類比搖桿和所有按鈕的狀態訊息,其數據格式如下:
位於肩部兩側的L和R,也是具備壓力感測的類比式按鈕(註:類比搖桿與類比按鈕的內部,各連接一個30K的可變電阻,內部照片和相關說明,請參閱WiiBrew.org的”Wiimote/Extension Controllers/Classic Controller“這篇文章說明);程式也能透過位元組4的第5和第1位元,讀取L和R鈕的開或關狀態(數位按鈕模式)。
左類比搖桿的資料長度是6個位元(可能值為十進位0~63),精確度比較高,右類比搖桿與L、R鍵的資料長度都是5個位元(可能值為十進位0~31)。筆者實際測試所得到的數值範圍如下:
Arduino的Wii傳統手把程式庫與程式範例
Tim Hirzel寫了一個Wii Classic Controller Arduino程式庫,請將網頁裡的程式複製到記事本,或者Arduino的程式編輯器中,並命名成“WiiClassic.h”(或按此連結下載),存入Arduino的Libraries路徑底下的“WiiClassic”資料夾:
底下的範例程式碼,可在「序列埠監控視窗」顯示所有數位按鈕的狀態:
#include "Wire.h"
#include "WiiClassic.h" // 引用Wii傳統手把的程式庫
WiiClassic wiiClassy = WiiClassic();
void setup() {
Wire.begin();
Serial.begin(9600);
wiiClassy.begin();
wiiClassy.update();
}
void loop() {
delay(100);
wiiClassy.update();
if (wiiClassy.leftShoulderPressed()) {
Serial.println("L"); // L被按下
}
if (wiiClassy.rightShoulderPressed()) {
Serial.println("R"); // R被按下
}
if (wiiClassy.lzPressed()) {
Serial.println("LZ"); // LZ被按下
}
if (wiiClassy.rzPressed()) {
Serial.println("RZ"); // RZ被按下
}
if (wiiClassy.leftDPressed()) {
Serial.println("LD"); // 十字左被按下
}
if (wiiClassy.rightDPressed()) {
Serial.println("RD"); // 十字右被按下
}
if (wiiClassy.upDPressed()) {
Serial.println("UD"); // 十字上被按下
}
if (wiiClassy.downDPressed()) {
Serial.println("DD"); // 十字下被按下
}
if (wiiClassy.selectPressed()) {
Serial.println("select"); // SELECT (-)被按下
}
if (wiiClassy.homePressed()) {
Serial.println("home."); // HOME被按下
}
if (wiiClassy.startPressed()) {
Serial.println("start."); // START (+)被按下
}
if (wiiClassy.xPressed()) {
Serial.println("x"); // x被按下
}
if (wiiClassy.yPressed()) {
Serial.println("y"); // y被按下
}
if (wiiClassy.aPressed()) {
Serial.println("a"); // a被按下
}
if (wiiClassy.bPressed()) {
Serial.println("b"); // b被按下
}
}
底下的範例程式碼,可在「序列埠監控視窗」顯示左類比搖桿的X, Y軸值:
#include "Wire.h"
#include "WiiClassic.h"
WiiClassic wiiClassy = WiiClassic();
void setup() {
Wire.begin();
Serial.begin(9600);
wiiClassy.begin();
wiiClassy.update();
}
void loop() {
delay(100);
wiiClassy.update();
Serial.print("x: ");
// 改成wiiClassy..rightStickX()可傳回右搖桿的x軸值
Serial.print(wiiClassy.leftStickX());
Serial.print("y: ");
// 改成wiiClassy..rightStickY()可傳回右搖桿的x軸值
Serial.println(wiiClassy.leftStickY());
Serial.println("------------------");
}
底下的範例程式碼,可在「序列埠監控視窗」顯示L和R的類比值:
#include "Wire.h"
#include "WiiClassic.h"
WiiClassic wiiClassy = WiiClassic();
void setup() {
Wire.begin();
Serial.begin(9600);
wiiClassy.begin();
wiiClassy.update();
}
void loop() {
delay(100);
wiiClassy.update();
Serial.print("L: ");
Serial.print(wiiClassy.leftShouldPressure());
Serial.print("R: ");
Serial.print(wiiClassy.rightShouldPressure());
Serial.println("------------------");
}
解析Wii手把資料的補充說明
傳統手把程式庫的程式碼,類似解析Wii左手把的程式庫,只是傳統手把的數據格式比較複雜一些。
從上文的Wii傳統手把數據表可得知,類比右搖桿的X軸值,分散在三個位元組。程式庫將接收到的6個位元組資料存入status陣列,因此,經過底下的運算步驟,即可獲得類比右搖桿的X軸數值:
實際的程式碼片段如下:
int rightStickX() {
return ((status[0] & (byte)0xc0) >> 3) + ((status[1] & (byte)0xc0) >> 5) + ((status[2] & (byte)0x80) >> 7);
}
以上的+運算,可用「邏輯或」(OR)代替(指令寫成一條豎線 | ):
int rightStickX() {
return ((status[0] & (byte)0xc0) >> 3) | ((status[1] & (byte)0xc0) >> 5) | ((status[2] & (byte)0x80) >> 7);
}
Hi 版主
請問,假設我要用單晶片跟wii手把做聯結
我想要手把按下什麼按鈕,單晶片的LCM就顯示什麼
問題來了,如果在這構想之下
那不就是單晶片要一直讀取手把的值
這樣程式不就很沒有效率?
hi scott:
我覺得還好,反正它開機也是閒著沒事。
若有必要,可以設置一個按鈕,按一下讓它睡眠或者喚醒它。
thanks,
jeffrey
不好意思,我用副廠pro搖桿可是完全讀不到,請問可能是什麼原因?
謝謝!!
Wii傳統手把和Wii左手把(nunchuk)的I2C位址都是0x52,為了方便對照與確認程式和接線,如果可能,你可以先用左手把測試看看。
have fun!
jeffrey
請問有沒有辦法改成USB接頭插電腦使用?謝謝
某些Arduino控制板,例如,採用Atmega32u4微控器的
Arduino Pro Micro和Leonardo,微控器本身具備USB埠,可程式化成各種USB裝置,包含遊戲控制器在內。Arduino IDE本身有內建一些範例程式。
thanks,
jeffrey
不好意思~您指的(桌上型電腦介面卡)是指顯示卡嗎?可以有詳細的作法解說甚至照片、圖解解說嗎?。我想在電腦上玩WII模擬器並使用WII傳統手把,雖然有其他手把可以用(例如仿PS的USB手把),但感覺就是差了一點,如果可以連接WII傳統手把就更好了~。有爬文說可以用WII傳統手把連接藍芽後就可以接電腦藍芽了,但我的藍芽已經使用在耳機上,WIN10一台電腦也只能連接一個藍芽設備,常常更換手把的電池也蠻麻煩的,又花錢又非常不環保,可以改成USB直接插在電腦上就好了~
Windows 10藍牙可支援多組設備同時連線,Wii很多遊戲都要使用「雙節棍」控制器操作,建議採用藍牙。
文章更新:「USB遊戲控制器(手把)DIY:使用Arduino Leonardo(李奧納多)控制板與Wii Classic經典手把」
thanks,
jeffrey